using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Cip; namespace ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Tests.Cip; public sealed class CipPathTests { [Theory] [InlineData("1,0", "0100")] [InlineData("", "")] [InlineData("1,0,2,10.0.0.5", "0100" + "1208" + "31302E302E302E35")] [InlineData("2,10.0.0.55", "1209" + "31302E302E302E3535" + "00")] [InlineData("15,3", "0F0F0003")] [InlineData("16,10.0.0.5", "1F08" + "1000" + "31302E302E302E35")] public void Encodes_route(string path, string hex) => Convert.ToHexString(CipPath.EncodeRoute(path)).ShouldBe(hex); [Fact] public void Odd_route_parts_throw() => Should.Throw(() => CipPath.EncodeRoute("1,0,2")); [Theory] [InlineData("TestDINT", "9108546573744449 4E54")] [InlineData("Abc", "910341626300")] [InlineData("Program:Main.Arr[3].Val", "910C50726F6772616D3A4D61696E" + "910341727200" + "2803" + "910356616C00")] [InlineData("Big[300]", "910342696700" + "29002C01")] [InlineData("Huge[70000]", "910448756765" + "2A00" + "70110100")] [InlineData("Grid[1,2]", "910447726964" + "2801" + "2802")] public void Encodes_symbolic(string name, string hex) => Convert.ToHexString(CipPath.EncodeSymbolic(name)).ShouldBe(hex.Replace(" ", "")); [Fact] public void Symbolic_rejects_bit_selector() => Should.Throw(() => CipPath.EncodeSymbolic("Tag.5")); [Fact] public void Splits_bit_selector() { CipPath.SplitBitSelector("Tag.5").ShouldBe(("Tag", 5)); CipPath.SplitBitSelector("Tag.Member").ShouldBe(("Tag.Member", null)); CipPath.SplitBitSelector("Tag").ShouldBe(("Tag", null)); } [Theory] [InlineData(2, 1u, "20022401")] [InlineData(0x6B, 0x1234u, "206B25003412")] [InlineData(0x300, 1u, "21000003" + "2401")] [InlineData(2, 70000u, "2002" + "2600" + "70110100")] public void Encodes_class_instance(ushort cls, uint inst, string hex) => Convert.ToHexString(CipPath.EncodeClassInstance(cls, inst)).ShouldBe(hex); [Fact] public void Prefixes_path_size_in_words() => Convert.ToHexString(CipPath.WithPathSize([0x20, 0x02, 0x24, 0x01])).ShouldBe("0220022401"); }