fix(abcip): thread CIP template-instance-id so discovered-UDT expansion works in production (review)

This commit is contained in:
Joseph Doherty
2026-06-17 20:30:12 -04:00
parent fdd6b332fe
commit 4a7b0fde7b
6 changed files with 239 additions and 20 deletions
@@ -98,11 +98,15 @@ public sealed class CipSymbolObjectDecoderTests
CipSymbolObjectDecoder.MapTypeCode(0xFF).ShouldBeNull();
}
/// <summary>Verifies that struct flag overrides type code.</summary>
/// <summary>
/// Verifies that the struct flag overrides the type code AND that the lower 12 bits are
/// surfaced as the CIP template instance id (used by discovery to fetch the UDT's Template
/// Object). This is the plumbing that makes top-level discovered-UDT expansion functional.
/// </summary>
[Fact]
public void Struct_flag_overrides_type_code_and_yields_Structure()
public void Struct_flag_yields_Structure_and_surfaces_template_instance_id()
{
// 0x8000 (struct) + 0x1234 (template instance id in lower 12 bits; uses 0x234)
// 0x8000 (struct flag) | 0x0234 (template instance id in the lower 12 bits)
var bytes = BuildEntry(
instanceId: 5,
symbolType: 0x8000 | 0x0234,
@@ -112,6 +116,25 @@ public sealed class CipSymbolObjectDecoderTests
var tag = CipSymbolObjectDecoder.Decode(bytes).Single();
tag.DataType.ShouldBe(AbCipDataType.Structure);
tag.TemplateInstanceId.ShouldBe(0x0234u);
}
/// <summary>
/// Verifies that an atomic (non-struct) symbol carries no template instance id — only struct
/// symbols repurpose the lower 12 bits as a template id.
/// </summary>
[Fact]
public void Atomic_symbol_has_no_template_instance_id()
{
var bytes = BuildEntry(
instanceId: 7,
symbolType: 0xC4, // DINT — atomic, not a struct
elementLength: 4,
arrayDims: (0, 0, 0),
name: "Counter");
var tag = CipSymbolObjectDecoder.Decode(bytes).Single();
tag.TemplateInstanceId.ShouldBeNull();
}
/// <summary>Verifies that system flag surfaces as IsSystemTag true.</summary>