using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.TwinCAT; namespace ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Tests; [Trait("Category", "Unit")] public sealed class TwinCATAmsAddressTests { [Theory] [InlineData("ads://5.23.91.23.1.1:851", "5.23.91.23.1.1", 851)] [InlineData("ads://5.23.91.23.1.1:852", "5.23.91.23.1.1", 852)] [InlineData("ads://5.23.91.23.1.1", "5.23.91.23.1.1", 851)] // default port [InlineData("ads://127.0.0.1.1.1:851", "127.0.0.1.1.1", 851)] [InlineData("ADS://5.23.91.23.1.1:851", "5.23.91.23.1.1", 851)] // case-insensitive scheme [InlineData("ads://10.0.0.1.1.1:10000", "10.0.0.1.1.1", 10000)] // system service port public void TryParse_accepts_valid_ams_addresses(string input, string netId, int port) { var parsed = TwinCATAmsAddress.TryParse(input); parsed.ShouldNotBeNull(); parsed.NetId.ShouldBe(netId); parsed.Port.ShouldBe(port); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] [InlineData("tcp://5.23.91.23.1.1:851")] // wrong scheme [InlineData("ads:5.23.91.23.1.1:851")] // missing // [InlineData("ads://")] // empty body [InlineData("ads://5.23.91.23.1:851")] // only 5 octets [InlineData("ads://5.23.91.23.1.1.1:851")] // 7 octets [InlineData("ads://5.23.91.256.1.1:851")] // octet > 255 [InlineData("ads://5.23.91.23.1.1:0")] // port 0 [InlineData("ads://5.23.91.23.1.1:65536")] // port out of range [InlineData("ads://5.23.91.23.1.1:abc")] // non-numeric port [InlineData("ads://a.b.c.d.e.f:851")] // non-numeric octets public void TryParse_rejects_invalid_forms(string? input) { TwinCATAmsAddress.TryParse(input).ShouldBeNull(); } [Theory] [InlineData("5.23.91.23.1.1", 851, "ads://5.23.91.23.1.1")] // default port stripped [InlineData("5.23.91.23.1.1", 852, "ads://5.23.91.23.1.1:852")] public void ToString_canonicalises(string netId, int port, string expected) { new TwinCATAmsAddress(netId, port).ToString().ShouldBe(expected); } [Fact] public void RoundTrip_is_stable() { const string input = "ads://5.23.91.23.1.1:852"; var parsed = TwinCATAmsAddress.TryParse(input)!; TwinCATAmsAddress.TryParse(parsed.ToString()).ShouldBe(parsed); } }