using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.AbCip; namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests; /// /// Gitea #534 — the authored EtherNet/IP port must reach libplctag's gateway attribute. /// /// /// This driver carried the identical defect to AbLegacy, where it was found: /// was on the record and consumed by nobody, so the runtime /// handed libplctag the bare host and libplctag substituted 44818. It survived here precisely because /// it is invisible here — every AbCip fixture profile binds 44818, so no test this driver has could /// distinguish "uses the authored port" from "always uses 44818". Worth remembering as a shape: a /// fixture that only ever exercises the default value cannot falsify a rule about non-default values, /// however many tests point at it. /// public sealed class AbCipGatewayCompositionTests { private static AbCipTagCreateParams Params(string host, int port) => new(Gateway: host, Port: port, CipPath: "1,0", LibplctagPlcAttribute: "controllogix", TagName: "TestDINT", Timeout: TimeSpan.FromSeconds(5)); [Fact] public void The_authored_port_is_appended_to_the_gateway() { Params("10.100.0.35", 44900).LibplctagGateway.ShouldBe("10.100.0.35:44900"); } [Fact] public void The_default_port_is_still_written_explicitly() { Params("plc1.plant.local", 44818).LibplctagGateway.ShouldBe("plc1.plant.local:44818"); } [Theory] [InlineData(0)] [InlineData(-1)] public void A_missing_port_falls_back_to_the_bare_host(int port) { Params("10.100.0.35", port).LibplctagGateway.ShouldBe("10.100.0.35"); } // Gitea #539 — #534 fixed the data path but both DISCOVERY call sites kept passing the bare // Gateway, so "Browse controller" against a device authored on a non-default port silently // browsed whatever answers on 44818. These pin the composed gateway at the actual libplctag // Tag construction seam, which the property-only tests above structurally cannot: they proved // LibplctagGateway composes correctly while nothing proved each Tag builder consumes it. [Fact] public void The_symbol_list_browse_tag_carries_the_authored_port() { using var tag = LibplctagListingReader.BuildSymbolListTag(Params("10.100.0.35", 44999)); tag.Gateway.ShouldBe("10.100.0.35:44999"); tag.Name.ShouldBe("@tags"); } [Fact] public void The_template_read_tag_carries_the_authored_port() { using var tag = LibplctagTemplateReader.BuildTemplateTag(Params("10.100.0.35", 44999), templateInstanceId: 0x123); tag.Gateway.ShouldBe("10.100.0.35:44999"); tag.Name.ShouldBe("@udt/291"); } }