Git/GitIdentity/Port/WriteAccess and Claude CLI/Version/Auth/PermissionModeAuto checks plus the ExecutableResolver they depend on were built in two sibling task branches that hadn't landed on main yet. Vendored the finished files in from those branches (same content, verified building + tests green) so the SystemCheckPage task has something to consume.
128 lines
3.9 KiB
C#
128 lines
3.9 KiB
C#
using ClaudeDo.Data.Environment;
|
|
|
|
namespace ClaudeDo.Data.Tests;
|
|
|
|
public sealed class ExecutableResolverTests : IDisposable
|
|
{
|
|
private readonly string _root;
|
|
|
|
public ExecutableResolverTests()
|
|
{
|
|
_root = Path.Combine(Path.GetTempPath(), $"claudedo_exeresolve_{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(_root);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
try { Directory.Delete(_root, recursive: true); } catch { }
|
|
}
|
|
|
|
private string MakeDir(string name)
|
|
{
|
|
var dir = Path.Combine(_root, name);
|
|
Directory.CreateDirectory(dir);
|
|
return dir;
|
|
}
|
|
|
|
private static void Touch(string path) => File.WriteAllText(path, "");
|
|
|
|
[Fact]
|
|
public void Command_with_directory_separator_is_treated_as_path()
|
|
{
|
|
var dir = MakeDir("bin1");
|
|
var exePath = Path.Combine(dir, "myclaude.exe");
|
|
Touch(exePath);
|
|
|
|
var result = ExecutableResolver.Resolve(exePath, pathOverride: "C:\\does\\not\\matter");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(exePath, result!.Path);
|
|
Assert.False(result.IsShim);
|
|
}
|
|
|
|
[Fact]
|
|
public void Path_like_command_without_extension_resolves_via_pathext()
|
|
{
|
|
var dir = MakeDir("bin2");
|
|
var cmdPath = Path.Combine(dir, "myclaude.cmd");
|
|
Touch(cmdPath);
|
|
var commandWithoutExt = Path.Combine(dir, "myclaude");
|
|
|
|
var result = ExecutableResolver.Resolve(commandWithoutExt, pathExtOverride: ".com;.exe;.bat;.cmd");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(cmdPath, result!.Path);
|
|
Assert.True(result.IsShim);
|
|
}
|
|
|
|
[Fact]
|
|
public void Cmd_file_in_path_is_found_when_no_exe_exists()
|
|
{
|
|
var dir = MakeDir("bin3");
|
|
Touch(Path.Combine(dir, "claude.cmd"));
|
|
|
|
var result = ExecutableResolver.Resolve("claude", pathOverride: dir, pathExtOverride: ".com;.exe;.bat;.cmd");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(Path.Combine(dir, "claude.cmd"), result!.Path);
|
|
Assert.True(result.IsShim);
|
|
}
|
|
|
|
[Fact]
|
|
public void Exe_wins_against_cmd_in_same_directory()
|
|
{
|
|
var dir = MakeDir("bin4");
|
|
Touch(Path.Combine(dir, "claude.cmd"));
|
|
Touch(Path.Combine(dir, "claude.exe"));
|
|
|
|
var result = ExecutableResolver.Resolve("claude", pathOverride: dir, pathExtOverride: ".com;.exe;.bat;.cmd");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(Path.Combine(dir, "claude.exe"), result!.Path);
|
|
Assert.False(result.IsShim);
|
|
}
|
|
|
|
[Fact]
|
|
public void Directory_order_in_path_is_respected()
|
|
{
|
|
var dir1 = MakeDir("bin5a");
|
|
var dir2 = MakeDir("bin5b");
|
|
Touch(Path.Combine(dir1, "claude.cmd"));
|
|
Touch(Path.Combine(dir2, "claude.exe"));
|
|
|
|
var pathOverride = $"{dir1}{Path.PathSeparator}{dir2}";
|
|
var result = ExecutableResolver.Resolve("claude", pathOverride: pathOverride, pathExtOverride: ".com;.exe;.bat;.cmd");
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Equal(Path.Combine(dir1, "claude.cmd"), result!.Path);
|
|
Assert.True(result.IsShim);
|
|
}
|
|
|
|
[Fact]
|
|
public void Unresolvable_command_returns_null()
|
|
{
|
|
var dir = MakeDir("bin6");
|
|
|
|
var result = ExecutableResolver.Resolve(
|
|
"claudedo_totally_missing_cmd_9f3a1",
|
|
pathOverride: dir,
|
|
pathExtOverride: ".com;.exe;.bat;.cmd");
|
|
|
|
Assert.Null(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void BuildShimStartInfo_uses_cmd_exe_and_quotes_paths_with_spaces()
|
|
{
|
|
const string shimPath = @"C:\Program Files\claude\claude.cmd";
|
|
|
|
var startInfo = ExecutableResolver.BuildShimStartInfo(shimPath, new[] { "--version", "arg2" });
|
|
|
|
Assert.Equal("cmd.exe", startInfo.FileName);
|
|
Assert.Contains("/c", startInfo.Arguments);
|
|
Assert.Contains($"\"{shimPath}\"", startInfo.Arguments);
|
|
Assert.Contains("--version", startInfo.Arguments);
|
|
Assert.Contains("arg2", startInfo.Arguments);
|
|
}
|
|
}
|