using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests; /// /// Gitea #610 — pins 's Modbus row against the REAL write path. For every /// region × element type, the server advertises an array node writable exactly when the driver accepts a /// whole-array write for it. A driver change that gains or loses an array encoder fails here until the table /// follows — so the server can never advertise a write this driver refuses (nor hide one it accepts). /// [Trait("Category", "Unit")] public sealed class ModbusArrayWriteSupportParityTests { private static IEnumerable<(ModbusRegion Region, ModbusDataType DataType)> Shapes() => from region in Enum.GetValues() from dt in Enum.GetValues() select (region, dt); public static TheoryData AllShapes() { var data = new TheoryData(); foreach (var (region, dt) in Shapes()) data.Add(region, dt); return data; } [Theory] [MemberData(nameof(AllShapes))] public async Task Table_agrees_with_the_driver_write_path(ModbusRegion region, ModbusDataType dataType) { var json = $$"""{"region":"{{region}}","address":10,"dataType":"{{dataType}}","stringLength":4,"isArray":true,"arrayLength":2}"""; var fake = new ModbusDriverTests.FakeTransport(); var drv = new ModbusDriver( new ModbusDriverOptions { Host = "fake", RawTags = [new RawTagEntry("cell/modbus/arr", json, false)] }, "modbus-array-parity", _ => fake); await drv.InitializeAsync("{}", CancellationToken.None); // A two-element value every element type can convert (Convert.ToBoolean / ToInt16 / ToSingle … of 1). var result = await drv.WriteAsync([new WriteRequest("cell/modbus/arr", new object[] { 1, 1 })], CancellationToken.None); var driverAccepts = result.Single().StatusCode == 0u; DriverArrayWriteSupport.Supports(DriverTypeNames.Modbus, "Int16", json).ShouldBe( driverAccepts, $"region={region} dataType={dataType}: driver status 0x{result.Single().StatusCode:X8}"); } /// Positive control: the theory above is not vacuously "everything refused". [Fact] public void The_matrix_contains_both_answers() { var answers = Shapes() .Select(s => DriverArrayWriteSupport.Supports( DriverTypeNames.Modbus, "Int16", $$"""{"region":"{{s.Region}}","address":10,"dataType":"{{s.DataType}}"}""")) .ToHashSet(); answers.ShouldBe(new[] { true, false }, ignoreOrder: true); } }