feat(opcua): remove SystemPlatform-mirror GalaxyTags contract end-to-end (composer+applier+artifact, byte-parity)
This commit is contained in:
+32
-16
@@ -102,10 +102,11 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
/// Wiring proof for per-ClusterId scoping (Task 4): a multi-cluster artifact must
|
||||
/// materialise ONLY the local node's cluster slice. Mirrors the multi-cluster artifact
|
||||
/// shape exercised in <c>DeploymentArtifactTests</c> (MAIN + SITE-A, one Galaxy driver +
|
||||
/// one SystemPlatform tag each). The scoped rebuild for the SITE-A node must surface the
|
||||
/// SITE-A tag (<c>t-sa</c> → variable <c>F.S1</c>) and NOT MAIN's (<c>t-main</c> →
|
||||
/// <c>F.M1</c>); the mirror holds for the MAIN node. Without the production scoping edit,
|
||||
/// the unscoped parse would materialise BOTH variables on every node.
|
||||
/// one equipment tag each — Galaxy points are ordinary equipment tags now). The scoped
|
||||
/// rebuild for the SITE-A node must surface the SITE-A tag (<c>t-sa</c> → folder-scoped
|
||||
/// variable <c>eq-sa/F/S1</c>) and NOT MAIN's (<c>t-main</c> → <c>eq-main/F/M1</c>); the
|
||||
/// mirror holds for the MAIN node. Without the production scoping edit, the unscoped parse
|
||||
/// would materialise BOTH variables on every node.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Rebuild_materialises_only_the_nodes_cluster()
|
||||
@@ -125,10 +126,10 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
siteActor.Tell(new OpcUaPublishActor.RebuildAddressSpace(CorrelationId.NewId()));
|
||||
|
||||
AwaitAssert(() => sinkA.RebuildCalls.ShouldBe(1), duration: TimeSpan.FromSeconds(2));
|
||||
// t-sa (Name "S1", FolderPath "F") → MxAccessRef "F.S1" → variable node "F.S1".
|
||||
sinkA.Calls.ShouldContain("EV:F.S1");
|
||||
// t-sa (EquipmentId "eq-sa", FolderPath "F", Name "S1") → folder-scoped variable "eq-sa/F/S1".
|
||||
sinkA.Calls.ShouldContain("EV:eq-sa/F/S1");
|
||||
// t-main (MAIN cluster) must NOT leak onto the SITE-A node.
|
||||
sinkA.Calls.ShouldNotContain("EV:F.M1");
|
||||
sinkA.Calls.ShouldNotContain("EV:eq-main/F/M1");
|
||||
|
||||
// --- MAIN node: the mirror — only MAIN's tag's variable, never SITE-A's. ---
|
||||
var dbM = NewInMemoryDbFactory();
|
||||
@@ -145,15 +146,15 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
mainActor.Tell(new OpcUaPublishActor.RebuildAddressSpace(CorrelationId.NewId()));
|
||||
|
||||
AwaitAssert(() => sinkM.RebuildCalls.ShouldBe(1), duration: TimeSpan.FromSeconds(2));
|
||||
sinkM.Calls.ShouldContain("EV:F.M1");
|
||||
sinkM.Calls.ShouldNotContain("EV:F.S1");
|
||||
sinkM.Calls.ShouldContain("EV:eq-main/F/M1");
|
||||
sinkM.Calls.ShouldNotContain("EV:eq-sa/F/S1");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seal a 2-cluster deployment (MAIN + SITE-A) whose artifact mirrors the multi-cluster
|
||||
/// shape the composer emits: a <c>Clusters</c> + <c>Nodes</c> map, one SystemPlatform
|
||||
/// namespace + Galaxy driver + Galaxy tag per cluster. Used by
|
||||
/// <see cref="Rebuild_materialises_only_the_nodes_cluster"/>.
|
||||
/// shape the composer emits: a <c>Clusters</c> + <c>Nodes</c> map, one Equipment namespace +
|
||||
/// Galaxy driver + equipment tag per cluster (Galaxy points are ordinary equipment tags now).
|
||||
/// Used by <see cref="Rebuild_materialises_only_the_nodes_cluster"/>.
|
||||
/// </summary>
|
||||
private static void SeedMultiClusterDeployment(IDbContextFactory<OtOpcUaConfigDbContext> dbFactory)
|
||||
{
|
||||
@@ -165,6 +166,21 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
new { NodeId = "central-1:4053", ClusterId = "MAIN" },
|
||||
new { NodeId = "site-a-1:4053", ClusterId = "SITE-A" },
|
||||
},
|
||||
UnsAreas = new[]
|
||||
{
|
||||
new { UnsAreaId = "area-main", ClusterId = "MAIN", Name = "main-area" },
|
||||
new { UnsAreaId = "area-sa", ClusterId = "SITE-A", Name = "sa-area" },
|
||||
},
|
||||
UnsLines = new[]
|
||||
{
|
||||
new { UnsLineId = "line-main", UnsAreaId = "area-main", Name = "main-line" },
|
||||
new { UnsLineId = "line-sa", UnsAreaId = "area-sa", Name = "sa-line" },
|
||||
},
|
||||
Equipment = new[]
|
||||
{
|
||||
new { EquipmentId = "eq-main", DriverInstanceId = "main-galaxy", UnsLineId = "line-main", Name = "eq-main", MachineCode = "EQ-MAIN" },
|
||||
new { EquipmentId = "eq-sa", DriverInstanceId = "sa-galaxy", UnsLineId = "line-sa", Name = "eq-sa", MachineCode = "EQ-SA" },
|
||||
},
|
||||
DriverInstances = new[]
|
||||
{
|
||||
new { DriverInstanceId = "main-galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}", ClusterId = "MAIN", NamespaceId = "main-ns" },
|
||||
@@ -172,13 +188,13 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
},
|
||||
Namespaces = new[]
|
||||
{
|
||||
new { NamespaceId = "main-ns", ClusterId = "MAIN", Kind = 1 }, // NamespaceKind.SystemPlatform
|
||||
new { NamespaceId = "sa-ns", ClusterId = "SITE-A", Kind = 1 },
|
||||
new { NamespaceId = "main-ns", ClusterId = "MAIN", Kind = 0 }, // NamespaceKind.Equipment
|
||||
new { NamespaceId = "sa-ns", ClusterId = "SITE-A", Kind = 0 },
|
||||
},
|
||||
Tags = new[]
|
||||
{
|
||||
new { TagId = "t-main", DriverInstanceId = "main-galaxy", EquipmentId = (string?)null, Name = "M1", FolderPath = "F", DataType = "Boolean", TagConfig = "{}" },
|
||||
new { TagId = "t-sa", DriverInstanceId = "sa-galaxy", EquipmentId = (string?)null, Name = "S1", FolderPath = "F", DataType = "Boolean", TagConfig = "{}" },
|
||||
new { TagId = "t-main", DriverInstanceId = "main-galaxy", EquipmentId = (string?)"eq-main", Name = "M1", FolderPath = "F", DataType = "Boolean", TagConfig = "{}" },
|
||||
new { TagId = "t-sa", DriverInstanceId = "sa-galaxy", EquipmentId = (string?)"eq-sa", Name = "S1", FolderPath = "F", DataType = "Boolean", TagConfig = "{}" },
|
||||
},
|
||||
ScriptedAlarms = Array.Empty<object>(),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user