test: revert Core.Net serialization; widen the virtual-clock harness patience instead
Some checks failed
CI / linux-portable (push) Successful in 3m21s
CI / windows-gate (push) Failing after 4m57s
CI / release (push) Has been skipped

Serializing AcDream.Core.Net.Tests to fix a Linux starvation REGRESSED Windows,
which had been green: Core.Net went from 1000 passed in 7 s (run 154) to
999/1000 in 17 s (run 155), taking down LossSoak_TwoPercentBidirectional_
ZeroMessageLoss_LedgersConverge, a test that had never failed. That trade trans-
ferred the flake between platforms rather than fixing anything, so it is
reverted: no xunit.runner.json, no csproj change.

The actual fragility is narrower than it looked — exactly ONE test uses
real-time waits (PausedSelector_SeededDroppedServerReady_RecoversOnIdleSweep),
and its harness drives a VIRTUAL clock while asserting on 2 s wall-clock
windows. Those windows are patience for background work, not part of the
assertion, and 2 s only ever encoded 'the machine is idle'. They now share a
60 s HarnessPatience constant.

Nothing about what the test verifies changes: recovery must still occur, a
genuine failure to NAK still fails, and a real hang is still bounded. Campaign N
transport code is untouched.

Local: 1000/1000 in 6 s under the gate filter.
This commit is contained in:
Erik 2026-08-19 13:59:42 +02:00
parent 03bcc1a41b
commit daf28bfec5
3 changed files with 16 additions and 19 deletions

View file

@ -22,15 +22,4 @@
<ProjectReference Include="..\..\src\AcDream.Core.Net\AcDream.Core.Net.csproj" />
</ItemGroup>
<ItemGroup>
<!-- Several transport tests drive a virtual clock but assert on REAL-time
waits (2 s SpinUntil windows). Under default parallelism on a small CI
container PausedSelector_SeededDroppedServerReady_RecoversOnIdleSweep
took 37-42 s and missed its window, while passing 5/5 in ~350 ms in
isolation on the same machine. Serialize the assembly rather than
loosen a Campaign N transport assertion. Same settings
AcDream.Core.Tests and AcDream.Launcher.Tests already use. -->
<None Update="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>

View file

@ -14,6 +14,13 @@ namespace AcDream.Core.Net.Tests.Transport;
/// </summary>
public sealed class FakeAceTransportTests
{
/// <summary>
/// Wall-clock allowance for background transport work in these
/// virtual-clock harnesses. Generous on purpose: it bounds a hang without
/// encoding an assumption that the machine is idle.
/// </summary>
private static readonly TimeSpan HarnessPatience = TimeSpan.FromSeconds(60);
// ---- LossyLink ----
[Fact]
@ -212,7 +219,14 @@ public sealed class FakeAceTransportTests
Task gapDriver = Task.Run(() =>
{
Assert.True(enterRequest.Wait(TimeSpan.FromSeconds(2)));
// These two windows are wall-clock patience for a harness whose
// CLOCK is virtual, not part of what the test verifies. Two
// seconds was enough on an idle dev box but not on a loaded CI
// runner, where this test took 37-42 s and failed while passing
// 5/5 in ~350 ms in isolation. Widening the window changes no
// assertion — recovery must still happen, and a genuine failure
// to NAK still fails the test, just later.
Assert.True(enterRequest.Wait(HarnessPatience));
// This later sequenced packet passes the seeded loss gate,
// exposing the missing ServerReady and parking behind it.
fake.EnqueueServerGameMessage(
@ -220,7 +234,7 @@ public sealed class FakeAceTransportTests
GameMessageGroup.UIQueue);
Assert.True(SpinWait.SpinUntil(
() => session.Transport?.Inbound.NakCount > 0,
TimeSpan.FromSeconds(2)));
HarnessPatience));
// No datagram follows this virtual-time edge. Recovery now
// requires paused EnterWorld's independent periodic sweep.

View file

@ -1,6 +0,0 @@
{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"parallelizeAssembly": false,
"parallelizeTestCollections": false,
"maxParallelThreads": 1
}