using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests; /// /// Coverage for the new ByteSwap (BADC) and FullReverse (DCBA) byte orders added by #137. /// The existing BigEndian (ABCD) and WordSwap (CDAB) cases live in . /// [Trait("Category", "Unit")] public sealed class ModbusByteOrderTests { [Fact] public void Int32_ByteSwap_decodes_BADC_layout() { // Value 0x12345678. PLC stores bytes within each register swapped: // register[0] = 0x3412, register[1] = 0x7856 → wire [0x34, 0x12, 0x78, 0x56]. var tag = new ModbusTagDefinition("T", ModbusRegion.HoldingRegisters, 0, ModbusDataType.Int32, ByteOrder: ModbusByteOrder.ByteSwap); var bytes = new byte[] { 0x34, 0x12, 0x78, 0x56 }; ModbusDriver.DecodeRegister(bytes, tag).ShouldBe(0x12345678); } [Fact] public void Int32_FullReverse_decodes_DCBA_layout() { // Value 0x12345678 stored fully little-endian: // wire [0x78, 0x56, 0x34, 0x12]. var tag = new ModbusTagDefinition("T", ModbusRegion.HoldingRegisters, 0, ModbusDataType.Int32, ByteOrder: ModbusByteOrder.FullReverse); var bytes = new byte[] { 0x78, 0x56, 0x34, 0x12 }; ModbusDriver.DecodeRegister(bytes, tag).ShouldBe(0x12345678); } [Theory] [InlineData(ModbusByteOrder.BigEndian)] [InlineData(ModbusByteOrder.WordSwap)] [InlineData(ModbusByteOrder.ByteSwap)] [InlineData(ModbusByteOrder.FullReverse)] public void Float32_All_ByteOrders_Roundtrip(ModbusByteOrder order) { var tag = new ModbusTagDefinition("T", ModbusRegion.HoldingRegisters, 0, ModbusDataType.Float32, ByteOrder: order); var wire = ModbusDriver.EncodeRegister(3.14159f, tag); wire.Length.ShouldBe(4); ModbusDriver.DecodeRegister(wire, tag).ShouldBe(3.14159f); } [Theory] [InlineData(ModbusByteOrder.BigEndian)] [InlineData(ModbusByteOrder.WordSwap)] [InlineData(ModbusByteOrder.ByteSwap)] [InlineData(ModbusByteOrder.FullReverse)] public void Float64_All_ByteOrders_Roundtrip(ModbusByteOrder order) { var tag = new ModbusTagDefinition("T", ModbusRegion.HoldingRegisters, 0, ModbusDataType.Float64, ByteOrder: order); var wire = ModbusDriver.EncodeRegister(2.718281828459045d, tag); wire.Length.ShouldBe(8); ModbusDriver.DecodeRegister(wire, tag).ShouldBe(2.718281828459045d); } [Theory] [InlineData(ModbusByteOrder.BigEndian)] [InlineData(ModbusByteOrder.WordSwap)] [InlineData(ModbusByteOrder.ByteSwap)] [InlineData(ModbusByteOrder.FullReverse)] public void Int32_All_ByteOrders_Roundtrip(ModbusByteOrder order) { var tag = new ModbusTagDefinition("T", ModbusRegion.HoldingRegisters, 0, ModbusDataType.Int32, ByteOrder: order); var wire = ModbusDriver.EncodeRegister(unchecked((int)0xDEADBEEF), tag); wire.Length.ShouldBe(4); ModbusDriver.DecodeRegister(wire, tag).ShouldBe(unchecked((int)0xDEADBEEF)); } }