fix(code-review): resolve Batch 2 open findings (AbCip, AbLegacy, Galaxy, FOCAS)

- Driver.AbCip.Contracts-001: parse 'writable' from TagConfig JSON (default true) instead of hardcoding
- Driver.AbCip.Contracts-002/-003: Dt type comment; drop dead [Display]/[Range] annotations
- Driver.AbCip.Contracts-004: dedicated AbCipEquipmentTagParser test class (+15)
- Driver.AbCip-017: document Tick severity Low-fallback on Bad severity read
- Driver.AbLegacy.Contracts-002/-003/-004: isArray-scalar remarks (+tests), MaxTagBytes/ForFamily docs
- Driver.Galaxy.Browser-003 + Driver.Galaxy.Contracts-003: extract ResolveApiKey -> GalaxySecretRef (dedup)
- Driver.Galaxy-019: cache buffered-interval only on Ok + ILogger warnings + ClassifyIntervalReply (+tests)
- Driver.FOCAS.Contracts-002: thread WriteIdempotent through DiscoverAsync (+test)
This commit is contained in:
Joseph Doherty
2026-06-20 22:43:36 -04:00
parent 3cc6a5f30d
commit ab57e53b92
26 changed files with 577 additions and 220 deletions
@@ -37,6 +37,32 @@ public sealed class AbLegacyEquipmentTagTests
=> AbLegacyEquipmentTagParser.TryParse(
"""{"address":"","dataType":"Int"}""", out _).ShouldBeFalse();
// -002 regression: isArray:true without a valid positive arrayLength → scalar (null ArrayLength).
[Fact]
public void IsArray_true_with_arrayLength_zero_produces_scalar()
{
var json = """{"address":"N7:0","dataType":"Int","isArray":true,"arrayLength":0}""";
AbLegacyEquipmentTagParser.TryParse(json, out var def).ShouldBeTrue();
def!.ArrayLength.ShouldBeNull();
}
[Fact]
public void IsArray_true_with_no_arrayLength_produces_scalar()
{
var json = """{"address":"N7:0","dataType":"Int","isArray":true}""";
AbLegacyEquipmentTagParser.TryParse(json, out var def).ShouldBeTrue();
def!.ArrayLength.ShouldBeNull();
}
[Fact]
public void IsArray_true_with_negative_arrayLength_produces_scalar()
{
var json = """{"address":"N7:0","dataType":"Int","isArray":true,"arrayLength":-5}""";
AbLegacyEquipmentTagParser.TryParse(json, out var def).ShouldBeTrue();
def!.ArrayLength.ShouldBeNull();
}
/// <summary>
/// End-to-end driver-level proof: an AbLegacy driver with NO authored tags can still read an
/// equipment-tag ref (the raw TagConfig JSON) — the resolver parses it into a transient