fix(worker-tests): decouple FakeRuntimeSession dispatch safety-net from the inspection window
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m13s
ci / java (push) Successful in 2m26s
ci / portable (push) Failing after 4m56s

The BlockDispatch branch waited 5 real seconds and then proceeded regardless — it does not
branch on the wait's result. The long-in-flight test's inspection loop is bounded by
elapsed time and a frame floor, so on a loaded box (the documented 4-5x slowdown class) it
can plausibly outrun that 5 s. When it does, the reply is emitted mid-window,
AssertNotWorkerFault waves it past, and the reply leg then waits for a reply already gone
by — failing at the 20 s cancellation with no message, on exactly the loaded-box run the
widened windows exist to survive.

The wait is a pure safety net: nothing asserts on it firing, and every test that blocks
dispatch releases it explicitly (ReleaseDispatch, or a WorkerShutdown envelope, both of
which Set the event) — none reaches the timeout on a healthy run. Named it
BlockedDispatchSafetyNet and raised it to 30 s, above any window a test opens and above the
20 s cancellation those tests arm, so a wedged test always fails on its own token with its
own message. Dispose still releases the wait, so teardown never waits on it either.

Inline rationale in the test now states the decoupling and what a close pairing would cost,
rather than asserting the window stays inside a 5 s ceiling. Nothing else changed.
This commit is contained in:
Joseph Doherty
2026-08-18 07:08:47 -04:00
parent bc22792a36
commit aaeb86b132
2 changed files with 18 additions and 4 deletions
@@ -20,6 +20,17 @@ namespace ZB.MOM.WW.MxGateway.Worker.Tests.TestSupport;
/// </summary>
internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
{
/// <summary>
/// Backstop on the <see cref="BlockDispatch"/> wait so a test that never releases leaves no
/// thread parked forever. It is a safety net, never a scenario's timing budget: nothing
/// asserts on it firing, and a test whose blocked window outruns it silently gets its reply
/// mid-window, which then fails as an opaque cancellation somewhere later. Kept far above
/// any test's window — and above the 20 s cancellation those tests arm — so the test's own
/// token always fails first, with its own message. <see cref="Dispose"/> releases the wait
/// regardless, so teardown never depends on this elapsing.
/// </summary>
private static readonly TimeSpan BlockedDispatchSafetyNet = TimeSpan.FromSeconds(30);
private readonly ManualResetEventSlim releaseDispatch = new(false);
private readonly object gate = new();
private readonly Queue<WorkerEvent> events = new();
@@ -91,7 +102,7 @@ internal sealed class FakeRuntimeSession : IWorkerRuntimeSession
if (BlockDispatch)
{
releaseDispatch.Wait(TimeSpan.FromSeconds(5));
releaseDispatch.Wait(BlockedDispatchSafetyNet);
}
SetSnapshot(new WorkerRuntimeHeartbeatSnapshot(