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.
69 lines
2.3 KiB
C#
69 lines
2.3 KiB
C#
using System.Net;
|
|
using System.Net.Sockets;
|
|
using ClaudeDo.Installer.Checks;
|
|
using ClaudeDo.Installer.Checks.Interfaces;
|
|
using ClaudeDo.Installer.Core;
|
|
|
|
namespace ClaudeDo.Installer.Tests.Checks;
|
|
|
|
public sealed class PortCheckTests
|
|
{
|
|
private sealed class FakeOwnerResolver : IPortOwnerResolver
|
|
{
|
|
private readonly string? _owner;
|
|
public FakeOwnerResolver(string? owner) => _owner = owner;
|
|
public Task<string?> FindOwningProcessNameAsync(int port, CancellationToken ct) => Task.FromResult(_owner);
|
|
}
|
|
|
|
private static int GetFreePort()
|
|
{
|
|
var listener = new TcpListener(IPAddress.Loopback, 0);
|
|
listener.Start();
|
|
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
listener.Stop();
|
|
return port;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Both_ports_free_reports_ok()
|
|
{
|
|
var ctx = new InstallContext { SignalRPort = GetFreePort(), ExternalMcpPort = GetFreePort() };
|
|
var check = new PortCheck(new FakeOwnerResolver(null));
|
|
|
|
var result = await check.RunAsync(ctx, CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Ok, result.Status);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Port_in_use_by_other_process_reports_failed()
|
|
{
|
|
var port = GetFreePort();
|
|
using var occupying = new TcpListener(IPAddress.Loopback, port);
|
|
occupying.Start();
|
|
var ctx = new InstallContext { SignalRPort = port, ExternalMcpPort = GetFreePort() };
|
|
var check = new PortCheck(new FakeOwnerResolver("SomeOtherApp"));
|
|
|
|
var result = await check.RunAsync(ctx, CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Failed, result.Status);
|
|
Assert.Equal(CheckSeverity.Warning, result.Severity);
|
|
Assert.Contains("SomeOtherApp", result.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Port_in_use_by_own_worker_reports_ok()
|
|
{
|
|
var port = GetFreePort();
|
|
using var occupying = new TcpListener(IPAddress.Loopback, port);
|
|
occupying.Start();
|
|
var ctx = new InstallContext { SignalRPort = port, ExternalMcpPort = GetFreePort() };
|
|
var check = new PortCheck(new FakeOwnerResolver("ClaudeDo.Worker"));
|
|
|
|
var result = await check.RunAsync(ctx, CancellationToken.None);
|
|
|
|
Assert.Equal(CheckStatus.Ok, result.Status);
|
|
Assert.Contains("ClaudeDo Worker", result.Message);
|
|
}
|
|
}
|