fix(drivers): flip runtime tag parsers to strict enum parsing (#457)
R2-11 Phase C. All six equipment-tag parsers (Modbus/S7/AbCip/AbLegacy/ TwinCAT/Focas) now read enum fields via the new TagConfigJson.TryReadEnumStrict: absent -> fallback, valid -> parsed, present-but-invalid (typo) -> TryParse returns false -> EquipmentTagRefResolver.TryResolve false -> driver surfaces BadNodeIdUnknown, instead of the old lenient path that silently defaulted a typo to a wrong-width Good. Modbus flips all three enum fields (region/dataType/byteOrder); the other five flip dataType. The deploy-time Deployment:TagConfigValidationMode=Error gate is unchanged and remains the operator pre-flight. Coverage: - Six *EquipmentTagParserStrictnessTests inverted from Freeze_typo_* (lenient) to Typo_*_rejects_the_tag + Valid_*_still_parses. - TagConfigJsonTests.TryReadEnumStrict_rejects_only_invalid matrix. - Driver-level end-to-end proof: AbCipEquipmentTagTests.Driver_read_of_a_typod_dataType_ref_surfaces_BadNodeIdUnknown drives the real AbCipDriver.ReadAsync through resolve->status. Golden parity corpus has no typo'd enums, so the flip is a no-op there. Full solution builds clean; all six driver suites + core + parity + gate green.
This commit is contained in:
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests;
|
||||
/// Pins the shared strict-capable TagConfig field readers (R2-11, 05/CONV-2): the
|
||||
/// <see cref="TagConfigJson.TryReadEnum{TEnum}"/> Absent/Valid/Invalid matrix (case-insensitive),
|
||||
/// <see cref="TagConfigJson.ReadEnumOrDefault{TEnum}"/> lenient equivalence to the retired copies,
|
||||
/// <see cref="TagConfigJson.TryReadEnumStrict{TEnum}"/> reject-only-invalid semantics (R2-11 Phase C),
|
||||
/// <see cref="TagConfigJson.ReadWritable"/> explicit-false-only semantics, and
|
||||
/// <see cref="TagConfigJson.DescribeInvalidEnum{TEnum}"/> messages.
|
||||
/// </summary>
|
||||
@@ -44,6 +45,18 @@ public sealed class TagConfigJsonTests
|
||||
TagConfigJson.ReadEnumOrDefault(Root(json), "k", Sample.Alpha).ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{\"k\":\"Gamma\"}", true, Sample.Gamma)] // valid → parsed, ok
|
||||
[InlineData("{}", true, Sample.Alpha)] // absent → fallback, ok
|
||||
[InlineData("{\"k\":42}", true, Sample.Alpha)] // non-string → Absent → fallback, ok
|
||||
[InlineData("{\"k\":\"typo\"}", false, default(Sample))] // invalid (typo) → REJECT (false)
|
||||
public void TryReadEnumStrict_rejects_only_invalid(string json, bool expectedOk, Sample expectedValue)
|
||||
{
|
||||
var ok = TagConfigJson.TryReadEnumStrict(Root(json), "k", Sample.Alpha, out var v);
|
||||
ok.ShouldBe(expectedOk);
|
||||
v.ShouldBe(expectedValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{\"writable\":false}", true, false)] // explicit false → false
|
||||
[InlineData("{\"writable\":true}", true, true)] // explicit true → default
|
||||
|
||||
Reference in New Issue
Block a user