test(vtags): thread-safe CapturingHistoryWriter + drop redundant wait (H5c review follow-up)
This commit is contained in:
+10
-7
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Akka.Actor;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
@@ -191,7 +192,8 @@ public sealed class VirtualTagHostActorTests : RuntimeActorTestBase
|
||||
|
||||
// Wait for the history record to land (delivered on the same actor turn as the publish).
|
||||
AwaitAssert(() => writer.Calls.Count.ShouldBe(1));
|
||||
var (path, value) = writer.Calls[0];
|
||||
writer.Calls.TryPeek(out var captured).ShouldBeTrue();
|
||||
var (path, value) = captured;
|
||||
path.ShouldBe("eq-1/speed-rpm");
|
||||
value.Value.ShouldBe(42.0);
|
||||
value.StatusCode.ShouldBe(0u); // OPC UA Good
|
||||
@@ -213,11 +215,10 @@ public sealed class VirtualTagHostActorTests : RuntimeActorTestBase
|
||||
|
||||
host.Tell(new VirtualTagActor.EvaluationResult("vt-1", 42.0, DateTime.UtcNow, CorrelationId.NewId()));
|
||||
|
||||
// The value is still published…
|
||||
// The value is still published — and the publish completing means OnResult's turn is done,
|
||||
// so the historian (which would have been called on the same turn) was never touched.
|
||||
publish.ExpectMsg<OpcUaPublishActor.AttributeValueUpdate>();
|
||||
// …but the historian was never touched.
|
||||
publish.ExpectNoMsg(TimeSpan.FromMilliseconds(200));
|
||||
writer.Calls.ShouldBeEmpty();
|
||||
writer.Calls.IsEmpty.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>A plan with an explicit Expression + DependencyRefs (the H1b in-place-change case).</summary>
|
||||
@@ -348,12 +349,14 @@ public sealed class VirtualTagHostActorTests : RuntimeActorTestBase
|
||||
/// assert the host historizes (or does not) and with what path + snapshot.</summary>
|
||||
private sealed class CapturingHistoryWriter : IHistoryWriter
|
||||
{
|
||||
public readonly List<(string Path, DataValueSnapshot Value)> Calls = new();
|
||||
// ConcurrentQueue: Record runs on the actor thread, the test asserts on the test thread —
|
||||
// a plain List would be a cross-thread data race under load.
|
||||
public readonly ConcurrentQueue<(string Path, DataValueSnapshot Value)> Calls = new();
|
||||
|
||||
/// <summary>Captures the path + snapshot of a Record call.</summary>
|
||||
/// <param name="path">The virtual tag path.</param>
|
||||
/// <param name="value">The data value snapshot.</param>
|
||||
public void Record(string path, DataValueSnapshot value) => Calls.Add((path, value));
|
||||
public void Record(string path, DataValueSnapshot value) => Calls.Enqueue((path, value));
|
||||
}
|
||||
|
||||
/// <summary>Deterministic no-op evaluator: keeps spawned children inert so tests drive the host's
|
||||
|
||||
Reference in New Issue
Block a user