329144b1aa
Fix TESTS only (production already green) so the four in-scope test projects compile + pass under the v3 dark address space: - Core.Abstractions.Tests: drop AllowedNamespaceKinds/NamespaceKindCompatibility from DriverTypeMetadata; rewrite EquipmentTagRefResolver tests to the single-func RawPath-lookup contract (no parseRef/transient cache). - Core.Tests: rewrite EquipmentNodeWalkerTests to EquipmentNamespaceContent(Areas, Lines,Equipment,VirtualTags?,ScriptedAlarms?) — folders + VirtualTags + ScriptedAlarms only; raw-tag variables dark (skipped Batch-4 placeholder). Drop retired Equipment.DriverInstanceId. - Runtime.Tests: rewrite golden corpus + TagConfigCorpusParityTests to the v3 RawPath/RawTagEntry round-trip (byte + TagConfigIntent parity; EquipmentTags dark). Salvage VirtualTag + ScriptedAlarm artifact parity to the new Compose signature. Retire the equipment-tag-materialization parity files (Array/Historize/Alias) and the equipment-device-binding DeviceHost parity to documented skipped placeholders. Skip 34 dark equipment-tag routing/value/alarm/write/discovery actor tests with a shared DarkAddressSpaceReasons constant. Re-key cluster-scoped tests to v3 UNS line->area attribution. - ControlPlane.Tests: ConfigComposer round-trips re-keyed to RawFolder/Device (no Namespaces); tag-config gate resolves driver via Device; deploy-gate collision test re-keyed to UnsEffectiveNameCollision; drop retired BadCrossClusterNamespaceBinding case.
75 lines
2.9 KiB
C#
75 lines
2.9 KiB
C#
using System.Text.Json;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;
|
|
|
|
/// <summary>
|
|
/// Verifies the artifact-decode mirror substitutes the reserved <c>{{equip}}</c> token in a
|
|
/// VirtualTag script's <c>ctx.GetTag("…")</c> literals with the owning equipment's tag base
|
|
/// (derived from its child Equipment-namespace tag's FullName) — byte-parity with
|
|
/// <c>AddressSpaceComposer.Compose</c>'s live-edit path, using the same shared
|
|
/// <c>EquipmentScriptPaths</c> helper and the same equipmentTags-derived base.
|
|
/// </summary>
|
|
public sealed class DeploymentArtifactEquipTokenTests
|
|
{
|
|
// v3 dark: the {{equip}} tag base is DERIVED from the owning equipment's child equipment-tag FullNames,
|
|
// and equipment-tag plans do not materialize until Batch 4 — so baseByEquip is empty and {{equip}} has
|
|
// no per-equipment base to substitute. Unskip when Batch 4 lights the equipment-tag plans.
|
|
[Fact(Skip = DarkAddressSpaceReasons.EquipmentTagsDarkBatch4)]
|
|
public void ParseComposition_substitutes_equip_token_in_virtual_tag_expression()
|
|
{
|
|
var blob = JsonSerializer.SerializeToUtf8Bytes(new
|
|
{
|
|
Namespaces = new[]
|
|
{
|
|
new { NamespaceId = "ns-eq", Kind = 0 }, // NamespaceKind.Equipment
|
|
},
|
|
DriverInstances = new[]
|
|
{
|
|
new { DriverInstanceId = "drv-modbus", DriverType = "Modbus", DriverConfig = "{}", NamespaceId = "ns-eq" },
|
|
},
|
|
Tags = new object[]
|
|
{
|
|
new
|
|
{
|
|
TagId = "tag-source",
|
|
DriverInstanceId = "drv-modbus",
|
|
EquipmentId = "TestMachine_001",
|
|
Name = "Source",
|
|
FolderPath = (string?)null,
|
|
DataType = "Float",
|
|
TagConfig = "{\"FullName\":\"TestMachine_001.Source\"}",
|
|
},
|
|
},
|
|
Scripts = new[]
|
|
{
|
|
new
|
|
{
|
|
ScriptId = "s-equip",
|
|
SourceCode = "return System.Convert.ToInt32(ctx.GetTag(\"{{equip}}.Source\").Value) > 50;",
|
|
},
|
|
},
|
|
VirtualTags = new[]
|
|
{
|
|
new
|
|
{
|
|
VirtualTagId = "vt-equip",
|
|
EquipmentId = "TestMachine_001",
|
|
Name = "OverThreshold",
|
|
DataType = "Boolean",
|
|
ScriptId = "s-equip",
|
|
},
|
|
},
|
|
});
|
|
|
|
var c = DeploymentArtifact.ParseComposition(blob);
|
|
|
|
var vt = c.EquipmentVirtualTags.ShouldHaveSingleItem();
|
|
vt.Expression.ShouldContain("ctx.GetTag(\"TestMachine_001.Source\")");
|
|
vt.Expression.ShouldNotContain("{{equip}}");
|
|
vt.DependencyRefs.ShouldBe(new[] { "TestMachine_001.Source" });
|
|
}
|
|
}
|