fix(ablegacy): wire the authored probeTimeoutSeconds into Test Connect

Dead config field (user decision: wire them all): the AdminUI form authors
probeTimeoutSeconds ("Admin UI probe timeout", default 5) but AbLegacyDriverProbe
never read it, so Test Connect always ran on the caller's budget. It now
tightens that budget (never raises it), the same rule as the Galaxy probe; a
non-positive value keeps the caller's budget.

Refs #738
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
Joseph Doherty
2026-10-22 14:43:23 -04:00
parent 582e82899b
commit 66927a3faa
2 changed files with 54 additions and 0 deletions
@@ -192,6 +192,40 @@ public sealed class AbLegacyDriverProbeTests
LibplctagLegacyName.Translate(status!).ShouldBe("S2:0");
}
private sealed class StallingTag(AbLegacyTagCreateParams p) : FakeAbLegacyTag(p)
{
public override Task InitializeAsync(CancellationToken ct) => Task.Delay(Timeout.Infinite, ct);
}
/// <summary>
/// The authored <c>probeTimeoutSeconds</c> ("Admin UI probe timeout") was parsed by nothing — Test Connect ran
/// on the caller's budget alone. It now tightens that budget (never raises it); absent or non-positive keeps
/// the caller's budget (the positive control).
/// </summary>
[Theory]
[InlineData(",\"probeTimeoutSeconds\":1", "1s")]
[InlineData(",\"probeTimeoutSeconds\":30", "2s")]
[InlineData("", "2s")]
[InlineData(",\"probeTimeoutSeconds\":0", "2s")]
public async Task Configured_probe_timeout_tightens_the_caller_budget(string key, string expectedBudget)
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
try
{
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
var factory = new FakeAbLegacyTagFactory { Customise = p => new StallingTag(p) };
var json = $"{{\"devices\":[{{\"hostAddress\":\"ab://127.0.0.1:{port}/1,0\"}}]{key}}}";
var result = await new AbLegacyDriverProbe(factory)
.ProbeAsync(json, TimeSpan.FromSeconds(2), TestContext.Current.CancellationToken);
result.Ok.ShouldBeFalse();
result.Message.ShouldBe($"Probe timed out after {expectedBudget}.");
}
finally { listener.Stop(); }
}
[Fact]
public async Task Unparseable_probe_address_is_a_clean_failure_not_an_exception()
{