Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/MeshWeaver.Fixture/HubFactAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,30 @@ namespace MeshWeaver.Fixture;
public class HubFactAttribute : FactAttribute;
#else
/// <summary>
/// Marks a hub test method. In non-DEBUG builds a 5 second timeout is applied
/// so that a wedged hub fails the test fast instead of hanging the run.
/// Marks a hub test method. In non-DEBUG builds a timeout is applied so that a wedged hub fails
/// the test instead of hanging the run.
///
/// <para>🚨 The budget must exceed what the MESH FIXTURE costs on a loaded CI runner, or the test
/// measures the runner instead of the code. It was 5s, and 5s is not achievable there: a CI log for
/// <c>MeshNodeVersionSyncTest</c> (2026-07-27) shows class init at 19:59:22.595 and dispose at
/// 19:59:30.720 — <b>8.1s of fixture</b> before the body runs at all. That produced a recurring
/// main-red flake with no defect behind it, and the same trap bit a heartbeat test written the same
/// night ("Test execution timed out after 5000 milliseconds", passing locally where no budget is
/// enforced).</para>
///
/// <para>30s matches the runner-wide <c>methodTimeout</c> and still fails a genuine wedge well
/// before the run hangs — a wedged read surfaces its own <c>GetMeshNode … timed out after 60.0s</c>
/// first, so nothing is masked by the larger budget.</para>
Comment on lines +24 to +26
/// </summary>
public sealed class HubFactAttribute : FactAttribute
{
/// <summary>
/// Initializes a new instance and sets the test timeout to 5000 milliseconds.
/// Initializes a new instance and sets the test timeout to 30000 milliseconds — above the
/// measured CI fixture cost, in line with the runner-wide <c>methodTimeout</c>.
/// </summary>
public HubFactAttribute()
{
Timeout = 5000;
Timeout = 30000;
}
};
#endif
6 changes: 3 additions & 3 deletions test/MeshWeaver.Persistence.Test/MeshNodeVersionSyncTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public override async ValueTask DisposeAsync()
}
}

[Fact(Timeout = 10000)]
[Fact(Timeout = 30000)]
public async Task MeshNode_InitialVersion_IsZero()
{
// Arrange - check initial version via the authoritative owner-hub read
Expand All @@ -201,7 +201,7 @@ public async Task MeshNode_InitialVersion_IsZero()
initialNode!.Version.Should().Be(0, "initial version should be 0");
}

[Fact(Timeout = 10000)]
[Fact(Timeout = 30000)]
public async Task MeshNode_VersionProperty_CanBeSetAndPersisted()
{
// Arrange - create a node with a specific version. Use a built-in
Expand All @@ -227,7 +227,7 @@ public async Task MeshNode_VersionProperty_CanBeSetAndPersisted()
savedNode!.Version.Should().Be(42, "version should be preserved in persistence");
}

[Fact(Timeout = 10000)]
[Fact(Timeout = 30000)]
public void MessageHub_HasSetInitialVersionMethod()
{
// Verify that IMessageHub interface has the SetInitialVersion method
Expand Down
Loading