71 lines
2.8 KiB
C#
71 lines
2.8 KiB
C#
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Tests;
|
|
|
|
[Trait("Category", "Unit")]
|
|
public sealed class OpcUaClientAlarmTests
|
|
{
|
|
[Theory]
|
|
[InlineData((ushort)1, AlarmSeverity.Low)]
|
|
[InlineData((ushort)200, AlarmSeverity.Low)]
|
|
[InlineData((ushort)201, AlarmSeverity.Medium)]
|
|
[InlineData((ushort)500, AlarmSeverity.Medium)]
|
|
[InlineData((ushort)501, AlarmSeverity.High)]
|
|
[InlineData((ushort)800, AlarmSeverity.High)]
|
|
[InlineData((ushort)801, AlarmSeverity.Critical)]
|
|
[InlineData((ushort)1000, AlarmSeverity.Critical)]
|
|
public void MapSeverity_buckets_per_OPC_UA_Part_9_guidance(ushort opcSev, AlarmSeverity expected)
|
|
{
|
|
OpcUaClientDriver.MapSeverity(opcSev).ShouldBe(expected);
|
|
}
|
|
|
|
[Fact]
|
|
public void MapSeverity_zero_maps_to_Low()
|
|
{
|
|
// 0 isn't in OPC UA's 1-1000 range but we handle it gracefully as Low.
|
|
OpcUaClientDriver.MapSeverity(0).ShouldBe(AlarmSeverity.Low);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SubscribeAlarmsAsync_without_initialize_throws_InvalidOperationException()
|
|
{
|
|
using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-alarm-uninit");
|
|
await Should.ThrowAsync<InvalidOperationException>(async () =>
|
|
await drv.SubscribeAlarmsAsync([], TestContext.Current.CancellationToken));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UnsubscribeAlarmsAsync_with_unknown_handle_is_noop()
|
|
{
|
|
using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-alarm-unknown");
|
|
// Parallels the subscribe handle path — session-drop races shouldn't crash the caller.
|
|
await drv.UnsubscribeAlarmsAsync(new FakeAlarmHandle(), TestContext.Current.CancellationToken);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AcknowledgeAsync_without_initialize_throws_InvalidOperationException()
|
|
{
|
|
using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-ack-uninit");
|
|
await Should.ThrowAsync<InvalidOperationException>(async () =>
|
|
await drv.AcknowledgeAsync(
|
|
[new AlarmAcknowledgeRequest("ns=2;s=Src", "ns=2;s=Cond", "operator ack")],
|
|
TestContext.Current.CancellationToken));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AcknowledgeAsync_with_empty_batch_is_noop_even_without_init()
|
|
{
|
|
// Empty batch short-circuits before touching the session, so it's safe pre-init. This
|
|
// keeps batch-ack callers from needing to guard the list size themselves.
|
|
using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-ack-empty");
|
|
await drv.AcknowledgeAsync([], TestContext.Current.CancellationToken);
|
|
}
|
|
|
|
private sealed class FakeAlarmHandle : IAlarmSubscriptionHandle
|
|
{
|
|
public string DiagnosticId => "fake-alarm";
|
|
}
|
|
}
|