review(Driver.TwinCAT): thread ArrayLength through factory DTO (Medium)

Re-review at 7286d320. -017 (Medium): TwinCATTagDto lacked ArrayLength, so JSON-authored
pre-declared array tags were silently scalar (Phase-4c array path dead for them). Fix:
add ArrayLength to the DTO + thread through BuildTag with positive-value guard + TDD.
This commit is contained in:
Joseph Doherty
2026-06-19 11:47:11 -04:00
parent 91e2609560
commit 22f7d92b72
3 changed files with 130 additions and 3 deletions
@@ -186,6 +186,69 @@ public sealed class TwinCATArraySupportTests
def!.ArrayLength.ShouldBeNull();
}
// ---- (4) Driver.TwinCAT-017 — pre-declared array tag parseable via driver config JSON ----
/// <summary>
/// A pre-declared tag in the driver config JSON with <c>arrayLength</c> must produce a
/// <see cref="TwinCATTagDefinition"/> with the correct <see cref="TwinCATTagDefinition.ArrayLength"/>,
/// which in turn drives <c>IsArray</c>/<c>ArrayDim</c> at discovery and a native array read
/// at runtime (Driver.TwinCAT-017).
/// </summary>
[Fact]
public void Predeclared_array_tag_arrayLength_parses_from_driver_config_json()
{
var json = System.Text.Json.JsonSerializer.Serialize(new
{
devices = new[] { new { hostAddress = Host } },
tags = new[]
{
new
{
name = "Speeds",
deviceHostAddress = Host,
symbolPath = "MAIN.Speeds",
dataType = "DInt",
arrayLength = 8,
},
},
});
var parsed = TwinCATDriverFactoryExtensions.ParseOptionsForTests(json, "drv-1");
parsed.Tags.Single().ArrayLength.ShouldBe(8);
}
/// <summary>
/// A pre-declared array tag parsed from JSON must surface as <c>IsArray=true</c> /
/// <c>ArrayDim=8</c> in the discovery address space.
/// </summary>
[Fact]
public async Task Predeclared_array_tag_from_json_reports_IsArray_in_discovery()
{
var configJson = System.Text.Json.JsonSerializer.Serialize(new
{
devices = new[] { new { hostAddress = Host } },
tags = new[]
{
new
{
name = "Speeds",
deviceHostAddress = Host,
symbolPath = "MAIN.Speeds",
dataType = "DInt",
arrayLength = 8,
},
},
});
var builder = new RecordingBuilder();
var drv = new TwinCATDriver(new TwinCATDriverOptions(), "drv-1", new FakeTwinCATClientFactory());
await drv.InitializeAsync(configJson, CancellationToken.None);
await drv.DiscoverAsync(builder, CancellationToken.None);
var v = builder.Variables.Single(x => x.BrowseName == "Speeds").Info;
v.IsArray.ShouldBeTrue();
v.ArrayDim.ShouldBe(8u);
}
// ---- helpers ----
private sealed class RecordingBuilder : IAddressSpaceBuilder