using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Cip; namespace ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Tests.Wire; public sealed class CipReplyTests { [Fact] public void Parses_success_reply_with_data() { // 0xCC = reply to Read Tag 0x4C; reserved; status 0; ext size 0; data C4 00 2A 00 00 00 var r = CipReply.Parse(new byte[] { 0xCC, 0x00, 0x00, 0x00, 0xC4, 0x00, 0x2A, 0x00, 0x00, 0x00 }); r.Service.ShouldBe((byte)0x4C); r.GeneralStatus.ShouldBe((byte)0); r.ExtendedStatus.Length.ShouldBe(0); r.Data.ToArray().ShouldBe(new byte[] { 0xC4, 0x00, 0x2A, 0x00, 0x00, 0x00 }); } [Fact] public void Parses_reply_with_one_extended_word() { var r = CipReply.Parse(new byte[] { 0xCC, 0x00, 0xFF, 0x01, 0x07, 0x21 }); r.ExtendedStatus.ToArray().ShouldBe(new ushort[] { 0x2107 }); r.Status.ShouldBe(AbStatus.TypeMismatch); } [Fact] public void Parses_error_reply_with_two_extended_words() { var r = CipReply.Parse(new byte[] { 0xCC, 0x00, 0xFF, 0x02, 0x05, 0x21, 0x00, 0x00 }); r.GeneralStatus.ShouldBe((byte)0xFF); r.ExtendedStatus.ToArray().ShouldBe(new ushort[] { 0x2105, 0x0000 }); r.Data.Length.ShouldBe(0); r.Status.ShouldBe(AbStatus.OutOfBounds); } [Fact] public void Truncated_reply_throws_BadReply() { var ex = Should.Throw(() => CipReply.Parse(new byte[] { 0xCC, 0x00 })); ex.Status.ShouldBe(AbStatus.BadReply); } }