using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Server.Tests.Alarms; /// /// PR B.3 — pins the routing decision DriverNodeManager makes when registering /// an AlarmConditionState: drivers that implement /// get an acknowledger that calls AcknowledgeAsync (driver-native path); drivers /// that don't fall back to the IWritable sub-attribute write. /// [Trait("Category", "Unit")] public sealed class DriverAlarmSourceAcknowledgerRoutingTests { [Fact] public void Driver_with_IAlarmSource_is_recognized() { IDriver driver = new FakeDriverWithAlarmSource("drv-1"); (driver is IAlarmSource).ShouldBeTrue( "fakes that participate in the routing-test fixture must report IAlarmSource"); } [Fact] public void Driver_without_IAlarmSource_falls_to_writable_path() { IDriver driver = new FakeDriverNoAlarmSource("drv-2"); (driver is IAlarmSource).ShouldBeFalse( "drivers without IAlarmSource take the legacy DriverWritableAcknowledger path"); } private sealed class FakeDriverWithAlarmSource(string id) : IDriver, IAlarmSource { public string DriverInstanceId { get; } = id; public string DriverType => "FakeAlarmSource"; public Task InitializeAsync(string c, CancellationToken ct) => Task.CompletedTask; public Task ReinitializeAsync(string c, CancellationToken ct) => Task.CompletedTask; public Task ShutdownAsync(CancellationToken ct) => Task.CompletedTask; public DriverHealth GetHealth() => new(DriverState.Healthy, DateTime.UtcNow, null); public long GetMemoryFootprint() => 0; public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask; public Task SubscribeAlarmsAsync( IReadOnlyList sourceNodeIds, CancellationToken cancellationToken) => Task.FromResult(new FakeHandle("h")); public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken) => Task.CompletedTask; public Task AcknowledgeAsync( IReadOnlyList acknowledgements, CancellationToken cancellationToken) => Task.CompletedTask; public event EventHandler? OnAlarmEvent; private void NoUnusedWarning() => OnAlarmEvent?.Invoke(this, null!); } private sealed class FakeDriverNoAlarmSource(string id) : IDriver { public string DriverInstanceId { get; } = id; public string DriverType => "FakeNoAlarmSource"; public Task InitializeAsync(string c, CancellationToken ct) => Task.CompletedTask; public Task ReinitializeAsync(string c, CancellationToken ct) => Task.CompletedTask; public Task ShutdownAsync(CancellationToken ct) => Task.CompletedTask; public DriverHealth GetHealth() => new(DriverState.Healthy, DateTime.UtcNow, null); public long GetMemoryFootprint() => 0; public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask; } private sealed class FakeHandle(string id) : IAlarmSubscriptionHandle { public string DiagnosticId { get; } = id; } }