using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Core.Hosting; namespace ZB.MOM.WW.OtOpcUa.Core.Tests; [Trait("Category", "Unit")] public sealed class DriverHostTests { private sealed class StubDriver(string id, bool failInit = false) : IDriver { public string DriverInstanceId { get; } = id; public string DriverType => "Stub"; public bool Initialized { get; private set; } public bool ShutDown { get; private set; } public Task InitializeAsync(string _, CancellationToken ct) { if (failInit) throw new InvalidOperationException("boom"); Initialized = true; return Task.CompletedTask; } public Task ReinitializeAsync(string _, CancellationToken ct) => Task.CompletedTask; public Task ShutdownAsync(CancellationToken ct) { ShutDown = true; return Task.CompletedTask; } public DriverHealth GetHealth() => new(Initialized ? DriverState.Healthy : DriverState.Unknown, null, null); public long GetMemoryFootprint() => 0; public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask; } [Fact] public async Task Register_initializes_driver_and_tracks_health() { await using var host = new DriverHost(); var driver = new StubDriver("d-1"); await host.RegisterAsync(driver, "{}", CancellationToken.None); host.RegisteredDriverIds.ShouldContain("d-1"); driver.Initialized.ShouldBeTrue(); host.GetHealth("d-1")!.State.ShouldBe(DriverState.Healthy); } [Fact] public async Task Register_rethrows_init_failure_but_keeps_driver_registered() { await using var host = new DriverHost(); var driver = new StubDriver("d-bad", failInit: true); await Should.ThrowAsync(() => host.RegisterAsync(driver, "{}", CancellationToken.None)); host.RegisteredDriverIds.ShouldContain("d-bad"); } [Fact] public async Task Duplicate_registration_throws() { await using var host = new DriverHost(); await host.RegisterAsync(new StubDriver("d-1"), "{}", CancellationToken.None); await Should.ThrowAsync(() => host.RegisterAsync(new StubDriver("d-1"), "{}", CancellationToken.None)); } [Fact] public async Task Unregister_shuts_down_and_removes() { await using var host = new DriverHost(); var driver = new StubDriver("d-1"); await host.RegisterAsync(driver, "{}", CancellationToken.None); await host.UnregisterAsync("d-1", CancellationToken.None); host.RegisteredDriverIds.ShouldNotContain("d-1"); driver.ShutDown.ShouldBeTrue(); } }