using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests; /// /// Pins 's AbLegacy row against the REAL array encoder /// (), the same way the Modbus and S7 parity tests do: for every element /// type the server must advertise an array node writable exactly when the driver encodes it. /// /// /// ⚠️ SKIPPED until follow-up F1 lands: the driver gained an array encoder in this lane (review 07 U10), but /// (Core.Abstractions, not owned by the AbLegacy lane) still lists AbLegacy as /// scalar-only, so every AbLegacy array node stays read-only and the encoder is unreachable from OPC UA. When F1 /// adds the row, delete the Skip; this test then holds the table and the encoder together. /// [Trait("Category", "Unit")] public sealed class AbLegacyArrayWriteSupportParityTests { public static TheoryData AllTypes() => new(Enum.GetValues()); private static string AddressFor(AbLegacyDataType t) => t switch { AbLegacyDataType.Float => "F8:0", AbLegacyDataType.Long => "L9:0", AbLegacyDataType.Bit => "B3:0", AbLegacyDataType.String => "ST9:0", AbLegacyDataType.TimerElement => "T4:0", AbLegacyDataType.CounterElement => "C5:0", AbLegacyDataType.ControlElement => "R6:0", _ => "N7:0", }; [Theory(Skip = "F1: DriverArrayWriteSupport has no AbLegacy row yet (Core.Abstractions is outside this lane)")] [MemberData(nameof(AllTypes))] public void Table_agrees_with_the_array_encoder(AbLegacyDataType dataType) { var json = $$"""{"address":"{{AddressFor(dataType)}}","dataType":"{{dataType}}","isArray":true,"arrayLength":2}"""; var encoderAccepts = AbLegacyTagDefinitionFactory.FromTagConfig(json, "p", out _) && AbLegacyArrayWriteEncoder.TryConvert(dataType, new object[] { 1, 1 }, 2, out _) == AbLegacyStatusMapper.Good; DriverArrayWriteSupport.Supports(DriverTypeNames.AbLegacy, "Int16", json).ShouldBe(encoderAccepts, dataType.ToString()); } /// What the encoder accepts today — the row F1 must add (Int, AnalogInt, Long, Float). [Theory] [InlineData(AbLegacyDataType.Int, true)] [InlineData(AbLegacyDataType.AnalogInt, true)] [InlineData(AbLegacyDataType.Long, true)] [InlineData(AbLegacyDataType.Float, true)] [InlineData(AbLegacyDataType.Bit, false)] [InlineData(AbLegacyDataType.String, false)] [InlineData(AbLegacyDataType.TimerElement, false)] public void Encoder_accepts_exactly_the_flat_numeric_element_types(AbLegacyDataType dataType, bool accepts) => (AbLegacyArrayWriteEncoder.TryConvert(dataType, new object[] { 1, 1 }, 2, out _) == AbLegacyStatusMapper.Good) .ShouldBe(accepts); }