fix(opcua): equipment-tag planner diff + folder-scoped NodeIds (review findings)
Two bundle-review fixes + idempotency coverage: - CRITICAL: the planner ignored EquipmentTags, so an incremental deploy changing only equipment tags produced an empty plan and HandleRebuild short-circuited before materialising them. Add TagId to EquipmentTagPlan + Added/Removed/ChangedEquipmentTags to Phase7Plan (diffed by TagId, in IsEmpty, driving Apply's needsRebuild) — mirroring the GalaxyTags treatment. - IMPORTANT: equipment variable NodeId was the raw driver FullName, which collides across identical machines (e.g. two PLCs both exposing register 40001) — the second variable was silently dropped. NodeId is now folder-scoped (parent/Name); FullName stays on EquipmentTagPlan for the later values-routing milestone. - Task 4: SDK-backed idempotency test (double-apply -> single variable); restart-safety confirmed (RestoreApplied reuses the same RebuildAddressSpace -> HandleRebuild path). - Minor: align composer equipment-tag sort with the artifact decoder (coalesce FolderPath).
This commit is contained in:
@@ -30,6 +30,31 @@ public sealed class Phase7PlannerTests
|
||||
plan.IsEmpty.ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>Verifies an equipment-tag-only delta (no equipment/driver/alarm/galaxy change)
|
||||
/// yields a NON-empty plan, so OpcUaPublishActor.HandleRebuild does not short-circuit at the
|
||||
/// IsEmpty gate before materialising the new equipment variables.</summary>
|
||||
[Fact]
|
||||
public void Equipment_tag_only_change_yields_non_empty_plan_with_added_tag()
|
||||
{
|
||||
var prev = new Phase7CompositionResult(
|
||||
Array.Empty<EquipmentNode>(), Array.Empty<DriverInstancePlan>(), Array.Empty<ScriptedAlarmPlan>());
|
||||
var next = new Phase7CompositionResult(
|
||||
Array.Empty<EquipmentNode>(), Array.Empty<DriverInstancePlan>(), Array.Empty<ScriptedAlarmPlan>())
|
||||
{
|
||||
EquipmentTags = new[]
|
||||
{
|
||||
new EquipmentTagPlan("tag-1", "eq-1", "drv", FolderPath: "", Name: "Speed", DataType: "Float", FullName: "40001"),
|
||||
},
|
||||
};
|
||||
|
||||
var plan = Phase7Planner.Compute(prev, next);
|
||||
|
||||
plan.IsEmpty.ShouldBeFalse();
|
||||
plan.AddedEquipmentTags.Single().TagId.ShouldBe("tag-1");
|
||||
plan.RemovedEquipmentTags.ShouldBeEmpty();
|
||||
plan.ChangedEquipmentTags.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>Verifies that new equipment goes to the AddedEquipment list.</summary>
|
||||
[Fact]
|
||||
public void New_equipment_goes_to_AddedEquipment()
|
||||
|
||||
Reference in New Issue
Block a user