diff --git a/Directory.Packages.props b/Directory.Packages.props
index 4b8205137..272995401 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -13,7 +13,7 @@
-
+
@@ -212,13 +212,10 @@
Avalonia.X11 (Linux desktop). Pin to the patched 0.21.3 in the same 0.x line.
Applied via a direct PackageReference in the consuming desktop project(s). -->
-
-
+
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorMailboxTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorMailboxTests.cs
index 95a2b0fc7..2d14b2c09 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorMailboxTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorMailboxTests.cs
@@ -33,16 +33,16 @@ public sealed class AdminOperationsActorMailboxTests : ControlPlaneActorTestBase
var connectClient = CreateTestProbe("connect-client");
connectClient.Send(actor, new TestDriverConnect("Blocking", "{}", TimeoutSeconds: 60, Guid.NewGuid()));
- probe.Started.Wait(PresenceBudget).ShouldBeTrue("the probe must be in flight before the ack is sent");
+ probe.Started.Wait(PresenceBudget, TestContext.Current.CancellationToken).ShouldBeTrue("the probe must be in flight before the ack is sent");
actor.Tell(new AcknowledgeAlarmCommand("alarm-1", "op", null, CorrelationId.NewId()));
- var ack = ExpectMsg(AckBudget);
+ var ack = ExpectMsg(AckBudget, cancellationToken: TestContext.Current.CancellationToken);
ack.Ok.ShouldBeTrue();
// Positive control: the probe reply still lands, with the right sender, once the probe returns.
- connectClient.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+ connectClient.ExpectNoMsg(TimeSpan.FromMilliseconds(200), TestContext.Current.CancellationToken);
probe.Release(new DriverProbeResult(true, null, TimeSpan.FromMilliseconds(5)));
- var result = connectClient.ExpectMsg(PresenceBudget);
+ var result = connectClient.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
result.Ok.ShouldBeTrue();
result.LatencyMs.ShouldNotBeNull();
}
@@ -58,7 +58,7 @@ public sealed class AdminOperationsActorMailboxTests : ControlPlaneActorTestBase
actor.Tell(new TestDriverConnect("Blocking", "{}", TimeoutSeconds: 1, Guid.NewGuid()));
- var result = ExpectMsg(PresenceBudget);
+ var result = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
result.Ok.ShouldBeFalse();
result.Message.ShouldNotBeNull();
result.Message.ShouldContain("timed out");
@@ -79,16 +79,16 @@ public sealed class AdminOperationsActorMailboxTests : ControlPlaneActorTestBase
gated.Hold();
deployer.Send(actor, new StartDeployment("joe", CorrelationId.NewId()));
- gated.Entered.Wait(PresenceBudget).ShouldBeTrue("the compose must be parked before the ack is sent");
+ gated.Entered.Wait(PresenceBudget, TestContext.Current.CancellationToken).ShouldBeTrue("the compose must be parked before the ack is sent");
actor.Tell(new AcknowledgeAlarmCommand("alarm-2", "op", null, CorrelationId.NewId()));
- ExpectMsg(AckBudget).Ok.ShouldBeTrue();
+ ExpectMsg(AckBudget, cancellationToken: TestContext.Current.CancellationToken).Ok.ShouldBeTrue();
// Positive control: the deploy completes once released.
- deployer.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+ deployer.ExpectNoMsg(TimeSpan.FromMilliseconds(200), TestContext.Current.CancellationToken);
gated.Release();
- deployer.ExpectMsg(PresenceBudget).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
- coordinator.ExpectMsg(PresenceBudget);
+ deployer.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -106,14 +106,14 @@ public sealed class AdminOperationsActorMailboxTests : ControlPlaneActorTestBase
gated.Hold();
first.Send(actor, new StartDeployment("joe", CorrelationId.NewId()));
- gated.Entered.Wait(PresenceBudget).ShouldBeTrue();
+ gated.Entered.Wait(PresenceBudget, TestContext.Current.CancellationToken).ShouldBeTrue();
second.Send(actor, new StartDeployment("kim", CorrelationId.NewId()));
- second.ExpectMsg(AckBudget).Outcome.ShouldBe(StartDeploymentOutcome.AnotherDeploymentInFlight);
+ second.ExpectMsg(AckBudget, cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(StartDeploymentOutcome.AnotherDeploymentInFlight);
gated.Release();
- first.ExpectMsg(PresenceBudget).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
- coordinator.ExpectMsg(PresenceBudget);
+ first.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
private sealed class BlockingProbe : IDriverProbe
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorServerFaultMessageTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorServerFaultMessageTests.cs
index f4e6fd228..cfa249103 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorServerFaultMessageTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorServerFaultMessageTests.cs
@@ -29,7 +29,7 @@ public sealed class AdminOperationsActorServerFaultMessageTests : ControlPlaneAc
actor.Tell(new StartDeployment("joe", correlationId));
- var reply = ExpectMsg(PresenceBudget);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldNotContain("hunter2");
@@ -46,7 +46,7 @@ public sealed class AdminOperationsActorServerFaultMessageTests : ControlPlaneAc
actor.Tell(new TestDriverConnect("Throwing", "{}", 5, correlationId));
- var reply = ExpectMsg(PresenceBudget);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Ok.ShouldBeFalse();
reply.Message.ShouldNotBeNull();
reply.Message.ShouldNotContain("hunter2");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorSingleSnapshotTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorSingleSnapshotTests.cs
index aa5ded290..d1c1bda06 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorSingleSnapshotTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorSingleSnapshotTests.cs
@@ -67,9 +67,9 @@ public sealed class AdminOperationsActorSingleSnapshotTests : ControlPlaneActorT
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var reply = ExpectMsg(PresenceBudget);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted, reply.Message);
- coordinator.ExpectMsg(PresenceBudget);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
using (var verify = plain.CreateDbContext())
{
@@ -85,7 +85,7 @@ public sealed class AdminOperationsActorSingleSnapshotTests : ControlPlaneActorT
// Positive control: now that the row is visible to a fresh read, the gate rejects it.
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var second = ExpectMsg(PresenceBudget);
+ var second = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
second.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
second.Message.ShouldNotBeNull();
second.Message.ShouldContain("EquipmentIdNotDerived");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTagConfigGateTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTagConfigGateTests.cs
index 8c078542b..fb62a6262 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTagConfigGateTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTagConfigGateTests.cs
@@ -61,8 +61,8 @@ public sealed class AdminOperationsActorTagConfigGateTests : ControlPlaneActorTe
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(PresenceBudget);
- var reply = ExpectMsg(PresenceBudget);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("Intt16");
@@ -80,8 +80,8 @@ public sealed class AdminOperationsActorTagConfigGateTests : ControlPlaneActorTe
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- var reply = ExpectMsg(PresenceBudget);
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("TagConfigInvalid");
@@ -102,8 +102,8 @@ public sealed class AdminOperationsActorTagConfigGateTests : ControlPlaneActorTe
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(PresenceBudget);
- var reply = ExpectMsg(PresenceBudget);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
(reply.Message is null || !reply.Message.Contains("Intt16")).ShouldBeTrue();
}
@@ -121,8 +121,8 @@ public sealed class AdminOperationsActorTagConfigGateTests : ControlPlaneActorTe
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(PresenceBudget);
- ExpectMsg(PresenceBudget).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
+ coordinator.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
+ ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
}
// lmxopcua#781 item 3 — through the actor, in Error mode too: the writable mismatch is a warning, never a reject.
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTests.cs
index 819d5618b..237f68dd2 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AdminOperationsActorTests.cs
@@ -46,14 +46,14 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
var correlationId = CorrelationId.NewId();
actor.Tell(new AcknowledgeAlarmCommand("alarm-42", "operator-jo", "looking into it", correlationId));
- var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3));
+ var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
published.AlarmId.ShouldBe("alarm-42");
published.Operation.ShouldBe("Acknowledge");
published.User.ShouldBe("operator-jo");
published.Comment.ShouldBe("looking into it");
published.UnshelveAtUtc.ShouldBeNull();
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Ok.ShouldBeTrue();
reply.Message.ShouldBeNull();
reply.CorrelationId.ShouldBe(correlationId);
@@ -72,13 +72,13 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
var correlationId = CorrelationId.NewId();
actor.Tell(new ShelveAlarmCommand("alarm-7", "op-kim", ShelveKind.OneShot, UnshelveAtUtc: null, Comment: null, correlationId));
- var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3));
+ var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
published.AlarmId.ShouldBe("alarm-7");
published.Operation.ShouldBe("OneShotShelve");
published.User.ShouldBe("op-kim");
published.UnshelveAtUtc.ShouldBeNull();
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Ok.ShouldBeTrue();
reply.CorrelationId.ShouldBe(correlationId);
}
@@ -96,13 +96,13 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
var unshelveAt = DateTime.UtcNow.AddMinutes(15);
actor.Tell(new ShelveAlarmCommand("alarm-9", "op-lee", ShelveKind.Timed, unshelveAt, Comment: "maint window", CorrelationId.NewId()));
- var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3));
+ var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
published.AlarmId.ShouldBe("alarm-9");
published.Operation.ShouldBe("TimedShelve");
published.UnshelveAtUtc.ShouldBe(unshelveAt);
published.Comment.ShouldBe("maint window");
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Ok.ShouldBeTrue();
}
@@ -118,11 +118,11 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new ShelveAlarmCommand("alarm-3", "op-sam", ShelveKind.Unshelve, UnshelveAtUtc: null, Comment: null, CorrelationId.NewId()));
- var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3));
+ var published = topicProbe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
published.Operation.ShouldBe("Unshelve");
published.UnshelveAtUtc.ShouldBeNull();
- ExpectMsg(TimeSpan.FromSeconds(3)).Ok.ShouldBeTrue();
+ ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken).Ok.ShouldBeTrue();
}
/// Verifies a shelve with a null UnshelveAtUtc is rejected
@@ -137,13 +137,13 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new ShelveAlarmCommand("alarm-1", "op-zoe", ShelveKind.Timed, UnshelveAtUtc: null, Comment: null, CorrelationId.NewId()));
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Ok.ShouldBeFalse();
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("UnshelveAtUtc");
// No command should have been published.
- topicProbe.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
+ topicProbe.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
}
/// Verifies that starting a deployment inserts a row and dispatches to the coordinator.
@@ -156,11 +156,11 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var dispatch = coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ var dispatch = coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
dispatch.DeploymentId.Value.ShouldNotBe(Guid.Empty);
dispatch.RevisionHash.Value.Length.ShouldBe(64);
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
reply.DeploymentId.ShouldBe(dispatch.DeploymentId);
reply.RevisionHash.ShouldBe(dispatch.RevisionHash);
@@ -237,8 +237,8 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("UnsEffectiveNameCollision"); // the v3 rule's error code
@@ -275,8 +275,8 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("EquipmentIdNotDerived");
@@ -321,9 +321,9 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
// Still dispatches — the advisory is non-blocking.
- coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("will compile");
@@ -360,9 +360,9 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
// No compiled scripts → no advisory emitted.
(reply.Message is null || !reply.Message.Contains("will compile")).ShouldBeTrue();
@@ -396,9 +396,9 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("will compile");
@@ -454,8 +454,8 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Rejected);
reply.Message.ShouldNotBeNull();
reply.Message.ShouldContain("ClusterEnabledNodeCountMismatch");
@@ -511,9 +511,9 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
(reply.Message is null || !reply.Message.Contains("ClusterEnabledNodeCountMismatch")).ShouldBeTrue();
(reply.Message is null || !reply.Message.Contains("ClusterRedundancyModeInvalid")).ShouldBeTrue();
@@ -544,8 +544,8 @@ public sealed class AdminOperationsActorTests : ControlPlaneActorTestBase
actor.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
- var reply = ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
+ var reply = ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
reply.Outcome.ShouldBe(StartDeploymentOutcome.AnotherDeploymentInFlight);
reply.DeploymentId.ShouldNotBeNull();
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorRejectedRowTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorRejectedRowTests.cs
index aba376480..86855b2c7 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorRejectedRowTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorRejectedRowTests.cs
@@ -35,7 +35,7 @@ public sealed class AuditWriterActorRejectedRowTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance); // PostStop flushes
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = rejecting.CreateDbContext();
var persisted = db.ConfigAuditLogs.Select(r => r.EventId).ToList();
@@ -71,7 +71,7 @@ public sealed class AuditWriterActorRejectedRowTests : ControlPlaneActorTestBase
foreach (var id in ids) actor.Tell(NewEvent(id));
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = factory.CreateDbContext();
var persisted = db.ConfigAuditLogs.Select(r => r.EventId).ToList();
@@ -99,7 +99,7 @@ public sealed class AuditWriterActorRejectedRowTests : ControlPlaneActorTestBase
foreach (var id in ids) actor.Tell(NewEvent(id));
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor, PresenceBudget);
+ ExpectTerminated(actor, PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
using var db = sql.NewContext();
var persisted = db.ConfigAuditLogs.Select(r => r.EventId).ToList();
@@ -120,7 +120,7 @@ public sealed class AuditWriterActorRejectedRowTests : ControlPlaneActorTestBase
for (var i = 0; i < 5; i++) actor.Tell(NewEvent(Guid.NewGuid()));
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor); // terminates ⇒ the retry loop did not spin
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken); // terminates ⇒ the retry loop did not spin
using var db = rejecting.CreateDbContext();
db.ConfigAuditLogs.Count().ShouldBe(0);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorTests.cs
index 7d0c5522b..3089b159b 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/AuditWriterActorTests.cs
@@ -39,7 +39,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
{
using var db = dbFactory.CreateDbContext();
db.ConfigAuditLogs.Count().ShouldBe(AuditWriterActor.FlushBatchSize);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
/// Verifies that duplicate event IDs within a batch are deduplicated in the buffer.
@@ -57,7 +57,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
// Force a flush — send PoisonPill, which triggers PostStop → FlushBuffer.
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
db.ConfigAuditLogs.Count().ShouldBe(100, "in-buffer dedup should collapse duplicate EventIds");
@@ -76,7 +76,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
db.ConfigAuditLogs.Count().ShouldBe(10);
@@ -94,7 +94,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
var row = db.ConfigAuditLogs.Single();
@@ -127,7 +127,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
var row = db.ConfigAuditLogs.Single();
@@ -146,7 +146,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
var testRef = ActorOfAsTestActorRef(AuditWriterActor.Props(dbFactory));
IAuditWriter writer = testRef.UnderlyingActor;
- var task = writer.WriteAsync(NewEvent(Guid.NewGuid(), action: "Published"));
+ var task = writer.WriteAsync(NewEvent(Guid.NewGuid(), action: "Published"), TestContext.Current.CancellationToken);
task.IsCompletedSuccessfully.ShouldBeTrue("WriteAsync must be best-effort and complete synchronously");
await Should.NotThrowAsync(async () => await task);
}
@@ -165,7 +165,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
var row = db.ConfigAuditLogs.Single();
@@ -187,7 +187,7 @@ public sealed class AuditWriterActorTests : ControlPlaneActorTestBase
Watch(actor);
actor.Tell(PoisonPill.Instance);
- ExpectTerminated(actor);
+ ExpectTerminated(actor, cancellationToken: TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
var row = db.ConfigAuditLogs.Single();
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ClusterNodeAddressReconcilerActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ClusterNodeAddressReconcilerActorTests.cs
index 27299c63a..c65228c59 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ClusterNodeAddressReconcilerActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ClusterNodeAddressReconcilerActorTests.cs
@@ -28,7 +28,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
SeedNode(dbFactory, "site-a-1:4053", enabled: true);
EventFilter.Warning(contains: "site-a-1:4053").ExpectOne(TimeSpan.FromSeconds(10), () =>
- Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory)));
+ Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory)), TestContext.Current.CancellationToken);
}
///
@@ -49,7 +49,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
dbFactory, sweepInterval: TimeSpan.FromMilliseconds(400)));
// Hold the filter open past several sweeps rather than returning immediately.
ExpectNoMsg(TimeSpan.FromSeconds(2.5));
- });
+ }, TestContext.Current.CancellationToken);
}
///
@@ -67,7 +67,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(
dbFactory, sweepInterval: TimeSpan.FromMilliseconds(400)));
ExpectNoMsg(TimeSpan.FromSeconds(1.5));
- });
+ }, TestContext.Current.CancellationToken);
}
///
@@ -88,7 +88,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(
dbFactory, ownClusterId: "MAIN", sweepInterval: TimeSpan.FromMilliseconds(400)));
ExpectNoMsg(TimeSpan.FromSeconds(1.5));
- });
+ }, TestContext.Current.CancellationToken);
}
///
@@ -103,7 +103,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
SeedNode(dbFactory, "main-1:4053", enabled: true, clusterId: "MAIN");
EventFilter.Warning(contains: "main-1:4053").ExpectOne(TimeSpan.FromSeconds(10), () =>
- Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory, ownClusterId: "MAIN")));
+ Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory, ownClusterId: "MAIN")), TestContext.Current.CancellationToken);
}
///
@@ -118,7 +118,7 @@ public sealed class ClusterNodeAddressReconcilerActorTests : ControlPlaneActorTe
SeedNode(dbFactory, "site-a-1:4053", enabled: true, clusterId: "SITE-A");
EventFilter.Warning(contains: "site-a-1:4053").ExpectOne(TimeSpan.FromSeconds(10), () =>
- Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory, ownClusterId: null)));
+ Sys.ActorOf(ClusterNodeAddressReconcilerActor.Props(dbFactory, ownClusterId: null)), TestContext.Current.CancellationToken);
}
private static void SeedNode(
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/CentralCommunicationActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/CentralCommunicationActorTests.cs
index 51dcd0466..39c1747c1 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/CentralCommunicationActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/CentralCommunicationActorTests.cs
@@ -3,7 +3,7 @@ using Akka.Actor;
using Akka.Cluster.Tools.PublishSubscribe;
using Akka.Event;
using Akka.TestKit;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Microsoft.EntityFrameworkCore;
using Shouldly;
using Xunit;
@@ -86,7 +86,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// without an explicit sender would ack to TestActor and this wait would hang.
DistributedPubSub.Get(Sys).Mediator.Tell(
new Subscribe(DeploymentsTopic, mediatorProbe.Ref), mediatorProbe.Ref);
- mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5));
+ mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
var actor = Spawn(factory, new MeshTransportOptions());
var dispatch = new DispatchDeployment(
@@ -94,7 +94,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
actor.Tell(new MeshCommand(DeploymentsTopic, dispatch));
- mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(dispatch);
+ mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(dispatch);
}
[Fact]
@@ -114,7 +114,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
actor.Tell(ack, node.Ref);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(ack);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(ack);
// Forward, not Tell: the coordinator must see the node, not this relay.
coordinator.LastSender.ShouldBe(node.Ref);
}
@@ -133,7 +133,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
new CorrelationId(Guid.NewGuid()));
EventFilter.Warning(contains: "not resolvable").ExpectOne(TimeSpan.FromSeconds(5), () =>
- actor.Tell(ack));
+ actor.Tell(ack), TestContext.Current.CancellationToken);
}
[Fact]
@@ -147,11 +147,11 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// fail with two matches instead of one.
EventFilter.Warning(contains: "contact set was NOT refreshed").ExpectOne(
TimeSpan.FromSeconds(5),
- () => actor.Tell(new Status.Failure(new InvalidOperationException("db down"))));
+ () => actor.Tell(new Status.Failure(new InvalidOperationException("db down"))), TestContext.Current.CancellationToken);
// Still serving: a transient DB outage must not take the command boundary down with it.
actor.Tell(new MeshCommand(DeploymentsTopic, "anything"));
- ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(200), TestContext.Current.CancellationToken);
}
// ------------------------------------------------------------------ Mode = Grpc
@@ -177,7 +177,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 3, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 3, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls.Select(c => c.Endpoint).ShouldBe(
new[] { "http://host-a:4056", "http://host-b:4056", "http://host-c:4056" }, ignoreOrder: true);
@@ -198,15 +198,15 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
var mediatorProbe = CreateTestProbe();
DistributedPubSub.Get(Sys).Mediator.Tell(
new Subscribe(DeploymentsTopic, mediatorProbe.Ref), mediatorProbe.Ref);
- mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5));
+ mediatorProbe.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
var rig = SpawnGrpcRig(factory);
AwaitContactsLoaded(rig);
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
- mediatorProbe.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
+ mediatorProbe.ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
}
[Fact]
@@ -226,11 +226,11 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls[0].Endpoint.ShouldContain("host-a");
// And no late arrival from the two excluded rows.
- ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
rig.Dialer.Calls.Count.ShouldBe(1);
}
@@ -248,13 +248,13 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
GrpcRig? rig = null;
EventFilter.Warning(contains: "has no GrpcPort").ExpectOne(
- TimeSpan.FromSeconds(5), () => rig = SpawnGrpcRig(factory));
+ TimeSpan.FromSeconds(5), () => rig = SpawnGrpcRig(factory), TestContext.Current.CancellationToken);
rig.ShouldNotBeNull();
AwaitContactsLoaded(rig);
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls[0].Endpoint.ShouldBe("http://host-b:4056");
}
@@ -273,11 +273,11 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
SetGrpcPort(factory, "host-a:4053", 4056);
rig.Actor.Tell(new CentralCommunicationActor.RefreshContacts());
AwaitCondition(
- () => rig.Psk.KnownClusterPublications.Count >= 2, TimeSpan.FromSeconds(5));
+ () => rig.Psk.KnownClusterPublications.Count >= 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
SetGrpcPort(factory, "host-a:4053", null);
EventFilter.Warning(contains: "has no GrpcPort").ExpectOne(TimeSpan.FromSeconds(5), () =>
- rig.Actor.Tell(new CentralCommunicationActor.RefreshContacts()));
+ rig.Actor.Tell(new CentralCommunicationActor.RefreshContacts()), TestContext.Current.CancellationToken);
}
[Fact]
@@ -302,14 +302,14 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// The node id, not the endpoint: an operator reading the log is looking at ClusterNode rows.
EventFilter.Warning(contains: "host-a:4053").ExpectOne(TimeSpan.FromSeconds(5), () =>
- rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
// Both were attempted; the healthy one is unaffected by its neighbour's failure.
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
// Still serving after a per-node failure — no supervision restart, no state loss.
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 4, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 4, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
}
[Fact]
@@ -330,9 +330,9 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
AwaitContactsLoaded(rig);
EventFilter.Warning(contains: "Unauthenticated").ExpectOne(TimeSpan.FromSeconds(5), () =>
- rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
}
[Fact]
@@ -343,7 +343,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
AwaitContactsLoaded(rig);
EventFilter.Warning(contains: "dropping").ExpectOne(TimeSpan.FromSeconds(5), () =>
- rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
rig.Dialer.Calls.ShouldBeEmpty();
}
@@ -359,13 +359,13 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
AwaitContactsLoaded(rig);
EventFilter.Error(contains: "Cannot encode").ExpectOne(TimeSpan.FromSeconds(5), () =>
- rig.Actor.Tell(new MeshCommand(DeploymentsTopic, "not a command record")));
+ rig.Actor.Tell(new MeshCommand(DeploymentsTopic, "not a command record")), TestContext.Current.CancellationToken);
rig.Dialer.Calls.ShouldBeEmpty();
// Still serving.
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
}
[Fact]
@@ -384,7 +384,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, new DispatchDeployment(
new DeploymentId(Guid.NewGuid()), new RevisionHash("abc"), correlationId)));
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls.ShouldAllBe(c => c.Envelope.CorrelationId == correlationId.ToString());
// One envelope object, encoded once and fanned — not re-encoded per node.
rig.Dialer.Calls.Select(c => c.Envelope).Distinct().Count().ShouldBe(1);
@@ -408,7 +408,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new MeshCommand(
"alarms", new AlarmCommand("alarm-1", "Acknowledge", "operator", null, null)));
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls.Select(c => c.Envelope.CorrelationId).Distinct().Count().ShouldBe(1);
rig.Dialer.Calls[0].Envelope.CorrelationId.ShouldNotBeNullOrWhiteSpace();
rig.Dialer.Calls[0].Envelope.AlarmCommand.AlarmId.ShouldBe("alarm-1");
@@ -461,7 +461,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
new CorrelationId(Guid.NewGuid()));
rig.Actor.Tell(ack);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(ack);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(ack);
}
finally
{
@@ -502,11 +502,11 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new CentralCommunicationActor.RefreshContacts());
AwaitCondition(
- () => rig.Psk.KnownClusterPublications.Count >= 2, TimeSpan.FromSeconds(5));
+ () => rig.Psk.KnownClusterPublications.Count >= 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.Calls.Select(c => c.Endpoint).ShouldBe(
new[] { "http://host-a:4056", "http://host-b:4056" }, ignoreOrder: true);
@@ -540,7 +540,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
() => psk));
AwaitCondition(
- () => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(5));
+ () => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
psk.KnownClusterPublications[0].ShouldBe(new[] { "C1" });
psk.InvalidateAllCount.ShouldBeGreaterThanOrEqualTo(1);
}
@@ -565,8 +565,8 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
- ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
+ ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
rig.Dialer.Calls.Count.ShouldBe(1);
rig.Dialer.Calls[0].ClusterId.ShouldBe("C1");
}
@@ -589,7 +589,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// Targets-before-gate, observed the only way it can be from outside the actor: the very next
// message finds the dispatch set already populated.
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 1, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
}
[Fact]
@@ -614,7 +614,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// same absence at two severities.
EventFilter.Error(contains: "no command dialer is wired").ExpectOne(
TimeSpan.FromSeconds(5),
- () => actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ () => actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
}
// ------------------------------------------------------------------ PreStart resolve-race logging
@@ -673,7 +673,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
actor!.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
return dialer.Calls.Count >= 1;
}, TimeSpan.FromSeconds(5));
- });
+ }, TestContext.Current.CancellationToken);
// Both retries actually happened — this fact is not vacuously true because the factories
// never got a second chance to run.
@@ -731,7 +731,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
Sys.ActorOf(CentralCommunicationActor.Props(
factory, ModeOptions(mode), () => null, () => new RecordingDialer(), PskFactory));
AwaitCondition(() => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(10));
- });
+ }, TestContext.Current.CancellationToken);
}
[Fact]
@@ -744,9 +744,9 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
EventFilter.Warning().Expect(2, TimeSpan.FromSeconds(10), () =>
Sys.ActorOf(CentralCommunicationActor.Props(
- factory, GrpcMode(), () => null, () => new RecordingDialer(), () => psk)));
+ factory, GrpcMode(), () => null, () => new RecordingDialer(), () => psk)), TestContext.Current.CancellationToken);
- AwaitCondition(() => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(10));
+ AwaitCondition(() => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken);
}
[Fact]
@@ -778,25 +778,25 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// A mailbox barrier also waits for PreStart to register the zero-delay periodic tick.
var marker = new object();
actor.Tell(marker);
- barrier.ExpectMsg(TimeSpan.FromSeconds(5)).Message.ShouldBeSameAs(marker);
+ barrier.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Message.ShouldBeSameAs(marker);
scheduler.Advance(TimeSpan.Zero);
- loads.ExpectMsg(1, TimeSpan.FromSeconds(5));
- local.AwaitCondition(() => Volatile.Read(ref calls) == 2, TimeSpan.FromSeconds(5));
+ loads.ExpectMsg(1, TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
+ local.AwaitCondition(() => Volatile.Read(ref calls) == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
// This mailbox marker is handled after the failed ContactsLoaded handler returns.
// Unlike observing the provider call alone, it proves retry registration is complete.
actor.Tell(marker);
- barrier.ExpectMsg(TimeSpan.FromSeconds(5)).Message.ShouldBeSameAs(marker);
+ barrier.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Message.ShouldBeSameAs(marker);
local.EventFilter.Info(contains: "Known-cluster gate published").ExpectOne(
- TimeSpan.FromSeconds(5), () => actor.Tell(new CentralCommunicationActor.RefreshContacts()));
- loads.ExpectMsg(2, TimeSpan.FromSeconds(5));
+ TimeSpan.FromSeconds(5), () => actor.Tell(new CentralCommunicationActor.RefreshContacts()), TestContext.Current.CancellationToken);
+ loads.ExpectMsg(2, TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
// Cross the pending retry deadline, leaving the 60-second periodic tick untouched.
// LoadContactsFromDb uses Task.Run, so observe its boundary for the original absence
// budget rather than asserting before a mistakenly retained retry can start its read.
scheduler.Advance(TimeSpan.FromMilliseconds(2500));
- loads.ExpectNoMsg(TimeSpan.FromMilliseconds(2500));
+ loads.ExpectNoMsg(TimeSpan.FromMilliseconds(2500), TestContext.Current.CancellationToken);
factory.Calls.ShouldBe(2);
psk.KnownClusterPublications.Count.ShouldBe(1);
}
@@ -810,7 +810,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
factory, GrpcMode(), () => null, () => new RecordingDialer(), () => new RecordingPskProvider(),
bootstrapRetryInterval: TimeSpan.FromMilliseconds(20)));
- EventFilter.Warning().Expect(32, TimeSpan.FromSeconds(10), () => { });
+ EventFilter.Warning().Expect(32, TimeSpan.FromSeconds(10), () => { }, TestContext.Current.CancellationToken);
Thread.Sleep(1500);
// 1 initial + 15 retries; the 60 s periodic tick has not fired again.
factory.Calls.ShouldBe(16);
@@ -854,7 +854,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// ran and PublishKnownClusters's property access performed the first-use retry — not
// merely that the actor was constructed.
AwaitCondition(() => pskCalls >= 2, TimeSpan.FromSeconds(5));
- });
+ }, TestContext.Current.CancellationToken);
// The bootstrap retry is BOUNDED: with a 50 ms interval and a budget of 15 it has long
// finished, so the call count plateaus instead of growing with elapsed time.
@@ -873,7 +873,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
{
actor.Tell(new CentralCommunicationActor.RefreshContacts());
AwaitCondition(() => pskCalls > pskCallsAfterFirstLoad, TimeSpan.FromSeconds(5));
- });
+ }, TestContext.Current.CancellationToken);
}
[Fact]
@@ -904,15 +904,15 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
// Proof PreStart's resolve attempt and the first contact load it schedules have
// actually run, so this block's silence is not vacuous.
AwaitCondition(() => psk.KnownClusterPublications.Count >= 1, TimeSpan.FromSeconds(5));
- });
+ }, TestContext.Current.CancellationToken);
EventFilter.Error(contains: "no command dialer is wired").ExpectOne(TimeSpan.FromSeconds(5), () =>
- actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
// A SECOND dispatch must ALSO log it: this signal is per-dispatch and unguarded, the
// opposite shape from the PSK provider's once-per-incarnation guard above.
EventFilter.Error(contains: "no command dialer is wired").ExpectOne(TimeSpan.FromSeconds(5), () =>
- actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())));
+ actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch())), TestContext.Current.CancellationToken);
}
private static void SetGrpcPort(
@@ -943,7 +943,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
AwaitContactsLoaded(rig);
// The dialer is resolved lazily on first use; a dispatch forces that, and the NEXT refresh prunes.
rig.Actor.Tell(new MeshCommand(DeploymentsTopic, NewDispatch()));
- AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5));
+ AwaitCondition(() => rig.Dialer.Calls.Count == 2, TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
using (var db = factory.CreateDbContext())
{
@@ -954,7 +954,7 @@ public class CentralCommunicationActorTests : ControlPlaneActorTestBase
AwaitCondition(
() => rig.Dialer.RetainCalls.Any(set => set.Count == 1 && set.Single().Contains("host-a")),
- TimeSpan.FromSeconds(5));
+ TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
rig.Dialer.RetainCalls.Last().ShouldBe(new[] { "http://host-a:4056" });
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/ControlPlaneStarterOrderTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/ControlPlaneStarterOrderTests.cs
index 618f9e788..4ed4f5683 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/ControlPlaneStarterOrderTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/ControlPlaneStarterOrderTests.cs
@@ -75,7 +75,7 @@ public sealed class ControlPlaneStarterOrderTests
}
finally
{
- await host.StopAsync();
+ await host.StopAsync(TestContext.Current.CancellationToken);
}
}
@@ -101,16 +101,16 @@ public sealed class ControlPlaneStarterOrderTests
// StartAsync at which a synchronous assertion is correct.
using var host = BuildAdminHost(mode, useSignallingProvider: true);
- await host.StartAsync();
+ await host.StartAsync(TestContext.Current.CancellationToken);
try
{
var signal = (SignallingPskProvider)host.Services.GetRequiredService();
- await signal.Published.WaitAsync(TimeSpan.FromSeconds(20));
+ await signal.Published.WaitAsync(TimeSpan.FromSeconds(20), TestContext.Current.CancellationToken);
}
finally
{
- await host.StopAsync();
+ await host.StopAsync(TestContext.Current.CancellationToken);
}
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderRefreshTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderRefreshTests.cs
index 259fa42f4..02aafc1b6 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderRefreshTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderRefreshTests.cs
@@ -51,7 +51,7 @@ public sealed class MeshPskProviderRefreshTests
resolver.Value = "new";
resolver.Hold();
var refresh = provider.RefreshAsync(new[] { "SITE-A" }, CancellationToken.None);
- resolver.Entered.Wait(TimeSpan.FromSeconds(5)).ShouldBeTrue();
+ resolver.Entered.Wait(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken).ShouldBeTrue();
// Mid-refresh: the old key, from memory — the store is NOT re-read on this path.
var callsMidRefresh = resolver.Calls;
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderTests.cs
index 6ccafb65c..356bd97a8 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshPskProviderTests.cs
@@ -307,7 +307,7 @@ public sealed class MeshPskProviderTests
return psk;
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default)).ToArray();
- arrived.Wait(TimeSpan.FromSeconds(10)).ShouldBeTrue("all callers should reach the start gate");
+ arrived.Wait(TimeSpan.FromSeconds(10), TestContext.Current.CancellationToken).ShouldBeTrue("all callers should reach the start gate");
start.Set();
var results = await Task.WhenAll(callers);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshRouterDispatchTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshRouterDispatchTests.cs
index 5d4095b74..d5a1fcaaf 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshRouterDispatchTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Communication/MeshRouterDispatchTests.cs
@@ -38,7 +38,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
coordinator.Tell(new Commons.Messages.Deploy.DispatchDeployment(
deploymentId, new RevisionHash("rev-1"), CorrelationId.NewId()));
- var cmd = router.ExpectMsg(PresenceBudget);
+ var cmd = router.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cmd.Topic.ShouldBe(DeploymentsTopic);
cmd.Message.ShouldBeOfType();
}
@@ -49,7 +49,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
var subscriber = CreateTestProbe();
DistributedPubSub.Get(Sys).Mediator.Tell(
new Subscribe(DeploymentsTopic, subscriber.Ref), subscriber.Ref);
- subscriber.ExpectMsg(PresenceBudget);
+ subscriber.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
var coordinator = Sys.ActorOf(ConfigPublishCoordinator.Props(NewInMemoryDbFactory()));
@@ -59,7 +59,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
// Presence budget, not 5 s: the coordinator's first ConfigDb (EF InMemory) read sits in front
// of the dispatch and is a cold multi-second cost on a loaded CI runner (#606).
- subscriber.ExpectMsg(PresenceBudget);
+ subscriber.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
[Fact]
@@ -75,7 +75,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
admin.Tell(new RestartDriver("C1", "driver-1", "alice", Guid.NewGuid()));
- var cmd = router.ExpectMsg(PresenceBudget);
+ var cmd = router.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cmd.Topic.ShouldBe(DriverControlTopic.Name);
cmd.Message.ShouldBeOfType();
}
@@ -93,7 +93,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
admin.Tell(new ReconnectDriver("C1", "driver-1", "alice", Guid.NewGuid()));
- var cmd = router.ExpectMsg(PresenceBudget);
+ var cmd = router.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cmd.Topic.ShouldBe(DriverControlTopic.Name);
cmd.Message.ShouldBeOfType();
}
@@ -111,7 +111,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
admin.Tell(new AcknowledgeAlarmCommand("alarm-1", "alice", "c", CorrelationId.NewId()));
- var cmd = router.ExpectMsg(PresenceBudget);
+ var cmd = router.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cmd.Topic.ShouldBe(AlarmCommandsTopic.Name);
cmd.Message.ShouldBeOfType();
}
@@ -129,7 +129,7 @@ public class MeshRouterDispatchTests : ControlPlaneActorTestBase
admin.Tell(new ShelveAlarmCommand("alarm-1", "alice", ShelveKind.OneShot, null, "c", CorrelationId.NewId()));
- var cmd = router.ExpectMsg(PresenceBudget);
+ var cmd = router.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cmd.Topic.ShouldBe(AlarmCommandsTopic.Name);
cmd.Message.ShouldBeOfType();
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerSqlServerHashStabilityTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerSqlServerHashStabilityTests.cs
index 67ac26bd6..afcc07037 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerSqlServerHashStabilityTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerSqlServerHashStabilityTests.cs
@@ -32,20 +32,20 @@ public sealed class ConfigComposerSqlServerHashStabilityTests
// Collation order a-2, B-1, c-3; ordinal order B-1, a-2, c-3.
foreach (var id in new[] { "c-3", "B-1", "a-2" })
seed.Scripts.Add(new Script { ScriptId = id, Name = id, SourceCode = "return 1;", SourceHash = id });
- await seed.SaveChangesAsync();
+ await seed.SaveChangesAsync(TestContext.Current.CancellationToken);
}
await using var legacyDb = sql.NewContext();
var legacy = await LegacySnapshotAndFlattenAsync(legacyDb);
await using var viaDb = sql.NewContext();
- var current = await ConfigComposer.SnapshotAndFlattenAsync(viaDb);
+ var current = await ConfigComposer.SnapshotAndFlattenAsync(viaDb, TestContext.Current.CancellationToken);
current.Blob.ShouldBe(legacy.Blob);
current.RevisionHash.ShouldBe(legacy.RevisionHash);
// The deploy path's form (validate + compose from ONE snapshot) must agree too.
await using var deployDb = sql.NewContext();
- var viaSnapshot = ConfigComposer.Compose(await DraftSnapshotFactory.FromConfigDbAsync(deployDb));
+ var viaSnapshot = ConfigComposer.Compose(await DraftSnapshotFactory.FromConfigDbAsync(deployDb, TestContext.Current.CancellationToken));
viaSnapshot.RevisionHash.ShouldBe(legacy.RevisionHash);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerTests.cs
index 674ececd6..6f740dfd9 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigComposerTests.cs
@@ -20,10 +20,10 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
var f = NewInMemoryDbFactory();
await using var db1 = f.CreateDbContext();
- var a1 = await ConfigComposer.SnapshotAndFlattenAsync(db1);
+ var a1 = await ConfigComposer.SnapshotAndFlattenAsync(db1, TestContext.Current.CancellationToken);
await using var db2 = f.CreateDbContext();
- var a2 = await ConfigComposer.SnapshotAndFlattenAsync(db2);
+ var a2 = await ConfigComposer.SnapshotAndFlattenAsync(db2, TestContext.Current.CancellationToken);
a1.RevisionHash.ShouldBe(a2.RevisionHash);
a1.Blob.ShouldBe(a2.Blob);
@@ -40,9 +40,9 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
{
db.ServerClusters.Add(NewCluster("cluster-a"));
db.ServerClusters.Add(NewCluster("cluster-b"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var hashAB = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext())).RevisionHash;
+ var hashAB = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
// Fresh DB, same rows in reverse insertion order.
var f2 = NewInMemoryDbFactory();
@@ -50,9 +50,9 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
{
db.ServerClusters.Add(NewCluster("cluster-b"));
db.ServerClusters.Add(NewCluster("cluster-a"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var hashBA = (await ConfigComposer.SnapshotAndFlattenAsync(f2.CreateDbContext())).RevisionHash;
+ var hashBA = (await ConfigComposer.SnapshotAndFlattenAsync(f2.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
hashAB.ShouldBe(hashBA);
}
@@ -65,16 +65,16 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
await using (var db = f.CreateDbContext())
{
db.ServerClusters.Add(NewCluster("cluster-a"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var hashA = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext())).RevisionHash;
+ var hashA = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
await using (var db = f.CreateDbContext())
{
db.ServerClusters.Add(NewCluster("cluster-b"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var hashAB = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext())).RevisionHash;
+ var hashAB = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
hashAB.ShouldNotBe(hashA);
}
@@ -84,7 +84,7 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
public async Task Hash_is_64_lowercase_hex_chars()
{
var f = NewInMemoryDbFactory();
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
artifact.RevisionHash.Length.ShouldBe(64);
artifact.RevisionHash.ShouldMatch("^[0-9a-f]{64}$");
}
@@ -102,10 +102,10 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
await using (var db = f.CreateDbContext())
{
db.ServerClusters.Add(NewCluster("c1"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
artifact.Blob[0].ShouldBe((byte)0x1F);
artifact.Blob[1].ShouldBe((byte)0x8B);
@@ -118,7 +118,7 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
using var inflated = new MemoryStream();
await using (var gz = new GZipStream(new MemoryStream(artifact.Blob), CompressionMode.Decompress))
{
- await gz.CopyToAsync(inflated);
+ await gz.CopyToAsync(inflated, TestContext.Current.CancellationToken);
}
var json = inflated.ToArray();
Encoding.UTF8.GetString(json).ShouldStartWith("{");
@@ -155,11 +155,11 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
DeviceId = "dev-1", DriverInstanceId = "drv-1",
Name = "dev-1", DeviceConfig = "{\"HostAddress\":\"10.9.9.9:8193\"}",
});
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
await using var readDb = f.CreateDbContext();
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(readDb);
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(readDb, TestContext.Current.CancellationToken);
var specs = DeploymentArtifact.ParseDriverInstances(artifact.Blob);
var spec = specs.ShouldHaveSingleItem();
@@ -208,11 +208,11 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
DriverInstanceId = "drv-2", ClusterId = "c1",
Name = "Modbus2", DriverType = "Modbus", DriverConfig = "{}",
});
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
await using var readDb = f.CreateDbContext();
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(readDb);
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(readDb, TestContext.Current.CancellationToken);
var specs = DeploymentArtifact.ParseDriverInstances(artifact.Blob);
var withOverride = specs.Single(s => s.DriverInstanceId == "drv-1");
@@ -241,11 +241,11 @@ public sealed class ConfigComposerTests : ControlPlaneActorTestBase
ApiKeyId = "k1", Name = "scada", SecretHash = "h", Principal = "scadabridge", CreatedUtc = FixedTimestamp,
});
db.Scripts.Add(new Script { ScriptId = "s-1", Name = "s", SourceCode = "return 1;", SourceHash = "x" });
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var viaDb = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
- var snapshot = await Configuration.Validation.DraftSnapshotFactory.FromConfigDbAsync(f.CreateDbContext());
+ var viaDb = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
+ var snapshot = await Configuration.Validation.DraftSnapshotFactory.FromConfigDbAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var viaSnapshot = ConfigComposer.Compose(snapshot);
viaSnapshot.RevisionHash.ShouldBe(viaDb.RevisionHash);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorDbSourcedAcksTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorDbSourcedAcksTests.cs
index 95d8a4ac3..467630bf6 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorDbSourcedAcksTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorDbSourcedAcksTests.cs
@@ -60,7 +60,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
using var db = dbFactory.CreateDbContext();
db.NodeDeploymentStates.Select(s => s.NodeId).ShouldBe(new[] { "site-a-1:4053" });
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
actor.Tell(new ApplyAck(deploymentId, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -69,7 +69,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -94,7 +94,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.NodeDeploymentStates.Select(s => s.NodeId).ShouldBe(new[] { "site-a-1:4053" });
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
// ...and the enabled node's ack alone seals it. If the disabled row were expected this would
// sit at AwaitingApplyAcks until the deadline.
@@ -105,7 +105,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -126,13 +126,13 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
// A node nobody registered acks. One expected node, one ack — if it were counted, the
// coordinator would seal here.
actor.Tell(new ApplyAck(deploymentId, NodeId.Parse("ghost-9:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
- ExpectNoMsg(TimeSpan.FromMilliseconds(400));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(400), TestContext.Current.CancellationToken);
using (var db = dbFactory.CreateDbContext())
{
@@ -147,7 +147,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -170,7 +170,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
db.NodeDeploymentStates.ShouldBeEmpty();
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -202,7 +202,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.NodeDeploymentStates.Select(s => s.NodeId).ShouldBe(new[] { "site-a-1:4053" });
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
actor.Tell(new ApplyAck(deploymentId, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -211,7 +211,7 @@ public sealed class ConfigPublishCoordinatorDbSourcedAcksTests : ControlPlaneAct
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
private static void SeedNodes(
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorRecoveryTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorRecoveryTests.cs
index 8c93fb1ce..bd73313ad 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorRecoveryTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorRecoveryTests.cs
@@ -46,7 +46,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
using var db = dbFactory.CreateDbContext();
db.NodeDeploymentStates.Select(s => s.NodeId).ShouldBe(new[] { "site-a-1:4053" });
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
actor.Tell(new ApplyAck(deploymentId, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -55,7 +55,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -79,7 +79,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
row.Status.ShouldBe(DeploymentStatus.TimedOut);
row.FailureReason.ShouldNotBeNull();
row.FailureReason.ShouldContain("lost");
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
// Positive control: the coordinator is not wedged — a fresh deployment runs end to end.
var nextId = SeedDeployment(dbFactory, DeploymentStatus.Dispatching, DateTime.UtcNow);
@@ -88,7 +88,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single(d => d.DeploymentId == nextId.Value).Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
actor.Tell(new ApplyAck(nextId, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -96,7 +96,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single(d => d.DeploymentId == nextId.Value).Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -116,7 +116,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
db.NodeDeploymentStates.ShouldBeEmpty();
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -139,10 +139,10 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
// Arm the fault AFTER PreStart has run (it would otherwise fault the recovery read itself and
// the actor would be stopped, not restarted). Identify is processed after creation, so a
// resolved selection proves PreStart completed.
- await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget);
+ await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget, TestContext.Current.CancellationToken);
faulting.FailNext();
admin.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var first = ExpectMsg(PresenceBudget);
+ var first = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
first.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
first.DeploymentId.ShouldNotBeNull();
@@ -153,7 +153,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
using var db = adminFactory.CreateDbContext();
db.NodeDeploymentStates.Count(s => s.DeploymentId == first.DeploymentId.Value.Value).ShouldBe(1);
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
coordinator.Tell(new ApplyAck(first.DeploymentId.Value, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -161,11 +161,11 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = adminFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
// Positive control: nothing is wedged — the next deploy is Accepted and seals too.
admin.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var second = ExpectMsg(PresenceBudget);
+ var second = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
second.Outcome.ShouldBe(StartDeploymentOutcome.Accepted);
coordinator.Tell(new ApplyAck(second.DeploymentId!.Value, NodeId.Parse("site-a-1:4053"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
@@ -173,7 +173,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = adminFactory.CreateDbContext();
db.Deployments.Count(d => d.Status == DeploymentStatus.Sealed).ShouldBe(2);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -189,14 +189,14 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
var dbFactory = NewInMemoryDbFactory();
SeedNodes(dbFactory, "site-a-1:4053");
var coordinator = Sys.ActorOf(ConfigPublishCoordinator.Props(dbFactory, NoTimeout));
- await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget); // PreStart saw nothing
+ await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget, TestContext.Current.CancellationToken); // PreStart saw nothing
var stale = SeedDeployment(dbFactory, DeploymentStatus.Dispatching, DateTime.UtcNow.AddMinutes(-10));
var admin = Sys.ActorOf(AdminOperationsActor.Props(
dbFactory, coordinator, Enumerable.Empty(), applyDeadline: NoTimeout));
admin.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var result = ExpectMsg(PresenceBudget);
+ var result = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
result.Outcome.ShouldBe(StartDeploymentOutcome.Accepted, result.Message);
using (var db = dbFactory.CreateDbContext())
@@ -214,7 +214,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
using var db = dbFactory.CreateDbContext();
db.Deployments.Single(d => d.DeploymentId == result.DeploymentId.Value.Value).Status
.ShouldBe(DeploymentStatus.Sealed);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
/// Control for the closure: the same row INSIDE the deadline is still in flight and still refuses.
@@ -228,7 +228,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
dbFactory, coordinator.Ref, Enumerable.Empty(), applyDeadline: NoTimeout));
admin.Tell(new StartDeployment("joe", CorrelationId.NewId()));
- var result = ExpectMsg(PresenceBudget);
+ var result = ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
result.Outcome.ShouldBe(StartDeploymentOutcome.AnotherDeploymentInFlight);
result.DeploymentId.ShouldBe(pending);
@@ -261,7 +261,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single(d => d.DeploymentId == live.Value).Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
using var verify = dbFactory.CreateDbContext();
verify.Deployments.Single(d => d.DeploymentId == done.Value).Status.ShouldBe(terminal);
@@ -298,7 +298,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
{
using var db = sql.NewContext();
db.Deployments.AsNoTracking().Single().Status.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget); // PreStart re-drives the un-dispatched row
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken); // PreStart re-drives the un-dispatched row
coordinator.Tell(new ApplyAck(id, NodeId.Parse("site-a-1:4053"), ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
AwaitAssert(() =>
@@ -308,7 +308,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
row.Status.ShouldBe(DeploymentStatus.Sealed);
row.SealedAtUtc.ShouldNotBeNull();
row.ArtifactBlob.ShouldBe(blob);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -327,7 +327,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
SeedNodes(inner, "site-a-1:4053");
var interposer = new InterposingDbFactory(inner);
var coordinator = Sys.ActorOf(ConfigPublishCoordinator.Props(interposer, NoTimeout));
- await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget); // PreStart ran over an empty table
+ await Sys.ActorSelection(coordinator.Path).ResolveOne(PresenceBudget, TestContext.Current.CancellationToken); // PreStart ran over an empty table
// The race proper: a new Dispatching row whose dispatch is interleaved with an AdminOps-style closure.
var victim = SeedDeployment(inner, DeploymentStatus.Dispatching, DateTime.UtcNow);
@@ -339,7 +339,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
(int)DeploymentStatus.TimedOut, victim.Value);
});
coordinator.Tell(new DispatchDeployment(victim, TestRevision, CorrelationId.NewId()));
- AwaitAssert(() => interposer.Fired.ShouldBeTrue(), duration: PresenceBudget);
+ AwaitAssert(() => interposer.Fired.ShouldBeTrue(), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
// Positive control + ordering: a live row dispatched after it IS flipped, so the victim's dispatch was processed.
var live = SeedDeployment(inner, DeploymentStatus.Dispatching, DateTime.UtcNow);
@@ -349,7 +349,7 @@ public sealed class ConfigPublishCoordinatorRecoveryTests : ControlPlaneActorTes
using var db = sql.NewContext();
db.Deployments.AsNoTracking().Single(d => d.DeploymentId == live.Value).Status
.ShouldBe(DeploymentStatus.AwaitingApplyAcks);
- }, duration: PresenceBudget);
+ }, duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
using var verify = sql.NewContext();
verify.Deployments.AsNoTracking().Single(d => d.DeploymentId == victim.Value).Status
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTests.cs
index fc16f0b55..a691e9579 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTests.cs
@@ -30,7 +30,7 @@ public sealed class ConfigPublishCoordinatorTests : ControlPlaneActorTestBase
using var db = dbFactory.CreateDbContext();
var status = db.Deployments.Single().Status;
status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
/// Verifies that stale apply acknowledgments arriving after seal are ignored.
@@ -48,14 +48,14 @@ public sealed class ConfigPublishCoordinatorTests : ControlPlaneActorTestBase
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
// Now send a late ApplyAck for the just-sealed deployment. Should be a no-op — neither
// crash the actor nor modify the row. We give it a beat and re-check the status.
actor.Tell(new ApplyAck(deploymentId, NodeId.Parse("ghost-node"),
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
- ExpectNoMsg(TimeSpan.FromMilliseconds(250));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(250), TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
}
@@ -106,7 +106,7 @@ public sealed class ConfigPublishCoordinatorTests : ControlPlaneActorTestBase
ApplyAckOutcome.Applied, null, CorrelationId.NewId()));
// Give it time to process and potentially seal if buggy.
- ExpectNoMsg(TimeSpan.FromMilliseconds(400));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(400), TestContext.Current.CancellationToken);
using var db2 = dbFactory.CreateDbContext();
var status = db2.Deployments.Single().Status;
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTimeoutTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTimeoutTests.cs
index 5639996f4..917be29e5 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTimeoutTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ConfigPublishCoordinatorTimeoutTests.cs
@@ -53,7 +53,7 @@ public sealed class ConfigPublishCoordinatorTimeoutTests : ControlPlaneActorTest
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.TimedOut);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
/// Verifies that stale DeadlineElapsed for other deployments is ignored.
@@ -68,7 +68,7 @@ public sealed class ConfigPublishCoordinatorTimeoutTests : ControlPlaneActorTest
actor.Tell(new ConfigPublishCoordinator.DeadlineElapsed(DeploymentId.NewId()));
// The seeded one should remain in its starting state (no transition triggered).
- ExpectNoMsg(TimeSpan.FromMilliseconds(250));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(250), TestContext.Current.CancellationToken);
using var db = dbFactory.CreateDbContext();
var status = db.Deployments.Single().Status;
status.ShouldBeOneOf(DeploymentStatus.Dispatching, DeploymentStatus.AwaitingApplyAcks, DeploymentStatus.Sealed);
@@ -108,7 +108,7 @@ public sealed class ConfigPublishCoordinatorTimeoutTests : ControlPlaneActorTest
{
using var db = dbFactory.CreateDbContext();
db.Deployments.Single().Status.ShouldBe(DeploymentStatus.Sealed);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
///
@@ -135,7 +135,7 @@ public sealed class ConfigPublishCoordinatorTimeoutTests : ControlPlaneActorTest
row.FailureReason.ShouldContain("No ack from: site-b-1:4053.");
row.FailureReason.ShouldContain("(1/2 landed)");
row.FailureReason.ShouldNotContain("site-a-1");
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
/// lmxopcua#784 — the timeout reason stays bounded on a large fleet: it names 20 nodes and counts the rest.
@@ -159,7 +159,7 @@ public sealed class ConfigPublishCoordinatorTimeoutTests : ControlPlaneActorTest
reason.ShouldNotContain("node-20-");
reason.ShouldContain("(and 5 more)");
reason.Length.ShouldBeLessThanOrEqualTo(2048);
- }, duration: TimeSpan.FromSeconds(3));
+ }, duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
}
private static void SeedNodeRows(
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DataPlaneAuthorityArtifactTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DataPlaneAuthorityArtifactTests.cs
index 857590c31..b098f85d8 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DataPlaneAuthorityArtifactTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DataPlaneAuthorityArtifactTests.cs
@@ -33,10 +33,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
{
db.ServerClusters.Add(NewCluster("cluster-a"));
db.ApiKeys.Add(NewKey("abc123", "scadabridge-dcl"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
var key = parsed.Keys.ShouldHaveSingleItem();
@@ -58,10 +58,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
db.ServerClusters.Add(NewCluster("cluster-a"));
db.NodeAcls.Add(NewAcl("acl-1", "cluster-a", "scadabridge-dcl",
NodeAclScopeKind.Cluster, NodePermissions.Read | NodePermissions.WriteOperate));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
var grant = parsed.Grants.ShouldHaveSingleItem();
@@ -82,10 +82,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
var acl = NewAcl("acl-1", "cluster-a", "p", NodeAclScopeKind.Equipment, NodePermissions.Read);
acl.ScopeId = "EQ-1";
db.NodeAcls.Add(acl);
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
var grant = parsed.Grants.ShouldHaveSingleItem();
@@ -110,10 +110,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
var key = NewKey("abc123", "p");
key.ExpiresUtc = expires;
db.ApiKeys.Add(key);
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
var parsedKey = parsed.Keys.ShouldHaveSingleItem();
@@ -139,10 +139,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
db.ApiKeys.Add(NewKey("key-b", "principal-b"));
db.NodeAcls.Add(NewAcl("acl-a", "cluster-a", "principal-a", NodeAclScopeKind.Cluster, NodePermissions.Read));
db.NodeAcls.Add(NewAcl("acl-b", "cluster-b", "principal-b", NodeAclScopeKind.Cluster, NodePermissions.Read));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
parsed.ClusterId.ShouldBe("cluster-a");
@@ -162,10 +162,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
db.ServerClusters.Add(NewCluster("cluster-b"));
db.ClusterNodes.Add(NewNode(NodeB, "cluster-b"));
db.NodeAcls.Add(NewAcl("acl-b", "cluster-b", "principal-b", NodeAclScopeKind.Cluster, NodePermissions.Read));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, "node-nowhere:4840");
parsed.Grants.ShouldBeEmpty();
@@ -184,10 +184,10 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
var key = NewKey("abc123", "p");
key.Enabled = false;
db.ApiKeys.Add(key);
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext());
+ var artifact = await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken);
var parsed = DeploymentArtifact.ParseDataPlaneAuthority(artifact.Blob, NodeA);
parsed.Keys.ShouldHaveSingleItem().Enabled.ShouldBeFalse();
@@ -211,16 +211,16 @@ public sealed class DataPlaneAuthorityArtifactTests : ControlPlaneActorTestBase
await using (var db = f.CreateDbContext())
{
db.ServerClusters.Add(NewCluster("cluster-a"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var before = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext())).RevisionHash;
+ var before = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
await using (var db = f.CreateDbContext())
{
db.ApiKeys.Add(NewKey("abc123", "p"));
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
- var after = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext())).RevisionHash;
+ var after = (await ConfigComposer.SnapshotAndFlattenAsync(f.CreateDbContext(), TestContext.Current.CancellationToken)).RevisionHash;
after.ShouldNotBe(before);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DeploymentRetentionTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DeploymentRetentionTests.cs
index bb607aafe..3cd0cd13a 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DeploymentRetentionTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/DeploymentRetentionTests.cs
@@ -29,20 +29,20 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
int pruned;
await using (var db = f.CreateDbContext())
- pruned = await DeploymentRetentionActor.SweepAsync(db, options, SweepNow);
+ pruned = await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken);
pruned.ShouldBe(7);
await using var verify = f.CreateDbContext();
foreach (var id in ids.Take(5))
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == id)).ArtifactBlob.Length.ShouldBeGreaterThan(0, "newest 5 keep their blob");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == id, TestContext.Current.CancellationToken)).ArtifactBlob.Length.ShouldBeGreaterThan(0, "newest 5 keep their blob");
foreach (var id in ids.Skip(5))
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == id)).ArtifactBlob.ShouldBeEmpty("older rows are emptied");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == id, TestContext.Current.CancellationToken)).ArtifactBlob.ShouldBeEmpty("older rows are emptied");
// Rows survive: the audit record is intact.
- (await verify.Deployments.CountAsync()).ShouldBe(12);
+ (await verify.Deployments.CountAsync(TestContext.Current.CancellationToken)).ShouldBe(12);
// Idempotent: a second sweep finds nothing.
await using var again = f.CreateDbContext();
- (await DeploymentRetentionActor.SweepAsync(again, options, SweepNow)).ShouldBe(0);
+ (await DeploymentRetentionActor.SweepAsync(again, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(0);
}
[Fact]
@@ -76,19 +76,19 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
DeploymentId = inFlight, RevisionHash = new string('f', 64), Status = DeploymentStatus.AwaitingApplyAcks,
CreatedBy = "test", CreatedAtUtc = SweepNow.AddDays(-400), ArtifactBlob = new byte[] { 1, 2, 3 },
});
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
var options = new DeploymentRetentionOptions { KeepSealed = 1, ReferencedDays = 30 };
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(2); // ids[1], ids[2]
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(2); // ids[1], ids[2]
await using var verify = f.CreateDbContext();
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[0])).ArtifactBlob.ShouldNotBeEmpty("newest");
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[1])).ArtifactBlob.ShouldBeEmpty();
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[2])).ArtifactBlob.ShouldBeEmpty("applied 90 days ago");
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[3])).ArtifactBlob.ShouldNotBeEmpty("applied yesterday");
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == inFlight)).ArtifactBlob.ShouldNotBeEmpty("in flight");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[0], TestContext.Current.CancellationToken)).ArtifactBlob.ShouldNotBeEmpty("newest");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[1], TestContext.Current.CancellationToken)).ArtifactBlob.ShouldBeEmpty();
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[2], TestContext.Current.CancellationToken)).ArtifactBlob.ShouldBeEmpty("applied 90 days ago");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[3], TestContext.Current.CancellationToken)).ArtifactBlob.ShouldNotBeEmpty("applied yesterday");
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == inFlight, TestContext.Current.CancellationToken)).ArtifactBlob.ShouldNotBeEmpty("in flight");
}
///
@@ -121,17 +121,17 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
CreatedBy = "test", CreatedAtUtc = SweepNow.AddHours(-i), ArtifactBlob = new byte[] { 9 },
});
}
- await db.SaveChangesAsync();
+ await db.SaveChangesAsync(TestContext.Current.CancellationToken);
}
var options = new DeploymentRetentionOptions { KeepSealed = 50, ReferencedDays = 30, MaxRowsPerSweep = 200 };
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(60);
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(60);
await using var verify = f.CreateDbContext();
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == sealedId)).ArtifactBlob
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == sealedId, TestContext.Current.CancellationToken)).ArtifactBlob
.ShouldNotBeEmpty("the newest Sealed artifact is never pruned");
- (await verify.Deployments.CountAsync(d => timedOut.Contains(d.DeploymentId) && d.ArtifactBlob.Length == 0))
+ (await verify.Deployments.CountAsync(d => timedOut.Contains(d.DeploymentId) && d.ArtifactBlob.Length == 0, TestContext.Current.CancellationToken))
.ShouldBe(60);
}
@@ -143,11 +143,11 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
var ids = Seed(f, sealedCount: 3, mixInTimedOut: false);
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, new DeploymentRetentionOptions { KeepSealed = 0 }, SweepNow))
+ (await DeploymentRetentionActor.SweepAsync(db, new DeploymentRetentionOptions { KeepSealed = 0 }, SweepNow, TestContext.Current.CancellationToken))
.ShouldBe(2);
await using var verify = f.CreateDbContext();
- (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[0])).ArtifactBlob.ShouldNotBeEmpty();
+ (await verify.Deployments.SingleAsync(d => d.DeploymentId == ids[0], TestContext.Current.CancellationToken)).ArtifactBlob.ShouldNotBeEmpty();
}
[Fact]
@@ -158,13 +158,13 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
var options = new DeploymentRetentionOptions { KeepSealed = 2, MaxRowsPerSweep = 3 };
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(3);
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(3);
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(3);
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(3);
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(2);
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(2);
await using (var db = f.CreateDbContext())
- (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow)).ShouldBe(0);
+ (await DeploymentRetentionActor.SweepAsync(db, options, SweepNow, TestContext.Current.CancellationToken)).ShouldBe(0);
}
/// The actor runs the same rule off its thread and reports back.
@@ -180,7 +180,7 @@ public sealed class DeploymentRetentionTests : ControlPlaneActorTestBase
actor.Tell(DeploymentRetentionActor.Sweep.Instance);
- ExpectMsg(PresenceBudget).Pruned.ShouldBe(2);
+ ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken).Pruned.ShouldBe(2);
using var verify = f.CreateDbContext();
verify.Deployments.Count(d => d.ArtifactBlob.Length == 0).ShouldBe(2);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/GossipedRoleCaseInsensitivityTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/GossipedRoleCaseInsensitivityTests.cs
index 3cc6c3c92..47eee29c6 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/GossipedRoleCaseInsensitivityTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/GossipedRoleCaseInsensitivityTests.cs
@@ -149,7 +149,7 @@ public sealed class GossipedRoleCaseInsensitivityTests
}),
$"redundancy-{Guid.NewGuid():N}");
- var snapshot = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(15));
+ var snapshot = await tcs.Task.WaitAsync(TimeSpan.FromSeconds(15), TestContext.Current.CancellationToken);
var node = snapshot.Nodes.ShouldHaveSingleItem();
node.Role.ShouldBe(
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Harness/ControlPlaneTestHarness.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Harness/ControlPlaneTestHarness.cs
index d98828a01..c073e5803 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Harness/ControlPlaneTestHarness.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/Harness/ControlPlaneTestHarness.cs
@@ -1,6 +1,6 @@
using Akka.Cluster;
using Akka.TestKit;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Microsoft.EntityFrameworkCore;
using ZB.MOM.WW.OtOpcUa.Configuration;
@@ -8,7 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.ControlPlane.Tests.Harness;
///
/// Akka TestKit fixture for ControlPlane actor tests. Provides:
-/// - A test ActorSystem (xunit2 TestKit) wired with PubSub/Cluster extensions.
+/// - A test ActorSystem (xunit.v3 TestKit) wired with PubSub/Cluster extensions.
/// - A fresh in-memory per harness instance.
/// - An the actors can hold.
///
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ManualFailoverServiceTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ManualFailoverServiceTests.cs
index c2f088529..e016bd323 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ManualFailoverServiceTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ManualFailoverServiceTests.cs
@@ -58,7 +58,7 @@ public sealed class ManualFailoverServiceTests : IAsyncLifetime
}
""");
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
// Order matters: the seed forms the cluster and is therefore the oldest member.
_oldest = ActorSystem.Create("manual-failover", NodeConfig(OldestPort, "manual-failover", OldestPort));
@@ -69,7 +69,7 @@ public sealed class ManualFailoverServiceTests : IAsyncLifetime
await WaitForUpAsync(_youngest, expectedMembers: 2);
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (_youngest is not null) await _youngest.Terminate();
if (_oldest is not null) await _oldest.Terminate();
@@ -128,7 +128,7 @@ public sealed class ManualFailoverServiceTests : IAsyncLifetime
// The leaving node runs CoordinatedShutdown and terminates — that is what makes the process
// exit and be restarted as the youngest member.
- await _oldest!.WhenTerminated.WaitAsync(TimeSpan.FromSeconds(30));
+ await _oldest!.WhenTerminated.WaitAsync(TimeSpan.FromSeconds(30), TestContext.Current.CancellationToken);
// ... and the survivor is now what RedundancyStateActor names Primary.
var snapshot = await CaptureSnapshotAsync(_youngest!);
@@ -192,7 +192,7 @@ public sealed class ManualFailoverServiceTests : IAsyncLifetime
snapshotPrimary.ShouldBe(elected.ToString(), "the UI panel must name the same node the button acts on");
// The dry run really was dry.
- await Task.Delay(500);
+ await Task.Delay(500, TestContext.Current.CancellationToken);
Akka.Cluster.Cluster.Get(_oldest!).State.Members
.Count(m => m.Status == MemberStatus.Up)
.ShouldBe(2, "a dry run must not remove anyone");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyPrimaryElectionTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyPrimaryElectionTests.cs
index 73be49736..30b172f4a 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyPrimaryElectionTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyPrimaryElectionTests.cs
@@ -74,7 +74,7 @@ public sealed class RedundancyPrimaryElectionTests : IAsyncLifetime
}
""");
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
// Order matters: the seed forms the cluster and is therefore the oldest member.
_oldest = ActorSystem.Create("redundancy-election", NodeConfig(OldestPort));
@@ -85,7 +85,7 @@ public sealed class RedundancyPrimaryElectionTests : IAsyncLifetime
await WaitForUpAsync(_youngest, expectedMembers: 2);
}
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
if (_youngest is not null) await _youngest.Terminate();
if (_oldest is not null) await _oldest.Terminate();
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyStateActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyStateActorTests.cs
index f48b7a5d9..e8c70f602 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyStateActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/RedundancyStateActorTests.cs
@@ -23,7 +23,7 @@ public sealed class RedundancyStateActorTests : ControlPlaneActorTestBase
Sys.ActorOf(RedundancyStateActor.Props(broadcast: msg => probe.Ref.Tell(msg)),
"redundancy-actor");
- var msg = probe.ExpectMsg(TimeSpan.FromSeconds(3));
+ var msg = probe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
msg.Nodes.ShouldNotBeNull();
msg.CorrelationId.Value.ShouldNotBe(Guid.Empty);
}
@@ -37,10 +37,10 @@ public sealed class RedundancyStateActorTests : ControlPlaneActorTestBase
"redundancy-debounce");
// First publish should arrive within the debounce window.
- probe.ExpectMsg(TimeSpan.FromSeconds(3));
+ probe.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
// After debounce settles, no more events are fired by a quiescent cluster.
- probe.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
+ probe.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
}
///
@@ -60,10 +60,10 @@ public sealed class RedundancyStateActorTests : ControlPlaneActorTestBase
"redundancy-heartbeat");
// First publish: the change-driven self-join snapshot.
- probe.ExpectMsg(TimeSpan.FromSeconds(2));
+ probe.ExpectMsg(TimeSpan.FromSeconds(2), cancellationToken: TestContext.Current.CancellationToken);
// Second publish: the periodic heartbeat re-publish, with NO new cluster event sent.
- probe.ExpectMsg(TimeSpan.FromSeconds(2));
+ probe.ExpectMsg(TimeSpan.FromSeconds(2), cancellationToken: TestContext.Current.CancellationToken);
}
///
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests.csproj b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests.csproj
index 1e6c1d352..2b051af8e 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests.csproj
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests.csproj
@@ -7,11 +7,10 @@
-
-
+
-
+
all
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/DriverResilienceStatusPublisherServiceTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/DriverResilienceStatusPublisherServiceTests.cs
index f9e195ace..94834d955 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/DriverResilienceStatusPublisherServiceTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/DriverResilienceStatusPublisherServiceTests.cs
@@ -68,7 +68,7 @@ public sealed class DriverResilienceStatusPublisherServiceTests
public async Task ExecuteAsync_emits_Resilience_item_per_published_snapshot()
{
// Plain self-joined single-node cluster (mirrors SecretsReplicationRegistrationTests — the
- // xunit.v3 project cannot use Akka.TestKit.Xunit2). public-hostname is load-bearing for the bind.
+ // xunit.v3 project cannot use Akka.TestKit.Xunit). public-hostname is load-bearing for the bind.
var hocon = ConfigurationFactory.ParseString("""
akka {
loglevel = WARNING
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/SecretsReplicationRegistrationTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/SecretsReplicationRegistrationTests.cs
index fcbe25376..5111174fe 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/SecretsReplicationRegistrationTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests/SecretsReplicationRegistrationTests.cs
@@ -128,7 +128,7 @@ public sealed class SecretsReplicationRegistrationTests
// the hook, and prove the replication actor exists. On 0.2.0 this fails because the actor
// is never spawned (inert replicator); on 0.2.1 it deadlocks in the resolve (scadaproj#1).
//
- // Akka.TestKit.Xunit2 is xunit-v2-only and this project is on xunit.v3 (CS0433), so this
+ // Akka.TestKit.Xunit is xunit-v2-only and this project is on xunit.v3 (CS0433), so this
// uses a plain self-joined single-node cluster — which is also all the actor needs: its
// constructor gets the DistributedPubSub mediator, no peers required.
ActorSystem system = ActorSystem.Create(
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Engines/VirtualTagToVirtualTagFlowTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Engines/VirtualTagToVirtualTagFlowTests.cs
index 71f8748be..70674ab35 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Engines/VirtualTagToVirtualTagFlowTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Engines/VirtualTagToVirtualTagFlowTests.cs
@@ -1,5 +1,5 @@
using Akka.Actor;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Microsoft.Extensions.Logging.Abstractions;
using Serilog;
using Shouldly;
@@ -62,7 +62,7 @@ public sealed class VirtualTagToVirtualTagFlowTests : TestKit
mux.Tell(Driver(5));
publish.FishForMessage(
m => m.NodeId == AKey && Equals(m.Value, 10d), TimeSpan.FromMilliseconds(500));
- }, Budget, TimeSpan.FromMilliseconds(50));
+ }, Budget, TimeSpan.FromMilliseconds(50), TestContext.Current.CancellationToken);
NextFor(publish, BKey, m => Equals(m.Value, 11d) && m.StatusCode == OpcUaStatus.Good);
// A's input changes: B re-evaluates against A's NEW value (ctx.GetTag returns A's current value).
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Grpc/NodeCommandGrpcServiceTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Grpc/NodeCommandGrpcServiceTests.cs
index a6a15050f..301128686 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Grpc/NodeCommandGrpcServiceTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Grpc/NodeCommandGrpcServiceTests.cs
@@ -1,5 +1,5 @@
using Akka.Hosting;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Grpc.Core;
using Microsoft.Extensions.Logging.Abstractions;
using Shouldly;
@@ -54,16 +54,16 @@ public sealed class NodeCommandGrpcServiceTests : TestKit
var alarm = new AlarmCommand("alarm-7", "Acknowledge", "carol", "looked at it", null);
(await service.Execute(MeshTransportDtoMapper.ToEnvelope(dispatch), Ctx())).ShouldNotBeNull();
- probe.ExpectMsg().ShouldBe(dispatch);
+ probe.ExpectMsg(cancellationToken: TestContext.Current.CancellationToken).ShouldBe(dispatch);
await service.Execute(MeshTransportDtoMapper.ToEnvelope(restart), Ctx());
- probe.ExpectMsg().ShouldBe(restart);
+ probe.ExpectMsg(cancellationToken: TestContext.Current.CancellationToken).ShouldBe(restart);
await service.Execute(MeshTransportDtoMapper.ToEnvelope(reconnect), Ctx());
- probe.ExpectMsg().ShouldBe(reconnect);
+ probe.ExpectMsg(cancellationToken: TestContext.Current.CancellationToken).ShouldBe(reconnect);
await service.Execute(MeshTransportDtoMapper.ToEnvelope(alarm, AlarmCorrelation), Ctx());
- probe.ExpectMsg().ShouldBe(alarm);
+ probe.ExpectMsg(cancellationToken: TestContext.Current.CancellationToken).ShouldBe(alarm);
}
[Fact]
@@ -94,7 +94,7 @@ public sealed class NodeCommandGrpcServiceTests : TestKit
new CommandEnvelope { CorrelationId = Guid.NewGuid().ToString("N") }, Ctx()));
ex.StatusCode.ShouldBe(StatusCode.InvalidArgument);
- probe.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+ probe.ExpectNoMsg(TimeSpan.FromMilliseconds(200), TestContext.Current.CancellationToken);
}
[Theory]
@@ -109,7 +109,7 @@ public sealed class NodeCommandGrpcServiceTests : TestKit
var ex = await Should.ThrowAsync(() => service.Execute(envelope, Ctx()));
ex.StatusCode.ShouldBe(StatusCode.InvalidArgument);
- probe.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
+ probe.ExpectNoMsg(TimeSpan.FromMilliseconds(200), TestContext.Current.CancellationToken);
}
public static TheoryData UndecodableEnvelopes() =>
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Health/ActiveTierRegistrationTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Health/ActiveTierRegistrationTests.cs
index bca0ea885..39e978c6d 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Health/ActiveTierRegistrationTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Health/ActiveTierRegistrationTests.cs
@@ -1,6 +1,6 @@
using Akka.Actor;
using Akka.Configuration;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Options;
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ApiKeyAuthenticationTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ApiKeyAuthenticationTests.cs
index 54e709f0e..b5905c34c 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ApiKeyAuthenticationTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ApiKeyAuthenticationTests.cs
@@ -106,7 +106,7 @@ public sealed class ApiKeyAuthenticationTests
{
var (presented, store) = SetUp(NodePermissions.WriteOperate, NodeAclScopeKind.Cluster);
- var result = await Auth(store).AuthenticateUserNameAsync("apikey", presented, default);
+ var result = await Auth(store).AuthenticateUserNameAsync("apikey", presented, TestContext.Current.CancellationToken);
result.Success.ShouldBeTrue();
result.DisplayName.ShouldBe(Principal);
@@ -117,7 +117,7 @@ public sealed class ApiKeyAuthenticationTests
public async Task The_wrong_username_is_denied()
{
var (presented, store) = SetUp();
- var result = await Auth(store).AuthenticateUserNameAsync("alice", presented, default);
+ var result = await Auth(store).AuthenticateUserNameAsync("alice", presented, TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
}
@@ -127,10 +127,10 @@ public sealed class ApiKeyAuthenticationTests
var (presented, store) = SetUp();
var auth = Auth(store);
- var wrongSecret = await auth.AuthenticateUserNameAsync("apikey", $"otua_{store.KeyId}_wrong", default);
- var noSuchKey = await auth.AuthenticateUserNameAsync("apikey", "otua_ffffffff_whatever", default);
- var malformed = await auth.AuthenticateUserNameAsync("apikey", "not-a-key", default);
- var empty = await auth.AuthenticateUserNameAsync("apikey", "", default);
+ var wrongSecret = await auth.AuthenticateUserNameAsync("apikey", $"otua_{store.KeyId}_wrong", TestContext.Current.CancellationToken);
+ var noSuchKey = await auth.AuthenticateUserNameAsync("apikey", "otua_ffffffff_whatever", TestContext.Current.CancellationToken);
+ var malformed = await auth.AuthenticateUserNameAsync("apikey", "not-a-key", TestContext.Current.CancellationToken);
+ var empty = await auth.AuthenticateUserNameAsync("apikey", "", TestContext.Current.CancellationToken);
foreach (var r in new[] { wrongSecret, noSuchKey, malformed, empty })
{
@@ -141,7 +141,7 @@ public sealed class ApiKeyAuthenticationTests
}
// ...and the valid one still works, so the above is not passing because everything is denied.
- (await auth.AuthenticateUserNameAsync("apikey", presented, default)).Success.ShouldBeTrue();
+ (await auth.AuthenticateUserNameAsync("apikey", presented, TestContext.Current.CancellationToken)).Success.ShouldBeTrue();
}
[Fact]
@@ -150,7 +150,7 @@ public sealed class ApiKeyAuthenticationTests
// The interface contract forbids throwing — an exception escapes into the SDK session-activation
// path and surfaces as BadInternalError instead of a clean rejection.
var store = new ThrowingApiKeyStore();
- var result = await Auth(store).AuthenticateUserNameAsync("apikey", "otua_aabbccdd_secret", default);
+ var result = await Auth(store).AuthenticateUserNameAsync("apikey", "otua_aabbccdd_secret", TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
result.Error.ShouldBe(ApiKeyOpcUaUserAuthenticator.DenyMessage);
@@ -165,7 +165,7 @@ public sealed class ApiKeyAuthenticationTests
Options.Create(new ApiKeyOptions { Username = "apikey", Pepper = "" }),
NullLogger.Instance);
- (await auth.AuthenticateUserNameAsync("apikey", presented, default)).Success.ShouldBeFalse();
+ (await auth.AuthenticateUserNameAsync("apikey", presented, TestContext.Current.CancellationToken)).Success.ShouldBeFalse();
}
// ---------- anonymous as a normal principal (D3) ----------
@@ -183,7 +183,7 @@ public sealed class ApiKeyAuthenticationTests
PermissionFlags = NodePermissions.WriteOperate,
});
- var result = await Auth(store).AuthenticateAnonymousAsync(default);
+ var result = await Auth(store).AuthenticateAnonymousAsync(TestContext.Current.CancellationToken);
result.Success.ShouldBeTrue();
result.DisplayName.ShouldBe(OpcUaPrincipals.Anonymous);
@@ -197,7 +197,7 @@ public sealed class ApiKeyAuthenticationTests
// Today's behaviour preserved: it connects, and every role-gated operation denies.
var (_, store) = SetUp();
- var result = await Auth(store).AuthenticateAnonymousAsync(default);
+ var result = await Auth(store).AuthenticateAnonymousAsync(TestContext.Current.CancellationToken);
result.Success.ShouldBeTrue();
result.Roles.ShouldBeEmpty();
@@ -208,7 +208,7 @@ public sealed class ApiKeyAuthenticationTests
{
// Deliberately NOT admit-with-no-roles. That is the pre-#520 behaviour, and defaulting to it
// exactly when we cannot read what anonymous may do stops being harmless once reads are gated.
- var result = await Auth(new ThrowingApiKeyStore()).AuthenticateAnonymousAsync(default);
+ var result = await Auth(new ThrowingApiKeyStore()).AuthenticateAnonymousAsync(TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
}
@@ -227,7 +227,7 @@ public sealed class ApiKeyAuthenticationTests
CreatedUtc = DateTime.UtcNow,
};
- var result = await Auth(new FakeApiKeyStore(key, [])).AuthenticateUserNameAsync("apikey", presented, default);
+ var result = await Auth(new FakeApiKeyStore(key, [])).AuthenticateUserNameAsync("apikey", presented, TestContext.Current.CancellationToken);
// Otherwise a credentialled client silently inherits whatever anonymous was granted.
result.Success.ShouldBeFalse();
@@ -241,7 +241,7 @@ public sealed class ApiKeyAuthenticationTests
// Interface-typed on purpose: a default interface implementation is only reachable through the
// interface, which is how OpcUaApplicationHost holds it.
IOpcUaUserAuthenticator sut = NullOpcUaUserAuthenticator.Instance;
- var result = await sut.AuthenticateAnonymousAsync(default);
+ var result = await sut.AuthenticateAnonymousAsync(TestContext.Current.CancellationToken);
result.Success.ShouldBeTrue();
result.Roles.ShouldBeEmpty();
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ArtifactApiKeyStoreTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ArtifactApiKeyStoreTests.cs
index 9cffddb05..275abe34b 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ArtifactApiKeyStoreTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ArtifactApiKeyStoreTests.cs
@@ -26,7 +26,7 @@ public sealed class ArtifactApiKeyStoreTests
{
var sut = new ArtifactApiKeyStore(new DataPlaneAuthorityState());
- (await sut.FindAsync("abc", Now, default)).ShouldBeNull();
+ (await sut.FindAsync("abc", Now, TestContext.Current.CancellationToken)).ShouldBeNull();
}
[Fact]
@@ -37,7 +37,7 @@ public sealed class ArtifactApiKeyStoreTests
[Key("abc", "scadabridge-dcl")],
[Acl("acl-1", "scadabridge-dcl", NodeAclScopeKind.Cluster, NodePermissions.WriteOperate)], NoScopePaths);
- var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, default);
+ var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found.ShouldNotBeNull();
found!.Key.Principal.ShouldBe("scadabridge-dcl");
@@ -67,7 +67,7 @@ public sealed class ArtifactApiKeyStoreTests
Acl("acl-equipment", "p", NodeAclScopeKind.Equipment, NodePermissions.WriteOperate),
], NoScopePaths);
- var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, default);
+ var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.Select(g => g.NodeAclId).ShouldBe(["acl-cluster", "acl-equipment"], ignoreOrder: true);
}
@@ -91,7 +91,7 @@ public sealed class ArtifactApiKeyStoreTests
[Acl("acl-equipment", "p", NodeAclScopeKind.Equipment, NodePermissions.WriteOperate)],
NoScopePaths);
- var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, default);
+ var found = await new ArtifactApiKeyStore(state).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.ShouldHaveSingleItem();
ApiKeyInterimRoleMapper.Map(found.Grants, "p").ShouldBeEmpty();
@@ -106,13 +106,13 @@ public sealed class ArtifactApiKeyStoreTests
var sut = new ArtifactApiKeyStore(state);
state.Apply("cluster-a", "rev-1", [Key("abc", "p")], [], NoScopePaths);
- (await sut.FindAsync("abc", Now, default)).ShouldNotBeNull();
+ (await sut.FindAsync("abc", Now, TestContext.Current.CancellationToken)).ShouldNotBeNull();
var revoked = Key("abc", "p");
revoked.Enabled = false;
state.Apply("cluster-a", "rev-2", [revoked], [], NoScopePaths);
- (await sut.FindAsync("abc", Now, default)).ShouldBeNull();
+ (await sut.FindAsync("abc", Now, TestContext.Current.CancellationToken)).ShouldBeNull();
}
[Fact]
@@ -124,7 +124,7 @@ public sealed class ArtifactApiKeyStoreTests
[Acl("acl-anon", OpcUaPrincipals.Anonymous, NodeAclScopeKind.Cluster, NodePermissions.Read)],
NoScopePaths);
- var grants = await new ArtifactApiKeyStore(state).FindGrantsAsync(OpcUaPrincipals.Anonymous, default);
+ var grants = await new ArtifactApiKeyStore(state).FindGrantsAsync(OpcUaPrincipals.Anonymous, TestContext.Current.CancellationToken);
grants.ShouldHaveSingleItem().PermissionFlags.ShouldBe(NodePermissions.Read);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreKnownIdTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreKnownIdTests.cs
index 8d08df5ee..6eb109028 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreKnownIdTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreKnownIdTests.cs
@@ -25,13 +25,13 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var clock = new FakeClock(T0);
var sut = Bounded(inner, clock, cacheSeconds: 5);
- (await sut.FindAsync("k-guess-1", T0.UtcDateTime, default)).ShouldBeNull();
- (await sut.FindAsync("k-guess-2", T0.UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-1", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-2", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(0, "unknown ids never reach the store");
inner.ListCalls.ShouldBe(1, "one set load serves every unknown id inside the TTL");
// Positive control: the real id reaches the store and is found.
- (await sut.FindAsync("k-real", T0.UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync("k-real", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
inner.FindCalls.ShouldBe(1);
}
@@ -42,15 +42,15 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var clock = new FakeClock(T0);
var sut = Bounded(inner, clock, cacheSeconds: 5);
- (await sut.FindAsync("k-new", T0.UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-new", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.Mint("k-new");
// Still inside the TTL: the stale set refuses it (the documented window).
clock.Advance(TimeSpan.FromSeconds(3));
- (await sut.FindAsync("k-new", clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-new", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(0);
clock.Advance(TimeSpan.FromSeconds(3));
- (await sut.FindAsync("k-new", clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync("k-new", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
inner.ListCalls.ShouldBe(2);
}
@@ -62,20 +62,20 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var sut = Bounded(inner, clock, cacheSeconds: 5);
// No set yet and the load fails: the per-id path runs (old behaviour), nothing is wedged.
- (await sut.FindAsync("k-guess", T0.UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(1);
sut.KnownKeyIds.ShouldBeNull();
inner.ListThrows = false;
clock.Advance(TimeSpan.FromSeconds(6));
- (await sut.FindAsync("k-guess-2", clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-2", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
sut.KnownKeyIds.ShouldNotBeNull();
inner.FindCalls.ShouldBe(1, "once the set loaded, the guess was refused in memory");
// A later failed refresh keeps the previous set in force.
inner.ListThrows = true;
clock.Advance(TimeSpan.FromSeconds(6));
- (await sut.FindAsync("k-guess-3", clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-3", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(1);
}
@@ -88,7 +88,7 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var sut = Bounded(inner, clock, cacheSeconds: 0, missBurst: 3, refillPerSecond: 1);
for (var i = 0; i < 3; i++)
- (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(3);
// Budget exhausted: refused without a store read, as a throw the authenticator denies on.
@@ -97,14 +97,14 @@ public sealed class BoundedApiKeyStoreKnownIdTests
// Refill: one second restores one token.
clock.Advance(TimeSpan.FromSeconds(1));
- (await sut.FindAsync("k-guess-10", clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-10", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(4);
// A hit is not a miss: it reaches the store even with the bucket empty? No — it needs a token to
// be attempted, but the token is refunded, so the next attempt still has it. Prove the refund.
clock.Advance(TimeSpan.FromSeconds(1));
- (await sut.FindAsync("k-real", clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
- (await sut.FindAsync("k-guess-11", clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-real", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
+ (await sut.FindAsync("k-guess-11", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(6);
}
@@ -114,8 +114,8 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var inner = new ListingStore("k-real");
var sut = Bounded(inner, new FakeClock(T0), cacheSeconds: 0, missBurst: 0);
- (await sut.FindAsync("k-guess", T0.UtcDateTime, default)).ShouldBeNull();
- (await sut.FindAsync("k-guess", T0.UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
+ (await sut.FindAsync("k-guess", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(2);
inner.ListCalls.ShouldBe(0);
}
@@ -139,13 +139,13 @@ public sealed class BoundedApiKeyStoreKnownIdTests
var unlisting = new ListingStore("k-real") { SupportsListing = false };
var first = new BoundedApiKeyStore(unlisting, options, NullLogger.Instance, clock, guard);
- (await first.FindAsync("k-guess", T0.UtcDateTime, default)).ShouldBeNull();
+ (await first.FindAsync("k-guess", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
unlisting.FindCalls.ShouldBe(1, "no set: the per-id path ran");
guard.KnownIdSet.ShouldBeTrue("the shared options object is never written");
var listing = new ListingStore("k-real");
var second = new BoundedApiKeyStore(listing, options, NullLogger.Instance, clock, guard);
- (await second.FindAsync("k-guess", T0.UtcDateTime, default)).ShouldBeNull();
+ (await second.FindAsync("k-guess", T0.UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
listing.FindCalls.ShouldBe(0, "the second decorator still refuses unknown ids in memory");
listing.ListCalls.ShouldBe(1);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStorePerEndpointTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStorePerEndpointTests.cs
index 2a43369d3..d506a0c68 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStorePerEndpointTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStorePerEndpointTests.cs
@@ -31,7 +31,7 @@ public sealed class BoundedApiKeyStorePerEndpointTests
var sut = Bounded(inner, new FakeClock(T0), missBurst: 100, perEndpointBurst: 3);
for (var i = 0; i < 3; i++)
- (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, Noisy, default)).ShouldBeNull();
+ (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(3);
var refused = await Should.ThrowAsync(
@@ -40,7 +40,7 @@ public sealed class BoundedApiKeyStorePerEndpointTests
inner.FindCalls.ShouldBe(3, "the exhausted client is refused without a store read");
// Positive control: another client still reaches the store.
- (await sut.FindAsync("k-guess-q", T0.UtcDateTime, Quiet, default)).ShouldBeNull();
+ (await sut.FindAsync("k-guess-q", T0.UtcDateTime, Quiet, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(4);
}
@@ -51,8 +51,8 @@ public sealed class BoundedApiKeyStorePerEndpointTests
var inner = new UnlistingStore("k-real");
var sut = Bounded(inner, new FakeClock(T0), missBurst: 2, perEndpointBurst: 10);
- (await sut.FindAsync("k-a", T0.UtcDateTime, Noisy, default)).ShouldBeNull();
- (await sut.FindAsync("k-b", T0.UtcDateTime, remoteAddress: null, default)).ShouldBeNull();
+ (await sut.FindAsync("k-a", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
+ (await sut.FindAsync("k-b", T0.UtcDateTime, remoteAddress: null, TestContext.Current.CancellationToken)).ShouldBeNull();
var refused = await Should.ThrowAsync(
() => sut.FindAsync("k-c", T0.UtcDateTime, Quiet, default));
@@ -70,14 +70,14 @@ public sealed class BoundedApiKeyStorePerEndpointTests
var sut = Bounded(inner, clock, missBurst: 100, perEndpointBurst: 2, perEndpointRefill: 1);
for (var i = 0; i < 5; i++)
- (await sut.FindAsync("k-real", T0.UtcDateTime, Noisy, default)).ShouldNotBeNull();
+ (await sut.FindAsync("k-real", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldNotBeNull();
- (await sut.FindAsync("k-g1", T0.UtcDateTime, Noisy, default)).ShouldBeNull();
- (await sut.FindAsync("k-g2", T0.UtcDateTime, Noisy, default)).ShouldBeNull();
+ (await sut.FindAsync("k-g1", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
+ (await sut.FindAsync("k-g2", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
await Should.ThrowAsync(() => sut.FindAsync("k-g3", T0.UtcDateTime, Noisy, default));
clock.Advance(TimeSpan.FromSeconds(1));
- (await sut.FindAsync("k-g4", clock.GetUtcNow().UtcDateTime, Noisy, default)).ShouldBeNull();
+ (await sut.FindAsync("k-g4", clock.GetUtcNow().UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(8);
}
@@ -89,7 +89,7 @@ public sealed class BoundedApiKeyStorePerEndpointTests
var sut = Bounded(inner, new FakeClock(T0), missBurst: 100, perEndpointBurst: 0);
for (var i = 0; i < 20; i++)
- (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, Noisy, default)).ShouldBeNull();
+ (await sut.FindAsync($"k-guess-{i}", T0.UtcDateTime, Noisy, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.FindCalls.ShouldBe(20);
}
@@ -107,7 +107,7 @@ public sealed class BoundedApiKeyStorePerEndpointTests
NullLogger.Instance);
var result = await authenticator.AuthenticateUserNameAsync(
- "apikey", "otua_k-guess_secret", new IPEndPoint(Noisy, 50123), default);
+ "apikey", "otua_k-guess_secret", new IPEndPoint(Noisy, 50123), TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
store.LastAddress.ShouldBe(Noisy);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreTests.cs
index 652019056..704e5a291 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/BoundedApiKeyStoreTests.cs
@@ -54,7 +54,7 @@ public sealed class BoundedApiKeyStoreTests
var auth = Auth(Bounded(inner, timeoutMs: 150, cacheSeconds: 0));
var result = await auth.AuthenticateUserNameAsync("apikey", presented, CancellationToken.None)
- .WaitAsync(TimeSpan.FromSeconds(5));
+ .WaitAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
result.Error.ShouldBe(ApiKeyOpcUaUserAuthenticator.DenyMessage);
@@ -95,10 +95,10 @@ public sealed class BoundedApiKeyStoreTests
var pending = auth.AuthenticateUserNameAsync("apikey", presented, CancellationToken.None);
// Let the deadline pass, THEN hand the inner store its (valid) answer.
- await Task.Delay(400);
+ await Task.Delay(400, TestContext.Current.CancellationToken);
gate.SetResult();
- var result = await pending.WaitAsync(TimeSpan.FromSeconds(5));
+ var result = await pending.WaitAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
result.Error.ShouldBe(ApiKeyOpcUaUserAuthenticator.DenyMessage);
}
@@ -167,10 +167,10 @@ public sealed class BoundedApiKeyStoreTests
// The abandoned inner task now completes, with a perfectly valid key, into nobody's hands.
inner.Release();
- await inner.Completed.WaitAsync(TimeSpan.FromSeconds(2));
+ await inner.Completed.WaitAsync(TimeSpan.FromSeconds(2), TestContext.Current.CancellationToken);
// Well inside the 60 s TTL: a cached late answer would make this a hit.
- (await sut.FindAsync(inner.KeyId, DateTime.UtcNow, default).WaitAsync(TimeSpan.FromSeconds(2)))
+ (await sut.FindAsync(inner.KeyId, DateTime.UtcNow, TestContext.Current.CancellationToken).WaitAsync(TimeSpan.FromSeconds(2), TestContext.Current.CancellationToken))
.ShouldNotBeNull("the store answers immediately once released");
inner.Calls.ShouldBe(2, "the abandoned lookup must not have populated the cache");
}
@@ -197,12 +197,12 @@ public sealed class BoundedApiKeyStoreTests
.WaitAsync(TimeSpan.FromSeconds(2)));
inner.ReleaseWithFault(new InvalidOperationException("SqlClient gave up"));
- await inner.Completed.WaitAsync(TimeSpan.FromSeconds(2));
+ await inner.Completed.WaitAsync(TimeSpan.FromSeconds(2), TestContext.Current.CancellationToken);
// The continuation is a separate task from the one just awaited; give it a moment to run.
var deadline = Stopwatch.StartNew();
while (log.Lines.Count == 0 && deadline.Elapsed < TimeSpan.FromSeconds(2))
- await Task.Delay(10);
+ await Task.Delay(10, TestContext.Current.CancellationToken);
log.Lines.ShouldContain(line => line.Contains("abandoned", StringComparison.OrdinalIgnoreCase));
}
@@ -222,11 +222,11 @@ public sealed class BoundedApiKeyStoreTests
var pending = auth.AuthenticateUserNameAsync("apikey", presented, CancellationToken.None);
// Far longer than any deadline this class configures; an active bound would have denied by now.
- await Task.Delay(300);
+ await Task.Delay(300, TestContext.Current.CancellationToken);
pending.IsCompleted.ShouldBeFalse("a disabled deadline must not cancel a slow lookup");
gate.SetResult();
- (await pending.WaitAsync(TimeSpan.FromSeconds(5))).Success.ShouldBeTrue();
+ (await pending.WaitAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken)).Success.ShouldBeTrue();
}
/// The anonymous activation path gets the same deadline, and the same denial.
@@ -242,7 +242,7 @@ public sealed class BoundedApiKeyStoreTests
var auth = Auth(Bounded(inner, timeoutMs: 150, cacheSeconds: 0));
var result = await auth.AuthenticateAnonymousAsync(CancellationToken.None)
- .WaitAsync(TimeSpan.FromSeconds(5));
+ .WaitAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
result.Success.ShouldBeFalse();
}
@@ -257,9 +257,9 @@ public sealed class BoundedApiKeyStoreTests
var clock = new FakeClock(new DateTimeOffset(2026, 8, 20, 12, 0, 0, TimeSpan.Zero));
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 5, clock);
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
clock.Advance(TimeSpan.FromSeconds(2));
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
inner.Calls.ShouldBe(1);
}
@@ -280,18 +280,18 @@ public sealed class BoundedApiKeyStoreTests
var clock = new FakeClock(new DateTimeOffset(2026, 8, 20, 12, 0, 0, TimeSpan.Zero));
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 5, clock);
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default))
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken))
.ShouldNotBeNull("non-vacuity: the key really was usable before the revocation");
inner.Revoked = true;
// Still inside the TTL — the documented, accepted staleness window.
clock.Advance(TimeSpan.FromSeconds(3));
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
// Past it — the store is re-read and the revocation lands.
clock.Advance(TimeSpan.FromSeconds(3));
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.Calls.ShouldBe(2);
}
@@ -304,7 +304,7 @@ public sealed class BoundedApiKeyStoreTests
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 0, clock);
for (var i = 0; i < 3; i++)
- await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default);
+ await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken);
inner.Calls.ShouldBe(3);
}
@@ -328,7 +328,7 @@ public sealed class BoundedApiKeyStoreTests
() => sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default));
// Same instant — a cached fault would still be "fresh" here, so the clock cannot rescue this.
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
inner.Calls.ShouldBe(2);
}
@@ -340,12 +340,12 @@ public sealed class BoundedApiKeyStoreTests
var clock = new FakeClock(new DateTimeOffset(2026, 8, 20, 12, 0, 0, TimeSpan.Zero));
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 5, clock);
- await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, default);
- await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, default);
+ await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, TestContext.Current.CancellationToken);
+ await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, TestContext.Current.CancellationToken);
inner.Calls.ShouldBe(1);
clock.Advance(TimeSpan.FromSeconds(6));
- await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, default);
+ await sut.FindGrantsAsync(OpcUaPrincipals.Anonymous, TestContext.Current.CancellationToken);
inner.Calls.ShouldBe(2);
}
@@ -369,15 +369,15 @@ public sealed class BoundedApiKeyStoreTests
guard: new ApiKeyStoreGuardOptions { MissBurst = 0 });
// Seed the real key, then flood past the ceiling with ids that do not exist.
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
for (var i = 0; i < BoundedApiKeyStore.MaxCacheEntries + 1; i++)
- await sut.FindAsync($"ghost-{i}", clock.GetUtcNow().UtcDateTime, default);
+ await sut.FindAsync($"ghost-{i}", clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken);
var callsAfterFlood = inner.Calls;
// Still correct after the clear — and the real key was evicted, so it is re-read rather than
// served from a cache the flood was supposed to have emptied.
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldNotBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldNotBeNull();
inner.Calls.ShouldBe(callsAfterFlood + 1);
}
@@ -406,7 +406,7 @@ public sealed class BoundedApiKeyStoreTests
var clock = new FakeClock(start);
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 60, clock);
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default))
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken))
.ShouldNotBeNull("non-vacuity: the key was usable and IS now cached");
inner.Revoked = true;
@@ -414,7 +414,7 @@ public sealed class BoundedApiKeyStoreTests
// Past ExpiresUtc (+2 s) but far inside the 60 s TTL — the entry is still "fresh" to the cache.
clock.Advance(TimeSpan.FromSeconds(5));
- (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default)).ShouldBeNull();
+ (await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken)).ShouldBeNull();
inner.Calls.ShouldBe(2, "the expired entry must be re-read, not served");
}
@@ -449,10 +449,10 @@ public sealed class BoundedApiKeyStoreTests
using var meter = new MeterRecorder();
var sut = Bounded(inner, timeoutMs: 0, cacheSeconds: 5, clock);
- await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default);
+ await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken);
meter.WithOutcome("cache_hit").ShouldBe(0, "the first call is a miss");
- await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, default);
+ await sut.FindAsync(inner.KeyId, clock.GetUtcNow().UtcDateTime, TestContext.Current.CancellationToken);
meter.WithOutcome("cache_hit").ShouldBe(1);
}
@@ -468,7 +468,7 @@ public sealed class BoundedApiKeyStoreTests
using var meter = new MeterRecorder();
var sut = Bounded(inner, timeoutMs: 2000, cacheSeconds: 0);
- await sut.FindAsync(inner.KeyId, DateTime.UtcNow, default);
+ await sut.FindAsync(inner.KeyId, DateTime.UtcNow, TestContext.Current.CancellationToken);
meter.Total.ShouldBe(0);
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ConfigDbApiKeyStoreTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ConfigDbApiKeyStoreTests.cs
index 506284eee..f6f511645 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ConfigDbApiKeyStoreTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/ConfigDbApiKeyStoreTests.cs
@@ -52,7 +52,7 @@ public sealed class ConfigDbApiKeyStoreTests
keys: [Key("abc", "scadabridge-dcl")],
acls: [Acl("acl-other", OtherCluster, "scadabridge-dcl", NodeAclScopeKind.Cluster, NodePermissions.WriteOperate)]);
- var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, default);
+ var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, TestContext.Current.CancellationToken);
// The KEY still resolves — keys are fleet-wide credentials (ApiKey carries no ClusterId); it is
// the grants that are cluster-bound. Asserting a null lookup here would pass for the wrong reason.
@@ -76,7 +76,7 @@ public sealed class ConfigDbApiKeyStoreTests
Acl("acl-other", OtherCluster, "scadabridge-dcl", NodeAclScopeKind.Cluster, NodePermissions.WriteOperate),
]);
- var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, default);
+ var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.ShouldHaveSingleItem().NodeAclId.ShouldBe("acl-mine");
}
@@ -98,7 +98,7 @@ public sealed class ConfigDbApiKeyStoreTests
Acl("acl-b", OtherCluster, "p", NodeAclScopeKind.Cluster, NodePermissions.WriteOperate),
]);
- var found = await new ConfigDbApiKeyStore(factory, clusterId: null).FindAsync("abc", Now, default);
+ var found = await new ConfigDbApiKeyStore(factory, clusterId: null).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.Select(g => g.NodeAclId).ShouldBe(["acl-a", "acl-b"], ignoreOrder: true);
}
@@ -119,7 +119,7 @@ public sealed class ConfigDbApiKeyStoreTests
keys: [Key("abc", "p")],
acls: [Acl("acl-mine", "SITE-A", "p", NodeAclScopeKind.Cluster, NodePermissions.Read)]);
- var found = await new ConfigDbApiKeyStore(factory, "site-a").FindAsync("abc", Now, default);
+ var found = await new ConfigDbApiKeyStore(factory, "site-a").FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.ShouldHaveSingleItem().NodeAclId.ShouldBe("acl-mine");
}
@@ -141,7 +141,7 @@ public sealed class ConfigDbApiKeyStoreTests
]);
var grants = await new ConfigDbApiKeyStore(factory, ThisCluster)
- .FindGrantsAsync(OpcUaPrincipals.Anonymous, default);
+ .FindGrantsAsync(OpcUaPrincipals.Anonymous, TestContext.Current.CancellationToken);
grants.ShouldHaveSingleItem().NodeAclId.ShouldBe("acl-anon-mine");
}
@@ -168,7 +168,7 @@ public sealed class ConfigDbApiKeyStoreTests
Acl("acl-equipment", ThisCluster, "p", NodeAclScopeKind.Equipment, NodePermissions.WriteOperate),
]);
- var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, default);
+ var found = await new ConfigDbApiKeyStore(factory, ThisCluster).FindAsync("abc", Now, TestContext.Current.CancellationToken);
found!.Grants.Select(g => g.NodeAclId).ShouldBe(["acl-cluster", "acl-equipment"], ignoreOrder: true);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/OtOpcUaServerHostedServiceStartFailureTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/OtOpcUaServerHostedServiceStartFailureTests.cs
index 341595d75..b705f82e2 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/OtOpcUaServerHostedServiceStartFailureTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/OpcUa/OtOpcUaServerHostedServiceStartFailureTests.cs
@@ -54,7 +54,7 @@ public sealed class OtOpcUaServerHostedServiceStartFailureTests
state.Status.ShouldBe(OpcUaEndpointStatus.Failed);
state.FailureReason.ShouldNotBeNullOrWhiteSpace();
- var probe = await new OpcUaEndpointHealthCheck(state).CheckHealthAsync(new HealthCheckContext());
+ var probe = await new OpcUaEndpointHealthCheck(state).CheckHealthAsync(new HealthCheckContext(), TestContext.Current.CancellationToken);
probe.Status.ShouldBe(HealthStatus.Unhealthy);
probe.Description.ShouldNotBeNull();
probe.Description.ShouldContain("failed to start");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Startup/FailStartExitTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Startup/FailStartExitTests.cs
index e1ea58a3a..060af9894 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Startup/FailStartExitTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/Startup/FailStartExitTests.cs
@@ -29,8 +29,8 @@ public sealed class FailStartExitTests
psi.Environment["Cluster__SeedNodes__0"] = "not-a-valid-address";
using var proc = Process.Start(psi)!;
- var stdout = proc.StandardOutput.ReadToEndAsync();
- var stderr = proc.StandardError.ReadToEndAsync();
+ var stdout = proc.StandardOutput.ReadToEndAsync(TestContext.Current.CancellationToken);
+ var stderr = proc.StandardError.ReadToEndAsync(TestContext.Current.CancellationToken);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
try { await proc.WaitForExitAsync(cts.Token); }
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/ZB.MOM.WW.OtOpcUa.Host.Tests.csproj b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/ZB.MOM.WW.OtOpcUa.Host.Tests.csproj
index 4d254b399..6b68aa551 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/ZB.MOM.WW.OtOpcUa.Host.Tests.csproj
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Host.Tests/ZB.MOM.WW.OtOpcUa.Host.Tests.csproj
@@ -7,11 +7,11 @@
-
+
-
+
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/EventStreamCommandDeliveryTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/EventStreamCommandDeliveryTests.cs
index aaa06b3c6..793e65252 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/EventStreamCommandDeliveryTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/EventStreamCommandDeliveryTests.cs
@@ -1,5 +1,5 @@
using Akka.Actor;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Deploy;
@@ -56,7 +56,7 @@ public class EventStreamCommandDeliveryTests : RuntimeActorTestBase
// EventStream subscription. Without this the relay below races the subscription.
var warmup = NewDispatch();
driverHost.Tell(warmup);
- ackRouter.ExpectMsg(TimeSpan.FromSeconds(15)).DeploymentId.ShouldBe(warmup.DeploymentId);
+ ackRouter.ExpectMsg(TimeSpan.FromSeconds(15), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(warmup.DeploymentId);
// Now the real assertion — relayed exactly as central would send it. The comm actor only
// publishes node-locally, so the host must be subscribed for this to arrive at all.
@@ -66,7 +66,7 @@ public class EventStreamCommandDeliveryTests : RuntimeActorTestBase
// The deployment id does not exist, so the host answers Failed. That is the stronger
// assertion, not a weaker one: an ack at all proves the command was received and handled,
// and only PreStart's EventStream subscription can have delivered it.
- ackRouter.ExpectMsg(TimeSpan.FromSeconds(15)).DeploymentId.ShouldBe(relayed.DeploymentId);
+ ackRouter.ExpectMsg(TimeSpan.FromSeconds(15), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(relayed.DeploymentId);
}
[Fact]
@@ -83,7 +83,7 @@ public class EventStreamCommandDeliveryTests : RuntimeActorTestBase
var dispatch = NewDispatch();
driverHost.Tell(dispatch);
- ackRouter.ExpectMsg(TimeSpan.FromSeconds(15)).DeploymentId.ShouldBe(dispatch.DeploymentId);
+ ackRouter.ExpectMsg(TimeSpan.FromSeconds(15), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(dispatch.DeploymentId);
}
}
@@ -150,12 +150,12 @@ akka {
// Tell INSIDE the assertion window alongside the relay, which made the test vacuous — the
// direct Tell alone produced the log the assertion was waiting for.
EventFilter.Debug(contains: "ignoring AlarmCommand")
- .ExpectOne(TimeSpan.FromSeconds(15), () => host.Tell(cmd));
+ .ExpectOne(TimeSpan.FromSeconds(15), () => host.Tell(cmd), TestContext.Current.CancellationToken);
// The real assertion: relayed ONLY through the comm actor, which publishes node-locally.
// The host owns no alarms, so it logs and stops — still a positive delivery signal, because
// that line is only reached if the message arrived.
EventFilter.Debug(contains: "ignoring AlarmCommand")
- .ExpectOne(TimeSpan.FromSeconds(15), () => comm.Tell(cmd));
+ .ExpectOne(TimeSpan.FromSeconds(15), () => comm.Tell(cmd), TestContext.Current.CancellationToken);
}
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/GrpcApplyAckSenderTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/GrpcApplyAckSenderTests.cs
index a8820cf11..d9c25aa09 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/GrpcApplyAckSenderTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/GrpcApplyAckSenderTests.cs
@@ -73,7 +73,7 @@ public sealed class GrpcApplyAckSenderTests
return (CentralCommandService.CentralCommandServiceClient)new RecordingClient(calls);
};
- await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack());
+ await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack(), TestContext.Current.CancellationToken);
consulted.ShouldBe(["http://central-1:4055"]);
calls.Count.ShouldBe(1);
@@ -90,7 +90,7 @@ public sealed class GrpcApplyAckSenderTests
"disk full",
new CorrelationId(Guid.NewGuid()));
- await Sender(["http://central-1:4055"], _ => new RecordingClient(calls)).SendAsync(ack);
+ await Sender(["http://central-1:4055"], _ => new RecordingClient(calls)).SendAsync(ack, TestContext.Current.CancellationToken);
var sent = calls.Single().Request;
sent.DeploymentId.ShouldBe(ack.DeploymentId.ToString());
@@ -109,7 +109,7 @@ public sealed class GrpcApplyAckSenderTests
var calls = new List<(ApplyAckMessage Request, CallOptions Options)>();
var before = DateTime.UtcNow;
- await Sender(["http://central-1:4055"], _ => new RecordingClient(calls)).SendAsync(Ack());
+ await Sender(["http://central-1:4055"], _ => new RecordingClient(calls)).SendAsync(Ack(), TestContext.Current.CancellationToken);
var options = calls.Single().Options;
options.Headers.ShouldNotBeNull();
@@ -138,7 +138,7 @@ public sealed class GrpcApplyAckSenderTests
? (CentralCommandService.CentralCommandServiceClient)new SlowThrowingClient(calls, TimeSpan.FromMilliseconds(50))
: new RecordingClient(calls);
- await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack());
+ await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack(), TestContext.Current.CancellationToken);
calls.Count.ShouldBe(2);
calls[1].Options.Deadline!.Value.ShouldBeGreaterThan(calls[0].Options.Deadline!.Value);
@@ -158,7 +158,7 @@ public sealed class GrpcApplyAckSenderTests
: new RecordingClient(calls);
};
- await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack());
+ await Sender(["http://central-1:4055", "http://central-2:4055"], factory).SendAsync(Ack(), TestContext.Current.CancellationToken);
consulted.ShouldBe(["http://central-1:4055", "http://central-2:4055"]);
calls.Count.ShouldBe(1);
@@ -185,7 +185,7 @@ public sealed class GrpcApplyAckSenderTests
};
var ack = Ack();
- await Sender(["http://central-1:4055", "http://central-2:4055"], factory, log).SendAsync(ack);
+ await Sender(["http://central-1:4055", "http://central-2:4055"], factory, log).SendAsync(ack, TestContext.Current.CancellationToken);
attempts.ShouldBe(2);
var warning = log.Entries.Single(e => e.Level == LogLevel.Warning);
@@ -213,7 +213,7 @@ public sealed class GrpcApplyAckSenderTests
: new RecordingClient(calls);
};
- await Sender(["http://c1:4055", "http://c2:4055", "http://c3:4055"], factory).SendAsync(Ack());
+ await Sender(["http://c1:4055", "http://c2:4055", "http://c3:4055"], factory).SendAsync(Ack(), TestContext.Current.CancellationToken);
// c3 is never dialled: the pass stops at the first success, and it does not go back to c1.
consulted.ShouldBe(["http://c1:4055", "http://c2:4055"]);
@@ -230,7 +230,7 @@ public sealed class GrpcApplyAckSenderTests
var factory = (string _) => (CentralCommandService.CentralCommandServiceClient)
new ThrowingClient(new RpcException(new Status(StatusCode.Unavailable, "down")));
- await Sender(["http://central-1:4055"], factory, log).SendAsync(Ack());
+ await Sender(["http://central-1:4055"], factory, log).SendAsync(Ack(), TestContext.Current.CancellationToken);
log.Entries.ShouldNotBeEmpty();
log.Entries.Any(e => e.Message.Contains(Psk, StringComparison.Ordinal)).ShouldBeFalse();
@@ -251,7 +251,7 @@ public sealed class GrpcApplyAckSenderTests
return (CentralCommandService.CentralCommandServiceClient)new RecordingClient([]);
};
- await Sender([], factory, log).SendAsync(Ack());
+ await Sender([], factory, log).SendAsync(Ack(), TestContext.Current.CancellationToken);
dialled.ShouldBeFalse();
log.Entries.Single(e => e.Level == LogLevel.Warning).Message
@@ -269,7 +269,7 @@ public sealed class GrpcApplyAckSenderTests
var calls = new List<(ApplyAckMessage Request, CallOptions Options)>();
await Sender(["http://central-1:4055"], _ => new RecordingClient(calls), log, roles: ["driver"])
- .SendAsync(Ack());
+ .SendAsync(Ack(), TestContext.Current.CancellationToken);
calls.Single().Options.Headers!.Any(h =>
h.Key.Equals("x-otopcua-cluster", StringComparison.Ordinal)).ShouldBeFalse();
@@ -311,7 +311,7 @@ public sealed class GrpcApplyAckSenderTests
Options.Create(new AkkaClusterOptions { Roles = ["driver", "cluster-SITE-A"] }),
log);
- await sender.SendAsync(Ack());
+ await sender.SendAsync(Ack(), TestContext.Current.CancellationToken);
// The post must have failed (nothing is listening) — which is what put a channel in the cache.
log.Entries.Any(e => e.Level == LogLevel.Warning).ShouldBeTrue();
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/NodeCommunicationActorTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/NodeCommunicationActorTests.cs
index e1bb1f9da..78f08d9c3 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/NodeCommunicationActorTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Communication/NodeCommunicationActorTests.cs
@@ -28,7 +28,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var dispatch = NewDispatch();
actor.Tell(dispatch);
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(dispatch);
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(dispatch);
}
[Fact]
@@ -43,8 +43,8 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
actor.Tell(NewDispatch());
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5));
- subscriber.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
+ subscriber.ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
}
[Fact]
@@ -57,7 +57,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var msg = new RestartDriver("C1", "driver-1", "alice", Guid.NewGuid());
actor.Tell(msg);
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(msg);
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(msg);
}
[Fact]
@@ -70,7 +70,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var msg = new ReconnectDriver("C1", "driver-1", "alice", Guid.NewGuid());
actor.Tell(msg);
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(msg);
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(msg);
}
[Fact]
@@ -86,7 +86,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var msg = new AlarmCommand("alarm-1", "Acknowledge", "alice", "comment", null);
actor.Tell(msg);
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(msg);
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(msg);
}
[Fact]
@@ -104,7 +104,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
new CorrelationId(Guid.NewGuid()));
EventFilter.Warning(contains: "dropping ApplyAck").ExpectOne(
- TimeSpan.FromSeconds(5), () => actor.Tell(ack));
+ TimeSpan.FromSeconds(5), () => actor.Tell(ack), TestContext.Current.CancellationToken);
}
// ---- Mode=Grpc (the cross-mesh ack leg) -----------------------------------------------------
@@ -129,9 +129,9 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var ack = NewAck();
actor.Tell(ack);
- AwaitAssert(() => sender.Sent.Count.ShouldBe(1), TimeSpan.FromSeconds(5));
+ AwaitAssert(() => sender.Sent.Count.ShouldBe(1), TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
sender.Sent[0].ShouldBe(ack);
- ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
sender.Sent.Count.ShouldBe(1);
}
@@ -148,7 +148,7 @@ public class NodeCommunicationActorTests : RuntimeActorTestBase
var dispatch = NewDispatch();
actor.Tell(dispatch);
- subscriber.ExpectMsg(TimeSpan.FromSeconds(5)).ShouldBe(dispatch);
+ subscriber.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).ShouldBe(dispatch);
sender.Sent.ShouldBeEmpty();
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Deployment/LocalDbDeploymentArtifactCacheTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Deployment/LocalDbDeploymentArtifactCacheTests.cs
index 4fc391ab8..b5b3ff365 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Deployment/LocalDbDeploymentArtifactCacheTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Deployment/LocalDbDeploymentArtifactCacheTests.cs
@@ -119,9 +119,9 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var artifact = RandomArtifact(300 * 1024);
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-1");
@@ -135,15 +135,15 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
{
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(64));
- await cache.StoreAsync(ClusterA, "dep-2", "rev-2", RandomArtifact(64));
- await cache.StoreAsync(ClusterA, "dep-3", "rev-3", RandomArtifact(64));
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(64), TestContext.Current.CancellationToken);
+ await cache.StoreAsync(ClusterA, "dep-2", "rev-2", RandomArtifact(64), TestContext.Current.CancellationToken);
+ await cache.StoreAsync(ClusterA, "dep-3", "rev-3", RandomArtifact(64), TestContext.Current.CancellationToken);
// Bounded retention is what stops a node that redeploys daily from filling its disk with
// address spaces nobody will ever roll back to.
(await DistinctDeploymentIdsAsync()).ShouldBe(["dep-2", "dep-3"]);
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-3");
}
@@ -163,20 +163,20 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var cache = CreateCache();
var newest = RandomArtifact(1024);
- await cache.StoreAsync(ClusterA, "dep-old-1", "rev-1", RandomArtifact(1024));
- await cache.StoreAsync(ClusterA, "dep-old-2", "rev-2", RandomArtifact(1024));
+ await cache.StoreAsync(ClusterA, "dep-old-1", "rev-1", RandomArtifact(1024), TestContext.Current.CancellationToken);
+ await cache.StoreAsync(ClusterA, "dep-old-2", "rev-2", RandomArtifact(1024), TestContext.Current.CancellationToken);
await _db.ExecuteAsync(
"UPDATE deployment_artifacts SET cached_at_utc = @Future",
- new { Future = "2099-01-01T00:00:00.0000000Z" });
+ new { Future = "2099-01-01T00:00:00.0000000Z" }, TestContext.Current.CancellationToken);
- await cache.StoreAsync(ClusterA, "dep-new", "rev-3", newest);
+ await cache.StoreAsync(ClusterA, "dep-new", "rev-3", newest, TestContext.Current.CancellationToken);
// The pointer names dep-new, so dep-new's chunks must still be there...
(await CountChunksAsync("dep-new")).ShouldBeGreaterThan(0);
// ...and it must actually read back, which is the behaviour that matters.
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-new");
cached.Artifact.ShouldBe(newest);
@@ -186,31 +186,31 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
public async Task GetCurrent_ReturnsNullWhenAChunkIsCorrupt()
{
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024));
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024), TestContext.Current.CancellationToken);
// Valid base64 of the wrong bytes: this passes decoding and the chunk-count check, so only
// the SHA-256 comparison can catch it. That is the check being pinned.
await _db.ExecuteAsync(
"UPDATE deployment_artifacts SET chunk_base64 = @Chunk WHERE deployment_id = @DeploymentId AND chunk_index = 1",
- new { Chunk = Convert.ToBase64String(RandomArtifact(128 * 1024)), DeploymentId = "dep-1" });
+ new { Chunk = Convert.ToBase64String(RandomArtifact(128 * 1024)), DeploymentId = "dep-1" }, TestContext.Current.CancellationToken);
- (await cache.GetCurrentAsync(ClusterA)).ShouldBeNull();
+ (await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken)).ShouldBeNull();
}
[Fact]
public async Task GetCurrent_ReturnsNullWhenAChunkIsMissing()
{
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024));
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024), TestContext.Current.CancellationToken);
// A partially replicated artifact is the realistic version of this: the pointer row arrives
// before the last chunk does. Reassembling what is present would yield a plausible-looking
// but silently truncated address space.
await _db.ExecuteAsync(
"DELETE FROM deployment_artifacts WHERE deployment_id = @DeploymentId AND chunk_index = 2",
- new { DeploymentId = "dep-1" });
+ new { DeploymentId = "dep-1" }, TestContext.Current.CancellationToken);
- (await cache.GetCurrentAsync(ClusterA)).ShouldBeNull();
+ (await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken)).ShouldBeNull();
}
[Fact]
@@ -218,7 +218,7 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
{
var cache = CreateCache();
- (await cache.GetCurrentAsync(ClusterA)).ShouldBeNull();
+ (await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken)).ShouldBeNull();
}
[Fact]
@@ -226,17 +226,17 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
{
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024));
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(300 * 1024), TestContext.Current.CancellationToken);
// The re-store is smaller, so a delete-before-insert that did not happen would leave the
// tail chunks of the first artifact behind — orphans that also break the chunk-count check.
var second = RandomArtifact(200 * 1024);
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1b", second);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1b", second, TestContext.Current.CancellationToken);
(await CountChunksAsync("dep-1")).ShouldBe(2);
(await CountChunksAsync()).ShouldBe(2);
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.RevisionHash.ShouldBe("rev-1b");
cached.Artifact.ShouldBe(second);
@@ -253,18 +253,18 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var cache = CreateCache();
var artifact = RandomArtifact(300 * 1024);
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
var oplogDepth = await OplogDepthAsync();
var rowVersions = await RowVersionsAsync();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
(await OplogDepthAsync()).ShouldBe(oplogDepth);
(await RowVersionsAsync()).ShouldBe(rowVersions);
// Skipping must not cost readability: the artifact still reads back intact.
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-1");
cached.Artifact.ShouldBe(artifact);
@@ -280,16 +280,16 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var cache = CreateCache();
var artifact = RandomArtifact(300 * 1024);
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
await _db.ExecuteAsync(
"DELETE FROM deployment_artifacts WHERE deployment_id = @DeploymentId AND chunk_index = 2",
- new { DeploymentId = "dep-1" });
- (await cache.GetCurrentAsync(ClusterA)).ShouldBeNull();
+ new { DeploymentId = "dep-1" }, TestContext.Current.CancellationToken);
+ (await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken)).ShouldBeNull();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
(await CountChunksAsync("dep-1")).ShouldBe(3);
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.Artifact.ShouldBe(artifact);
}
@@ -303,12 +303,12 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
// space with every id-shaped signal saying it was correct.
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(1024));
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", RandomArtifact(1024), TestContext.Current.CancellationToken);
var rebuilt = RandomArtifact(1024);
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", rebuilt);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", rebuilt, TestContext.Current.CancellationToken);
- var cached = await cache.GetCurrentAsync(ClusterA);
+ var cached = await cache.GetCurrentAsync(ClusterA, TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.Artifact.ShouldBe(rebuilt);
}
@@ -319,9 +319,9 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var artifact = RandomArtifact(300 * 1024);
var cache = CreateCache();
- await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact);
+ await cache.StoreAsync(ClusterA, "dep-1", "rev-1", artifact, TestContext.Current.CancellationToken);
- var cached = await cache.GetCurrentUnkeyedAsync();
+ var cached = await cache.GetCurrentUnkeyedAsync(TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-1");
@@ -335,10 +335,10 @@ public sealed class LocalDbDeploymentArtifactCacheTests : IDisposable
var logger = new CapturingLogger();
var cache = CreateCache(logger);
- await cache.StoreAsync(ClusterA, "dep-a", "rev-a", RandomArtifact(1024));
- await cache.StoreAsync(ClusterB, "dep-b", "rev-b", newest);
+ await cache.StoreAsync(ClusterA, "dep-a", "rev-a", RandomArtifact(1024), TestContext.Current.CancellationToken);
+ await cache.StoreAsync(ClusterB, "dep-b", "rev-b", newest, TestContext.Current.CancellationToken);
- var cached = await cache.GetCurrentUnkeyedAsync();
+ var cached = await cache.GetCurrentUnkeyedAsync(TestContext.Current.CancellationToken);
cached.ShouldNotBeNull();
cached.DeploymentId.ShouldBe("dep-b");
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/AbCipAlmaNativeAlarmEndToEndTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/AbCipAlmaNativeAlarmEndToEndTests.cs
index 0b827959a..fc8f8f0e4 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/AbCipAlmaNativeAlarmEndToEndTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/AbCipAlmaNativeAlarmEndToEndTests.cs
@@ -100,7 +100,7 @@ public sealed class AbCipAlmaNativeAlarmEndToEndTests : RuntimeActorTestBase
drop.State.Message.ShouldContain("H alarm");
drop.State.Message.ShouldNotContain("HH");
drop.State.Severity.ShouldBe((ushort)600);
- alerts.ExpectNoMsg(Quiet);
+ alerts.ExpectNoMsg(Quiet, TestContext.Current.CancellationToken);
// The PLC acknowledges every declared limit — ONE "Acknowledged" row.
foreach (var a in new[] { "HHAcked", "HAcked", "LAcked", "LLAcked" }) plc.Set(a, true);
@@ -116,7 +116,7 @@ public sealed class AbCipAlmaNativeAlarmEndToEndTests : RuntimeActorTestBase
plc.Set("HHInAlarm", false);
var back = NextUpdate(publish);
back.State.Acknowledged.ShouldBeFalse("the unacknowledged HH excursion keeps the condition unacknowledged");
- alerts.ExpectNoMsg(Quiet);
+ alerts.ExpectNoMsg(Quiet, TestContext.Current.CancellationToken);
// Positive control: the clear MUST write its row (the absence checks above would pass on a dead host).
plc.Set("HInAlarm", false);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/ActorNodeWriteGatewayTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/ActorNodeWriteGatewayTests.cs
index c168cf88a..7370bdf3e 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/ActorNodeWriteGatewayTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/ActorNodeWriteGatewayTests.cs
@@ -27,7 +27,7 @@ public sealed class ActorNodeWriteGatewayTests : RuntimeActorTestBase
var writeTask = gateway.WriteAsync("eq-1/speed", 123.0, AddressSpaceRealm.Uns, CancellationToken.None);
- var routed = probe.ExpectMsg(TimeSpan.FromSeconds(5));
+ var routed = probe.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
routed.NodeId.ShouldBe("eq-1/speed");
routed.Value.ShouldBe(123.0);
probe.Reply(new DriverHostActor.NodeWriteResult(true, null));
@@ -46,7 +46,7 @@ public sealed class ActorNodeWriteGatewayTests : RuntimeActorTestBase
var writeTask = gateway.WriteAsync("eq-1/speed", 123.0, AddressSpaceRealm.Uns, CancellationToken.None);
- probe.ExpectMsg(TimeSpan.FromSeconds(5));
+ probe.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
probe.Reply(new DriverHostActor.NodeWriteResult(false, "not primary"));
var outcome = await writeTask;
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/CalculationDependencyFlowTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/CalculationDependencyFlowTests.cs
index d342023c8..9fd63a003 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/CalculationDependencyFlowTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/CalculationDependencyFlowTests.cs
@@ -82,7 +82,7 @@ public sealed class CalculationDependencyFlowTests : RuntimeActorTestBase
published.ShouldContain(e => e.FullReference == "calc/engine/out" && Equals(e.Snapshot.Value, 42.0));
// Leg 2 — calc-of-calc: A's 42 re-entered the mux → B computes 43 on calc/engine/b.
published.ShouldContain(e => e.FullReference == "calc/engine/b" && Equals(e.Snapshot.Value, 43.0));
- }, PresenceBudget, TimeSpan.FromMilliseconds(100));
+ }, PresenceBudget, TimeSpan.FromMilliseconds(100), TestContext.Current.CancellationToken);
}
///
@@ -128,7 +128,7 @@ public sealed class CalculationDependencyFlowTests : RuntimeActorTestBase
mux.Tell(ValuePublishes.Single("src-drv", "src/a", 2.0, OpcUaStatus.Good, Ts));
published.ShouldContain(e => e.FullReference == "calc/keep" && Equals(e.Snapshot.Value, 20.0));
published.ShouldContain(e => e.FullReference == "calc/remove" && Equals(e.Snapshot.Value, 7.0));
- }, PresenceBudget, TimeSpan.FromMilliseconds(100));
+ }, PresenceBudget, TimeSpan.FromMilliseconds(100), TestContext.Current.CancellationToken);
// ---- IN-PLACE RE-BIND (driver ReinitializeAsync) ----
// New authored set: "keep" script EDITED to src/a*1000; "add" is a NEW tag reading a NEW dep src/b;
@@ -157,11 +157,11 @@ public sealed class CalculationDependencyFlowTests : RuntimeActorTestBase
published.ShouldContain(e => e.FullReference == "calc/add" && Equals(e.Snapshot.Value, 150.0));
// (c) edited script produces the NEW result: 3 * 1000 = 3000 (NOT the pre-edit 3 * 10 = 30).
published.ShouldContain(e => e.FullReference == "calc/keep" && Equals(e.Snapshot.Value, 3000.0));
- }, PresenceBudget, TimeSpan.FromMilliseconds(100));
+ }, PresenceBudget, TimeSpan.FromMilliseconds(100), TestContext.Current.CancellationToken);
// (b) the removed tag never recomputes on the post-redeploy src/a=3 (it would be 3 + 5 = 8) and the
// edited "keep" never serves the stale *10 result (3 * 10 = 30). Give any errant compute a moment to land.
- await Task.Delay(200);
+ await Task.Delay(200, TestContext.Current.CancellationToken);
published.ShouldNotContain(e => e.FullReference == "calc/remove" && Equals(e.Snapshot.Value, 8.0));
published.ShouldNotContain(e => e.FullReference == "calc/keep" && Equals(e.Snapshot.Value, 30.0));
}
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorApplyingStashTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorApplyingStashTests.cs
index 4ca52a950..4cc820fa7 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorApplyingStashTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorApplyingStashTests.cs
@@ -67,7 +67,7 @@ public sealed class DriverHostActorApplyingStashTests()
{
// A is in flight: the fetch has started and its task will not complete until released.
actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId()));
- AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget);
+ AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
var logs = SubscribeToLogs("deferring");
@@ -86,8 +86,8 @@ public sealed class DriverHostActorApplyingStashTests()
// Nothing was lost: B re-enters exactly once, after A's apply transitions back to Steady.
fetcher.Release();
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
fetcher.Calls.ShouldBe(2);
}
finally
@@ -137,7 +137,7 @@ public sealed class DriverHostActorApplyingStashTests()
try
{
actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId()));
- AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget);
+ AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
var logs = SubscribeToLogs("deferring", "already deferred");
@@ -152,9 +152,9 @@ public sealed class DriverHostActorApplyingStashTests()
// No second stash, therefore no second re-delivery: exactly one Applied ack for B.
fetcher.Release();
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
fetcher.Calls.ShouldBe(2);
}
finally
@@ -194,24 +194,24 @@ public sealed class DriverHostActorApplyingStashTests()
try
{
actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId()));
- AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget);
+ AwaitAssert(() => fetcher.Calls.ShouldBe(1), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
actor.Tell(new DispatchDeployment(deploymentB, RevB, CorrelationId.NewId()));
// A completes; B unstashes and starts its own (still gated) fetch.
fetcher.Release(1);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).DeploymentId.ShouldBe(deploymentA);
- AwaitAssert(() => fetcher.Calls.ShouldBe(2), duration: PresenceBudget);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(deploymentA);
+ AwaitAssert(() => fetcher.Calls.ShouldBe(2), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
// C arrives mid-B — a fresh stash cycle, on a set that was cleared when B was released.
actor.Tell(new DispatchDeployment(deploymentC, RevC, CorrelationId.NewId()));
fetcher.Release(2);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).DeploymentId.ShouldBe(deploymentB);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).DeploymentId.ShouldBe(deploymentC);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(deploymentB);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).DeploymentId.ShouldBe(deploymentC);
actor.Tell(new GetDiagnostics(CorrelationId.NewId()), coordinator.Ref);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5))
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken)
.CurrentRevision.ShouldBe(RevC);
}
finally
@@ -251,7 +251,7 @@ public sealed class DriverHostActorApplyingStashTests()
try
{
EventFilter.Warning(contains: deploymentA.ToString()).ExpectOne(TimeSpan.FromSeconds(10), () =>
- actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId())));
+ actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId())), TestContext.Current.CancellationToken);
}
finally
{
@@ -285,7 +285,7 @@ public sealed class DriverHostActorApplyingStashTests()
var logs = SubscribeToLogs("appears WEDGED");
actor.Tell(new DispatchDeployment(deploymentA, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(10)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(10), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
// Well past the (200 ms) delay — a live timer would have fired several times over.
logs.Drain(SpinWindow);
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorArtifactCacheTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorArtifactCacheTests.cs
index 94302e10b..f90459b90 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorArtifactCacheTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorArtifactCacheTests.cs
@@ -42,9 +42,9 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
deploymentArtifactCache: cache));
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
- AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3));
+ AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
var store = cache.Stores[0];
store.DeploymentId.ShouldBe(deploymentId.ToString());
@@ -69,9 +69,9 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
deploymentArtifactCache: cache));
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
- AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3));
+ AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
cache.Stores[0].ClusterId.ShouldBe("SITE-A");
}
@@ -89,9 +89,9 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
deploymentArtifactCache: cache));
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken);
- AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3));
+ AwaitAssert(() => cache.Stores.Count.ShouldBe(1), duration: TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
cache.Stores[0].ClusterId.ShouldBe("__single");
}
@@ -132,7 +132,7 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
// Since #486 the apply FAILS rather than reporting a success it did not achieve: empty bytes are
// what an unreadable artifact looks like, not a legitimate no-op deployment. (A configuration that
// genuinely declares nothing still serialises to a JSON document with empty arrays.)
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Failed);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Failed);
// The point of this test is unchanged, and now holds for two independent reasons: nothing is cached.
Thread.Sleep(500);
@@ -156,11 +156,11 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
// Exactly one ACK, and it says Applied. A second Failed ACK arriving here would mean the
// cache failure had corrupted the deployment protocol.
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(500), TestContext.Current.CancellationToken);
}
[Fact]
@@ -177,7 +177,7 @@ public sealed class DriverHostActorArtifactCacheTests : RuntimeActorTestBase
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
}
///
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorAsyncCacheWriteTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorAsyncCacheWriteTests.cs
index 1a2c6c9f5..2abb7cf84 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorAsyncCacheWriteTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorAsyncCacheWriteTests.cs
@@ -56,21 +56,21 @@ public sealed class DriverHostActorAsyncCacheWriteTests()
try
{
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
- coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(5), cancellationToken: TestContext.Current.CancellationToken).Outcome.ShouldBe(ApplyAckOutcome.Applied);
// The store was entered and has NOT completed — the gate is still closed.
- AwaitAssert(() => cache.StoresEntered.ShouldBe(1), duration: PresenceBudget);
+ AwaitAssert(() => cache.StoresEntered.ShouldBe(1), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
cache.StoresCompleted.ShouldBe(0);
// THE assertion: with the store still in flight the host is still processing its mailbox.
// A blocking `.GetAwaiter().GetResult()` parks the actor thread here and this times out.
actor.Tell(new GetDiagnostics(CorrelationId.NewId()), coordinator.Ref);
- coordinator.ExpectMsg(TimeSpan.FromSeconds(3));
+ coordinator.ExpectMsg(TimeSpan.FromSeconds(3), cancellationToken: TestContext.Current.CancellationToken);
// Completion is observed rather than fire-and-forgotten: the store pipes back to Self and
// the handler logs it, so an operator can tell a cached apply from an uncached one.
EventFilter.Info(contains: "cached applied deployment")
- .ExpectOne(TimeSpan.FromSeconds(5), () => cache.Release());
+ .ExpectOne(TimeSpan.FromSeconds(5), () => cache.Release(), TestContext.Current.CancellationToken);
}
finally
{
@@ -107,9 +107,9 @@ public sealed class DriverHostActorAsyncCacheWriteTests()
{
actor.Tell(new DispatchDeployment(deploymentId, RevA, CorrelationId.NewId()));
coordinator.ExpectMsg(TimeSpan.FromSeconds(5)).Outcome.ShouldBe(ApplyAckOutcome.Applied);
- });
+ }, TestContext.Current.CancellationToken);
- coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ coordinator.ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
}
/// Seeds a sealed, parseable deployment and returns its id.
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorBatchFanOutTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorBatchFanOutTests.cs
index 51e3ee874..a17c51e0f 100644
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorBatchFanOutTests.cs
+++ b/tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/Drivers/DriverHostActorBatchFanOutTests.cs
@@ -57,7 +57,7 @@ public sealed class DriverHostActorBatchFanOutTests : RuntimeActorTestBase
new DriverInstanceActor.AttributeValueItem("Plant/Modbus/dev1/temp", 7.5, OpcUaStatus.BadNoCommunication, TsB),
}));
- var batch = publish.ExpectMsg(PresenceBudget);
+ var batch = publish.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
batch.Items.Count.ShouldBe(3);
var byId = batch.Items.ToDictionary(w => w.NodeId);
@@ -85,7 +85,7 @@ public sealed class DriverHostActorBatchFanOutTests : RuntimeActorTestBase
byId["Plant/Modbus/dev1/temp"].Realm.ShouldBe(AddressSpaceRealm.Raw);
// ONE message, not one per value.
- publish.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ publish.ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
}
/// An item whose ref is bound to no NodeId is dropped; the rest of the burst still lands in the
@@ -106,7 +106,7 @@ public sealed class DriverHostActorBatchFanOutTests : RuntimeActorTestBase
new DriverInstanceActor.AttributeValueItem("Plant/Modbus/dev1/speed", 42.0, OpcUaStatus.Good, TsA),
}));
- var batch = publish.ExpectMsg(PresenceBudget);
+ var batch = publish.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
batch.Items.Count.ShouldBe(1);
batch.Items[0].NodeId.ShouldBe("Plant/Modbus/dev1/speed");
batch.Items[0].Value.ShouldBe(42.0);
@@ -116,7 +116,7 @@ public sealed class DriverHostActorBatchFanOutTests : RuntimeActorTestBase
{
new DriverInstanceActor.AttributeValueItem("Plant/Modbus/dev1/speed", 43.0, OpcUaStatus.Good, TsB),
}));
- publish.ExpectMsg(PresenceBudget)
+ publish.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken)
.Items[0].Value.ShouldBe(43.0);
}
@@ -142,11 +142,11 @@ public sealed class DriverHostActorBatchFanOutTests : RuntimeActorTestBase
new DriverInstanceActor.AttributeValueItem("Plant/Modbus/dev1/temp", 7.5, OpcUaStatus.Good, TsB),
}));
- var fwd = mux.ExpectMsg(PresenceBudget);
+ var fwd = mux.ExpectMsg(PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
fwd.DriverInstanceId.ShouldBe("drv-1");
fwd.Items.Select(i => i.FullReference).ShouldBe(
new[] { "Plant/Modbus/dev1/speed", "Plant/Modbus/dev1/temp" });
- mux.ExpectNoMsg(TimeSpan.FromMilliseconds(300));
+ mux.ExpectNoMsg(TimeSpan.FromMilliseconds(300), TestContext.Current.CancellationToken);
}
///