feat(runtime): EvaluationResult carries OpcUaQuality; VT bridge publishes it + historizes BadInternalError on Bad (02/S13)
This commit is contained in:
@@ -406,6 +406,48 @@ public sealed class VirtualTagHostActorTests : RuntimeActorTestBase
|
||||
bad.TimestampUtc.ShouldBe(ts2);
|
||||
}
|
||||
|
||||
/// <summary>02/S13 bridge: a Bad-quality <see cref="VirtualTagActor.EvaluationResult"/> must bridge to
|
||||
/// an <see cref="OpcUaPublishActor.AttributeValueUpdate"/> carrying <see cref="OpcUaQuality.Bad"/>
|
||||
/// (not the old hard-coded Good).</summary>
|
||||
[Fact]
|
||||
public void Bad_quality_EvaluationResult_is_bridged_as_Bad()
|
||||
{
|
||||
var publish = CreateTestProbe();
|
||||
var host = Sys.ActorOf(VirtualTagHostActor.Props(publish.Ref, mux: null, new StubEvaluator()));
|
||||
|
||||
host.Tell(new VirtualTagHostActor.ApplyVirtualTags(new[] { Plan("vt-1", "eq-1", "speed-rpm") }));
|
||||
|
||||
var ts = new DateTime(2026, 7, 12, 12, 0, 0, DateTimeKind.Utc);
|
||||
host.Tell(new VirtualTagActor.EvaluationResult(
|
||||
"vt-1", 42.0, ts, CorrelationId.NewId(), OpcUaQuality.Bad));
|
||||
|
||||
var update = publish.ExpectMsg<OpcUaPublishActor.AttributeValueUpdate>();
|
||||
update.Quality.ShouldBe(OpcUaQuality.Bad);
|
||||
update.Value.ShouldBe(42.0);
|
||||
}
|
||||
|
||||
/// <summary>02/S13 historize parity: a Bad result on a historized plan must record the dormant
|
||||
/// engine's BadInternalError status (0x80020000u) in the snapshot, not the Good 0u.</summary>
|
||||
[Fact]
|
||||
public void Historized_Bad_result_is_recorded_with_BadInternalError_status()
|
||||
{
|
||||
var publish = CreateTestProbe();
|
||||
var writer = new CapturingHistoryWriter();
|
||||
var host = Sys.ActorOf(VirtualTagHostActor.Props(publish.Ref, mux: null, new StubEvaluator(), writer));
|
||||
|
||||
host.Tell(new VirtualTagHostActor.ApplyVirtualTags(
|
||||
new[] { PlanH("vt-1", "eq-1", "speed-rpm", historize: true) }));
|
||||
|
||||
var ts = new DateTime(2026, 7, 12, 12, 0, 0, DateTimeKind.Utc);
|
||||
host.Tell(new VirtualTagActor.EvaluationResult(
|
||||
"vt-1", 42.0, ts, CorrelationId.NewId(), OpcUaQuality.Bad));
|
||||
|
||||
publish.ExpectMsg<OpcUaPublishActor.AttributeValueUpdate>();
|
||||
AwaitAssert(() => writer.Calls.Count.ShouldBe(1));
|
||||
writer.Calls.TryPeek(out var captured).ShouldBeTrue();
|
||||
captured.Value.StatusCode.ShouldBe(0x80020000u); // BadInternalError — dormant-engine parity
|
||||
}
|
||||
|
||||
/// <summary>Evaluator that returns <c>Ok(42.0)</c> on its first call and <c>Failure</c> thereafter —
|
||||
/// the S13 "was working, now broken" shape. Interlocked counter so it is safe across the actor's
|
||||
/// evaluation thread.</summary>
|
||||
|
||||
Reference in New Issue
Block a user