fix(drivers): serialize driver-config enums as strings in AdminUI pages + probes
AdminUI driver-instance pages serialized enum config fields (S7 CpuType, Modbus DataType/Region, AbCip PlcFamily, ...) as JSON *numbers* because each page's _jsonOpts lacked a JsonStringEnumConverter. The driver factories, however, deserialize into string-typed DTOs (+ lenient ParseEnum) and throw when binding a JSON number to a string? — so an AdminUI-authored config containing any enum field produced a blob the driver could not parse, faulting the driver on deploy. Proven end-to-end for S7 and Modbus; latent for AbCip/AbLegacy/TwinCAT/FOCAS/Galaxy/Historian. Only OpcUaClient was safe (its factory + probe already carried the converter). Add JsonStringEnumConverter to all 9 driver-instance pages' _jsonOpts and the 8 missing driver probes' _opts (factories unchanged — already string-via- ParseEnum; strictly more permissive, also lets pages load hand-seeded string-enum configs back into the form). Also fix DriverProbeHandshakeE2eTests.AbCip_Green_AgainstSim to probe a real sim tag (TestDINT) — the no-tags @raw_cpu_type fallback is rejected by the ab_server sim with ErrorBadParam (a real ControlLogix returns ErrorNotFound, which the probe treats as reachable; hardware-gated follow-up). Tests: reflection guard over all driver pages' _jsonOpts (AdminUI.Tests); factory round-trip + numeric-form-throws guards for S7 and Modbus. Found by running the never-before-run FB-9/FB-10 live verifies.
This commit is contained in:
+49
@@ -0,0 +1,49 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Regression guard for the 2026-06-19 enum-serialization bug (the FB-9 Modbus-Int64 authoring
|
||||
/// case). The AdminUI Modbus page now serialises tag enums (<see cref="ModbusRegion"/>,
|
||||
/// <see cref="ModbusDataType"/>, byte-order) as STRINGS. This proves the factory parses that
|
||||
/// AdminUI-shaped Int64-tag blob, and documents that the pre-fix NUMERIC form threw because the
|
||||
/// <c>ModbusTagDto</c> enum fields are <c>string?</c>.
|
||||
/// </summary>
|
||||
public sealed class ModbusDriverConfigEnumSerializationTests
|
||||
{
|
||||
// Mirrors the (now fixed) AdminUI ModbusDriverPage._jsonOpts: camelCase + string enums.
|
||||
private static readonly JsonSerializerOptions _adminPageOpts = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Converters = { new JsonStringEnumConverter() },
|
||||
};
|
||||
|
||||
/// <summary>Verifies the factory parses an AdminUI-authored Modbus config carrying an Int64
|
||||
/// holding-register tag (string enums) without throwing.</summary>
|
||||
[Fact]
|
||||
public void Factory_parses_admin_authored_int64_string_enum_config()
|
||||
{
|
||||
var tag = new ModbusTagDefinition("Int64Tag", ModbusRegion.HoldingRegisters, (ushort)100, ModbusDataType.Int64);
|
||||
var opts = new ModbusDriverOptions { Host = "10.0.0.5", Port = 502, UnitId = 1, Tags = new[] { tag } };
|
||||
var blob = JsonSerializer.Serialize(opts, _adminPageOpts);
|
||||
// The fixed AdminUI page must emit tag enums as strings, not numbers.
|
||||
blob.ShouldContain("\"dataType\":\"Int64\"");
|
||||
|
||||
using var driver = ModbusDriverFactoryExtensions.CreateInstance("mb-test", blob);
|
||||
driver.DriverType.ShouldBe("Modbus");
|
||||
}
|
||||
|
||||
/// <summary>Documents the original bug: the pre-fix AdminUI page emitted numeric tag enums
|
||||
/// (<c>"dataType":5,"region":3</c>) which the string-typed tag DTO cannot bind, so the factory throws.</summary>
|
||||
[Fact]
|
||||
public void Factory_throws_on_the_numeric_enum_form_the_pre_fix_page_emitted()
|
||||
{
|
||||
const string numericBlob =
|
||||
"{\"host\":\"10.0.0.5\",\"port\":502,\"unitId\":1,\"tags\":[" +
|
||||
"{\"name\":\"Int64Tag\",\"region\":3,\"address\":100,\"dataType\":5}]}";
|
||||
Should.Throw<Exception>(() => ModbusDriverFactoryExtensions.CreateInstance("mb-test", numericBlob));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user