fix(ab-transport): harden Task 7 codecs (read status, 32-bit start instance, empty-More, size range)

This commit is contained in:
Joseph Doherty
2026-10-07 16:06:49 -04:00
parent 5f86b370f7
commit 6d16765804
6 changed files with 55 additions and 13 deletions
@@ -1,3 +1,4 @@
using System.Buffers.Binary;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.Cip;
@@ -26,9 +27,9 @@ public sealed class ConnectionManagerServicesTests
public void Forward_close_matches_capture()
{
var cap = CapturedRequest("logix-forward-close.hex");
var serial = BitConverter.ToUInt16(cap, 8);
var vendor = BitConverter.ToUInt16(cap, 10);
var orig = BitConverter.ToUInt32(cap, 12);
var serial = BinaryPrimitives.ReadUInt16LittleEndian(cap.AsSpan(8));
var vendor = BinaryPrimitives.ReadUInt16LittleEndian(cap.AsSpan(10));
var orig = BinaryPrimitives.ReadUInt32LittleEndian(cap.AsSpan(12));
vendor.ShouldBe((ushort)0xF33D);
ConnectionManagerServices.ForwardClose(serial, vendor, orig, [0x01, 0x00]).ShouldBe(cap);
}
@@ -40,11 +41,11 @@ public sealed class ConnectionManagerServicesTests
// Values read out of the capture: T->O id @12, serial @16, vendor @18, originator serial @20,
// timeout multiplier @24, RPI @28, network params @32 (0x42000FA2 -> size 4002).
var p = new ForwardOpenParams(
Large: true, TOConnectionId: BitConverter.ToUInt32(cap, 12), ConnectionSerial: BitConverter.ToUInt16(cap, 16),
VendorId: BitConverter.ToUInt16(cap, 18), OriginatorSerial: BitConverter.ToUInt32(cap, 20),
TimeoutMultiplier: cap[24], RpiMicros: BitConverter.ToUInt32(cap, 28), ConnectionSize: 4002, Route: [0x01, 0x00]);
Large: true, TOConnectionId: BinaryPrimitives.ReadUInt32LittleEndian(cap.AsSpan(12)), ConnectionSerial: BinaryPrimitives.ReadUInt16LittleEndian(cap.AsSpan(16)),
VendorId: BinaryPrimitives.ReadUInt16LittleEndian(cap.AsSpan(18)), OriginatorSerial: BinaryPrimitives.ReadUInt32LittleEndian(cap.AsSpan(20)),
TimeoutMultiplier: cap[24], RpiMicros: BinaryPrimitives.ReadUInt32LittleEndian(cap.AsSpan(28)), ConnectionSize: 4002, Route: [0x01, 0x00]);
p.RpiMicros.ShouldBe(1_000_000u);
BitConverter.ToUInt32(cap, 32).ShouldBe(0x42000FA2u);
BinaryPrimitives.ReadUInt32LittleEndian(cap.AsSpan(32)).ShouldBe(0x42000FA2u);
ConnectionManagerServices.ForwardOpen(p).ShouldBe(cap);
}
@@ -111,4 +112,15 @@ public sealed class ConnectionManagerServicesTests
[InlineData("DB000000", false)]
public void Fallback_rules(string hex, bool expected) =>
ConnectionManagerServices.ShouldFallBackToRegularOpen(CipReply.Parse(Convert.FromHexString(hex))).ShouldBe(expected);
[Theory]
[InlineData(true, 0)] [InlineData(true, 0x10000)] [InlineData(false, 0)] [InlineData(false, 0x200)]
public void Connection_size_out_of_range_throws(bool large, int size) =>
Should.Throw<ArgumentOutOfRangeException>(() => ConnectionManagerServices.ForwardOpen(
new ForwardOpenParams(large, 1, 2, 3, 4, 1, 1_000_000, size, [])));
[Theory]
[InlineData(true, 1)] [InlineData(true, 0xFFFF)] [InlineData(false, 1)] [InlineData(false, 0x1FF)]
public void Connection_size_bounds_accepted(bool large, int size) =>
ConnectionManagerServices.ForwardOpen(new ForwardOpenParams(large, 1, 2, 3, 4, 1, 1_000_000, size, [])).ShouldNotBeEmpty();
}