test(alarms): native ack wrong-role deny + tidy NativeAlarmAck doc (code-review)
This commit is contained in:
@@ -12,9 +12,9 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
|
||||
/// ref, the operator's acknowledge comment, and the authenticated operator's display name.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="ConditionNodeId">The acknowledged condition's folder-scoped NodeId identifier string
|
||||
/// (the same value the <c>DriverHostActor</c> inverse map keys native conditions by), used to resolve the
|
||||
/// command back to its backing driver + alarm ref.</param>
|
||||
/// <param name="ConditionNodeId">The folder-scoped condition NodeId identifier string — the same value
|
||||
/// stored in <c>DriverHostActor._alarmNodeIdByDriverRef</c> (keyed by <c>(DriverInstanceId, FullName)</c>),
|
||||
/// used to resolve the ack back to its backing driver.</param>
|
||||
/// <param name="Comment">The operator's acknowledge comment text, or <c>null</c> when none was supplied.</param>
|
||||
/// <param name="OperatorUser">The authenticated operator's display name (empty when none resolves).</param>
|
||||
public sealed record NativeAlarmAck(string ConditionNodeId, string? Comment, string OperatorUser);
|
||||
|
||||
@@ -480,6 +480,35 @@ public sealed class AlarmCommandRouterTests : IDisposable
|
||||
await host.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>H6c — a NATIVE condition's Acknowledge from a non-null identity that lacks the
|
||||
/// <c>AlarmAck</c> role is vetoed (BadUserAccessDenied) and NEITHER router is invoked — the gate
|
||||
/// fails closed before any route, exactly as for scripted conditions.</summary>
|
||||
[Fact]
|
||||
public async Task Native_OnAcknowledge_without_AlarmAck_returns_denied_and_routes_nothing()
|
||||
{
|
||||
var (host, server) = await BootAsync();
|
||||
var nm = server.NodeManager!;
|
||||
|
||||
var scripted = new List<AlarmCommand>();
|
||||
var native = new List<NativeAlarmAck>();
|
||||
nm.AlarmCommandRouter = scripted.Add;
|
||||
nm.NativeAlarmAckRouter = native.Add;
|
||||
|
||||
nm.EnsureFolder("eq-nak4", parentNodeId: null, displayName: "Equipment NAK4");
|
||||
nm.MaterialiseAlarmCondition("alm-nak4", "eq-nak4", "HighTemp", "OffNormalAlarm", severity: 700, isNative: true);
|
||||
var condition = nm.TryGetAlarmCondition("alm-nak4");
|
||||
condition.ShouldNotBeNull();
|
||||
|
||||
var ctx = SessionContext(server, "pete", "ReadOnly"); // non-null identity, but no AlarmAck
|
||||
var result = condition!.OnAcknowledge!(ctx, condition, EventIdBytes(), new LocalizedText("nope"));
|
||||
|
||||
result.StatusCode.Code.ShouldBe(StatusCodes.BadUserAccessDenied);
|
||||
native.ShouldBeEmpty();
|
||||
scripted.ShouldBeEmpty();
|
||||
|
||||
await host.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>H6c — a NATIVE condition's Acknowledge from an anonymous / role-less identity is vetoed
|
||||
/// (BadUserAccessDenied) and NEITHER router is invoked — the gate fails closed before any route.</summary>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user