fix(r2-04): scripted-alarm alerts emit uses PrimaryGatePolicy (consistency with 03/S4)
This commit is contained in:
+52
@@ -519,6 +519,58 @@ public sealed class ScriptedAlarmHostActorTests : RuntimeActorTestBase
|
||||
evt.TransitionKind.ShouldBe("Activated");
|
||||
}
|
||||
|
||||
/// <summary>Boot-window multi-driver suppression (archreview 03/S4): role unknown + a real driver peer
|
||||
/// (member count 2) ⇒ the alerts publish is DENIED (default-deny closes the dual-primary window that would
|
||||
/// historize duplicate AVEVA rows), while the OPC UA node write stays ungated.</summary>
|
||||
[Fact]
|
||||
public void Unknown_role_multi_driver_suppresses_alerts_but_still_writes_opcua()
|
||||
{
|
||||
var publish = CreateTestProbe();
|
||||
var mux = CreateTestProbe();
|
||||
var alerts = CreateTestProbe();
|
||||
SubscribeToAlerts(alerts);
|
||||
|
||||
var (host, _) = SpawnWithMemberCount(publish, mux, LocalNode, driverMemberCount: 2);
|
||||
host.Tell(new ScriptedAlarmHostActor.ApplyScriptedAlarms(new[] { Plan(severity: 800) }));
|
||||
mux.ExpectMsg<DependencyMuxActor.RegisterInterest>(Timeout);
|
||||
|
||||
// No snapshot sent ⇒ role unknown; count 2 ⇒ default-DENY.
|
||||
host.Tell(new VirtualTagActor.DependencyValueChanged("M.T", 99, DateTime.UtcNow));
|
||||
|
||||
publish.FishForMessage<OpcUaPublishActor.AlarmStateUpdate>(m => m.State.Active, Timeout);
|
||||
alerts.ExpectNoMsg(TimeSpan.FromMilliseconds(500));
|
||||
}
|
||||
|
||||
/// <summary>Boot-window single-driver emit (archreview 03/S4): role unknown + no driver peer (member
|
||||
/// count 1) ⇒ the alerts publish proceeds (single-node posture preserved).</summary>
|
||||
[Fact]
|
||||
public void Unknown_role_single_driver_publishes_alerts()
|
||||
{
|
||||
var publish = CreateTestProbe();
|
||||
var mux = CreateTestProbe();
|
||||
var alerts = CreateTestProbe();
|
||||
SubscribeToAlerts(alerts);
|
||||
|
||||
var (host, _) = SpawnWithMemberCount(publish, mux, LocalNode, driverMemberCount: 1);
|
||||
host.Tell(new ScriptedAlarmHostActor.ApplyScriptedAlarms(new[] { Plan(severity: 800) }));
|
||||
mux.ExpectMsg<DependencyMuxActor.RegisterInterest>(Timeout);
|
||||
|
||||
host.Tell(new VirtualTagActor.DependencyValueChanged("M.T", 99, DateTime.UtcNow));
|
||||
|
||||
publish.FishForMessage<OpcUaPublishActor.AlarmStateUpdate>(m => m.State.Active, Timeout);
|
||||
alerts.ExpectMsg<AlarmTransitionEvent>(Timeout).AlarmId.ShouldBe("alm-1");
|
||||
}
|
||||
|
||||
private (IActorRef Host, DependencyMuxTagUpstreamSource Upstream) SpawnWithMemberCount(
|
||||
TestProbe publish, TestProbe mux, NodeId localNode, int driverMemberCount)
|
||||
{
|
||||
var upstream = new DependencyMuxTagUpstreamSource();
|
||||
var engine = BuildEngine(upstream);
|
||||
var host = Sys.ActorOf(ScriptedAlarmHostActor.Props(
|
||||
publish.Ref, mux.Ref, upstream, engine, localNode, driverMemberCountProvider: () => driverMemberCount));
|
||||
return (host, upstream);
|
||||
}
|
||||
|
||||
/// <summary>Inbound command ungated by role (T1): the alerts-publish gate must NOT affect inbound
|
||||
/// command processing. Under a Secondary role, an AlarmCommand("Acknowledge") for an owned, active
|
||||
/// alarm still drives the engine — observed via the resulting AlarmStateUpdate(Acknowledged=true)
|
||||
|
||||
Reference in New Issue
Block a user