using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Tests; /// /// Scaffold tests for 's /// surface that don't require a live remote server. Live-browse coverage lands in a /// follow-up PR once the in-process OPC UA server fixture is scaffolded. /// [Trait("Category", "Unit")] public sealed class OpcUaClientDiscoveryTests { [Fact] public async Task DiscoverAsync_without_initialize_throws_InvalidOperationException() { using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-disco"); var builder = new NullAddressSpaceBuilder(); await Should.ThrowAsync(async () => await drv.DiscoverAsync(builder, TestContext.Current.CancellationToken)); } [Fact] public void DiscoverAsync_rejects_null_builder() { using var drv = new OpcUaClientDriver(new OpcUaClientDriverOptions(), "opcua-disco"); Should.ThrowAsync(async () => await drv.DiscoverAsync(null!, TestContext.Current.CancellationToken)); } [Fact] public void Discovery_caps_are_sensible_defaults() { var opts = new OpcUaClientDriverOptions(); opts.MaxDiscoveredNodes.ShouldBe(10_000, "bounds memory on runaway servers without clipping normal models"); opts.MaxBrowseDepth.ShouldBe(10, "deep enough for realistic info models; shallow enough for cycle safety"); opts.BrowseRoot.ShouldBeNull("null = default to ObjectsFolder i=85"); } private sealed class NullAddressSpaceBuilder : IAddressSpaceBuilder { public IAddressSpaceBuilder Folder(string browseName, string displayName) => this; public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo) => new StubHandle(); public void AddProperty(string browseName, DriverDataType dataType, object? value) { } public void AttachAlarmCondition(IVariableHandle sourceVariable, string alarmName, DriverAttributeInfo alarmInfo) { } private sealed class StubHandle : IVariableHandle { public string FullReference => "stub"; public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => throw new NotSupportedException(); } } }