117 lines
3.7 KiB
C#
117 lines
3.7 KiB
C#
using System.Diagnostics;
|
|
using System.Text.Json;
|
|
using System.Runtime.CompilerServices;
|
|
using Xunit;
|
|
|
|
namespace DevTool.Tests;
|
|
|
|
public sealed class DevShellScriptTests
|
|
{
|
|
[Theory]
|
|
[InlineData("pwsh")]
|
|
[InlineData("bash")]
|
|
[InlineData("zsh")]
|
|
[InlineData("cmd")]
|
|
public async Task DevShellExport_ReturnsSuccess_ForSupportedShells(string shell)
|
|
{
|
|
var python = ResolvePython();
|
|
var result = await RunAsync(
|
|
python,
|
|
["scripts/dev_shell.py", "export", "--shell", shell, "--json"]);
|
|
|
|
Assert.Equal(0, result.ExitCode);
|
|
using var doc = JsonDocument.Parse(result.StdOut);
|
|
Assert.True(doc.RootElement.TryGetProperty("projectRoot", out _));
|
|
Assert.True(doc.RootElement.TryGetProperty("env", out _));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DevShellExport_InvalidShell_ReturnsExitCode3()
|
|
{
|
|
var python = ResolvePython();
|
|
var result = await RunAsync(
|
|
python,
|
|
["scripts/dev_shell.py", "export", "--shell", "fish"]);
|
|
|
|
Assert.Equal(3, result.ExitCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DevShellDoctor_ReturnsJson()
|
|
{
|
|
var python = ResolvePython();
|
|
var result = await RunAsync(
|
|
python,
|
|
["scripts/dev_shell.py", "doctor"]);
|
|
|
|
Assert.Equal(0, result.ExitCode);
|
|
using var doc = JsonDocument.Parse(result.StdOut);
|
|
Assert.True(doc.RootElement.TryGetProperty("repo_root", out _));
|
|
}
|
|
|
|
private static string ResolvePython()
|
|
{
|
|
var candidates = OperatingSystem.IsWindows()
|
|
? new[] { "python", "py" }
|
|
: new[] { "python3", "python" };
|
|
|
|
foreach (var candidate in candidates)
|
|
{
|
|
try
|
|
{
|
|
using var process = new Process
|
|
{
|
|
StartInfo = new ProcessStartInfo
|
|
{
|
|
FileName = candidate,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
}
|
|
};
|
|
process.StartInfo.ArgumentList.Add("--version");
|
|
process.Start();
|
|
process.WaitForExit(2000);
|
|
if (process.ExitCode == 0)
|
|
return candidate;
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
throw new InvalidOperationException("Python executable not found.");
|
|
}
|
|
|
|
private static async Task<(int ExitCode, string StdOut, string StdErr)> RunAsync(string command, IReadOnlyList<string> args)
|
|
{
|
|
var psi = new ProcessStartInfo
|
|
{
|
|
FileName = command,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true,
|
|
WorkingDirectory = RepoRoot(),
|
|
};
|
|
foreach (var arg in args)
|
|
psi.ArgumentList.Add(arg);
|
|
|
|
using var process = new Process { StartInfo = psi };
|
|
process.Start();
|
|
var stdout = await process.StandardOutput.ReadToEndAsync();
|
|
var stderr = await process.StandardError.ReadToEndAsync();
|
|
await process.WaitForExitAsync();
|
|
return (process.ExitCode, stdout, stderr);
|
|
}
|
|
|
|
private static string RepoRoot([CallerFilePath] string file = "")
|
|
{
|
|
var repoRoot = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(file)!, "..", ".."));
|
|
if (!File.Exists(Path.Combine(repoRoot, "scripts", "dev_shell.py")))
|
|
throw new InvalidOperationException("Could not locate repo root.");
|
|
return repoRoot;
|
|
}
|
|
}
|