test(flaky): decouple fake-worker CreateAsync anti-hang net from the semantic timeout
The nightly (run #47) portable job failed CreateAsync_WhenFakeWorkerNeverSendsReady _TimesOutAndKillsWorker: it asserts the factory's TimeoutException carries 'did not complete startup' (thrown at the session's 1s startup timeout), but the test's .WaitAsync(TestTimeout=5s) anti-hang net tripped first under CI load and surfaced .NET's generic 'The operation has timed out.' — same commit passed on the push run (#46), so it's a load-sensitive timeout race, not a regression. Raising runner capacity to 4 makes concurrent-load flakes like this more likely. Fix: give the two CreateAsync failure/timeout tests a dedicated 30s HangGuardTimeout, far above the 1s semantic timeout under test, so the factory's own exception is always the one observed. The net still catches a genuine hang. Note: this class cannot run on macOS (named pipes -> Unix domain sockets fail on the pipe path); verification is via CI Linux.
This commit is contained in:
+9
-2
@@ -15,6 +15,13 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
|
||||
{
|
||||
private static readonly TimeSpan TestTimeout = TimeSpan.FromSeconds(5);
|
||||
|
||||
// Anti-hang guard for the CreateAsync failure/timeout tests. It only exists to stop a genuine
|
||||
// hang from wedging the run, so it must be far larger than any in-test semantic timeout (the
|
||||
// factory startup timeout being exercised) — otherwise, under CI load, this WaitAsync net can
|
||||
// trip before the factory's own timeout propagates and the test observes .NET's generic
|
||||
// "The operation has timed out." instead of the asserted "did not complete startup".
|
||||
private static readonly TimeSpan HangGuardTimeout = TimeSpan.FromSeconds(30);
|
||||
|
||||
private readonly List<IWorkerTaskLauncher> _launchers = [];
|
||||
|
||||
/// <summary>
|
||||
@@ -79,7 +86,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
|
||||
GatewaySession session = CreateSession();
|
||||
|
||||
WorkerClientException exception = await Assert.ThrowsAsync<WorkerClientException>(
|
||||
async () => await factory.CreateAsync(session, CancellationToken.None).WaitAsync(TestTimeout));
|
||||
async () => await factory.CreateAsync(session, CancellationToken.None).WaitAsync(HangGuardTimeout));
|
||||
|
||||
Assert.Equal(WorkerClientErrorCode.ProtocolViolation, exception.ErrorCode);
|
||||
Assert.True(launcher.Process.IsDisposed);
|
||||
@@ -100,7 +107,7 @@ public sealed class SessionWorkerClientFactoryFakeWorkerTests : IAsyncDisposable
|
||||
GatewaySession session = CreateSession(startupTimeout: TimeSpan.FromSeconds(1));
|
||||
|
||||
TimeoutException exception = await Assert.ThrowsAsync<TimeoutException>(
|
||||
async () => await factory.CreateAsync(session, CancellationToken.None).WaitAsync(TestTimeout));
|
||||
async () => await factory.CreateAsync(session, CancellationToken.None).WaitAsync(HangGuardTimeout));
|
||||
|
||||
Assert.Contains("did not complete startup", exception.Message);
|
||||
Assert.Equal(1, launcher.Process.KillCount);
|
||||
|
||||
Reference in New Issue
Block a user