4b14feb373
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.
47 lines
2.1 KiB
C#
47 lines
2.1 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests;
|
|
|
|
/// <summary>
|
|
/// Regression guard for the 2026-06-19 enum-serialization bug. The AdminUI S7 page now
|
|
/// serialises <see cref="S7CpuType"/> as a STRING (its <c>_jsonOpts</c> gained a
|
|
/// <see cref="JsonStringEnumConverter"/>). This proves the factory parses that AdminUI-shaped
|
|
/// blob and round-trips the enum, and documents that the pre-fix NUMERIC form — which the old
|
|
/// page emitted — threw because <c>S7DriverConfigDto.CpuType</c> is <c>string?</c>.
|
|
/// </summary>
|
|
public sealed class S7DriverConfigEnumSerializationTests
|
|
{
|
|
// Mirrors the (now fixed) AdminUI S7DriverPage._jsonOpts: camelCase + string enums.
|
|
private static readonly JsonSerializerOptions _adminPageOpts = new()
|
|
{
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
Converters = { new JsonStringEnumConverter() },
|
|
};
|
|
|
|
/// <summary>Verifies the factory parses an AdminUI-authored (string-enum) S7 config and
|
|
/// preserves the CpuType.</summary>
|
|
[Fact]
|
|
public void Factory_parses_admin_authored_string_enum_config()
|
|
{
|
|
var opts = new S7DriverOptions { Host = "10.0.0.5", Port = 102, CpuType = S7CpuType.S71500, Rack = 0, Slot = 1 };
|
|
var blob = JsonSerializer.Serialize(opts, _adminPageOpts);
|
|
// The fixed AdminUI page must emit the enum as a string, not a number.
|
|
blob.ShouldContain("\"cpuType\":\"S71500\"");
|
|
|
|
var parsed = S7DriverFactoryExtensions.ParseOptions("s7-test", blob);
|
|
parsed.CpuType.ShouldBe(S7CpuType.S71500);
|
|
}
|
|
|
|
/// <summary>Documents the original bug: the pre-fix AdminUI page emitted a numeric enum
|
|
/// (<c>"cpuType":40</c>) which the string-typed config 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\":102,\"cpuType\":40,\"rack\":0,\"slot\":1}";
|
|
Should.Throw<Exception>(() => S7DriverFactoryExtensions.ParseOptions("s7-test", numericBlob));
|
|
}
|
|
}
|