using System.Text.Json; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Runtime.Drivers; namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers; /// /// Verifies the artifact-decode mirror () /// treats a Galaxy point as an ordinary equipment tag — an equipment-scoped tag (non-null /// EquipmentId) bound to a GalaxyMxGateway driver in an Equipment-kind namespace — /// into the decoded EquipmentTags with byte-parity to the live-edit composer path: same FullName, /// EquipmentId, DriverInstanceId, Name, DataType. Both data-contract sites gate purely on the namespace /// Kind being Equipment (no Galaxy/DriverType exception — the SystemPlatform-mirror contract is /// retired), so they agree on which tags qualify. /// public sealed class DeploymentArtifactAliasParityTests { /// An artifact JSON blob with a GalaxyMxGateway driver in an Equipment (Kind=0) namespace and /// one equipment-scoped tag (EquipmentId set, FolderPath null, FullName = the Galaxy ref). Decode must /// surface the tag in EquipmentTags carrying its driver-side FullName, coalescing the null FolderPath to /// string.Empty. [Fact] public void ParseComposition_admits_galaxy_equipment_tag_in_equipment_tags() { var blob = JsonSerializer.SerializeToUtf8Bytes(new { Namespaces = new[] { new { NamespaceId = "ns-eq", Kind = 0 }, // NamespaceKind.Equipment }, DriverInstances = new[] { new { DriverInstanceId = "drv-galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}", NamespaceId = "ns-eq" }, }, Tags = new object[] { new { TagId = "tag-galaxy", DriverInstanceId = "drv-galaxy", EquipmentId = "eq-1", Name = "TestChangingInt", FolderPath = (string?)null, DataType = "Int32", TagConfig = "{\"FullName\":\"TestMachine_020.TestChangingInt\"}", }, }, }); var c = DeploymentArtifact.ParseComposition(blob); var tag = c.EquipmentTags.ShouldHaveSingleItem(); tag.TagId.ShouldBe("tag-galaxy"); tag.EquipmentId.ShouldBe("eq-1"); tag.DriverInstanceId.ShouldBe("drv-galaxy"); tag.Name.ShouldBe("TestChangingInt"); tag.DataType.ShouldBe("Int32"); tag.FolderPath.ShouldBe(string.Empty); tag.FullName.ShouldBe("TestMachine_020.TestChangingInt"); } /// An equipment-scoped GalaxyMxGateway tag in a SystemPlatform-kind namespace must NOT surface /// in EquipmentTags — byte-parity with the composer's pure ns.Kind == NamespaceKind.Equipment /// predicate. The retired SystemPlatform-mirror contract no longer carried a DriverType exception, so a /// non-Equipment namespace excludes the tag regardless of driver type. [Fact] public void ParseComposition_excludes_galaxy_tag_in_non_equipment_namespace() { var blob = JsonSerializer.SerializeToUtf8Bytes(new { Namespaces = new[] { new { NamespaceId = "ns-sp", Kind = 1 }, // NamespaceKind.SystemPlatform }, DriverInstances = new[] { new { DriverInstanceId = "drv-galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}", NamespaceId = "ns-sp" }, }, Tags = new object[] { new { TagId = "tag-x", DriverInstanceId = "drv-galaxy", EquipmentId = "eq-1", Name = "Source", FolderPath = (string?)null, DataType = "Int32", TagConfig = "{\"FullName\":\"TestMachine_020.Source\"}", }, }, }); var c = DeploymentArtifact.ParseComposition(blob); c.EquipmentTags.ShouldBeEmpty(); } }