using Shouldly; using ZB.MOM.WW.OtOpcUa.Commons.Browsing; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Commons.Tests.Browsing; public class CapturingAddressSpaceBuilderTests { private static DriverAttributeInfo Attr(string fullName, bool isAlarm = false) => new(fullName, DriverDataType.Float64, false, null, SecurityClassification.Operate, false, IsAlarm: isAlarm); [Fact] public void CapturesNestedFoldersAndLeaves() { var b = new CapturingAddressSpaceBuilder(nodeCap: 100); var plc = b.Folder("Plc1", "PLC 1"); plc.Variable("Speed", "Speed", Attr("Program:Main.Speed")); var udt = plc.Folder("Motor", "Motor"); udt.Variable("Amps", "Amps", Attr("Program:Main.Motor.Amps")); var tree = b.Build(); tree.Truncated.ShouldBeFalse(); tree.Root.Children.Count.ShouldBe(1); var plcNode = tree.Root.Children[0]; plcNode.Id.ShouldBe("/Plc1"); plcNode.IsLeaf.ShouldBeFalse(); plcNode.Children.Select(c => c.Id).ShouldBe(new[] { "Program:Main.Speed", "/Plc1/Motor" }); tree.ById["Program:Main.Motor.Amps"].Attribute!.FullName.ShouldBe("Program:Main.Motor.Amps"); } [Fact] public void LeafNodeIdIsTheDriverFullName() { var b = new CapturingAddressSpaceBuilder(100); var handle = b.Variable("T", "T", Attr("Device.Tag1")); handle.FullReference.ShouldBe("Device.Tag1"); b.Build().ById["Device.Tag1"].IsLeaf.ShouldBeTrue(); } [Fact] public void NodeCapTruncatesInsteadOfGrowing() { var b = new CapturingAddressSpaceBuilder(nodeCap: 3); for (var i = 0; i < 10; i++) b.Variable($"T{i}", $"T{i}", Attr($"Dev.T{i}")); var tree = b.Build(); tree.Truncated.ShouldBeTrue(); tree.Count.ShouldBe(3); } [Fact] public void MarkAsAlarmConditionRecordsAlarmAndReturnsNoopSink() { var b = new CapturingAddressSpaceBuilder(100); var h = b.Variable("A", "A", Attr("Dev.Alarm1")); var sink = h.MarkAsAlarmCondition(new AlarmConditionInfo("A", AlarmSeverity.High, null)); sink.ShouldNotBeNull(); Should.NotThrow(() => sink.OnTransition(null!)); // no-op — browse never delivers transitions b.Build().ById["Dev.Alarm1"].IsAlarmMarked.ShouldBeTrue(); } [Fact] public void AddPropertyAttachesToCurrentScope() { var b = new CapturingAddressSpaceBuilder(100); var f = b.Folder("Dev", "Dev"); f.AddProperty("Model", DriverDataType.String, "1756-L83E"); b.Build().ById["/Dev"].Properties.ShouldContain(p => p.Name == "Model" && (string?)p.Value == "1756-L83E"); } }