test(dcl): strengthen DCL002 derace — 30s AwaitCondition + non-parallel collection for full-suite load (#234)

This commit is contained in:
Joseph Doherty
2026-06-19 01:04:36 -04:00
parent 6a4c9a85b8
commit 78360eb6a7
2 changed files with 15 additions and 2 deletions
@@ -0,0 +1,12 @@
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests;
/// <summary>
/// Marks DataConnectionManagerActorTests as non-parallel with any other tests in the
/// same collection. This prevents CPU-contention-induced timing flakiness in DCL002
/// (and neighbours) where actor message dispatch + async I/O must complete before an
/// AwaitCondition deadline. xUnit runs all tests in the same [Collection] sequentially
/// within the assembly; the generous 30 s AwaitCondition ceiling handles cross-assembly
/// contention when the full solution test suite runs in parallel.
/// </summary>
[CollectionDefinition("DataConnectionManagerActor", DisableParallelization = true)]
public class DataConnectionManagerActorCollection { }
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests;
/// <summary> /// <summary>
/// WP-34: Tests for DataConnectionManagerActor routing and lifecycle. /// WP-34: Tests for DataConnectionManagerActor routing and lifecycle.
/// </summary> /// </summary>
[Collection("DataConnectionManagerActor")]
public class DataConnectionManagerActorTests : TestKit public class DataConnectionManagerActorTests : TestKit
{ {
private readonly IDataConnectionFactory _mockFactory; private readonly IDataConnectionFactory _mockFactory;
@@ -108,7 +109,7 @@ public class DataConnectionManagerActorTests : TestKit
// completes under CPU contention. // completes under CPU contention.
AwaitCondition( AwaitCondition(
() => mockAdapter.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ConnectAsync"), () => mockAdapter.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "ConnectAsync"),
TimeSpan.FromSeconds(5)); TimeSpan.FromSeconds(30));
// Register a subscription. // Register a subscription.
manager.Tell(new SubscribeTagsRequest("c1", "inst1", "conn1", ["tag1"], DateTimeOffset.UtcNow)); manager.Tell(new SubscribeTagsRequest("c1", "inst1", "conn1", ["tag1"], DateTimeOffset.UtcNow));
@@ -122,7 +123,7 @@ public class DataConnectionManagerActorTests : TestKit
// actor processes the message under CPU load. // actor processes the message under CPU load.
AwaitCondition( AwaitCondition(
() => mockAdapter.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "WriteAsync"), () => mockAdapter.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "WriteAsync"),
TimeSpan.FromSeconds(5)); TimeSpan.FromSeconds(30));
// After the crash the subscription state must survive: the health report // After the crash the subscription state must survive: the health report
// still shows the subscribed/resolved tag. With Restart it would be 0. // still shows the subscribed/resolved tag. With Restart it would be 0.