105 lines
3.2 KiB
C#
105 lines
3.2 KiB
C#
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Authorization;
|
|
using ZB.MOM.WW.OtOpcUa.Server.Security;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Server.Tests;
|
|
|
|
[Trait("Category", "Unit")]
|
|
public sealed class NodeScopeResolverTests
|
|
{
|
|
[Fact]
|
|
public void Resolve_PopulatesClusterAndTag()
|
|
{
|
|
var resolver = new NodeScopeResolver("c-warsaw");
|
|
|
|
var scope = resolver.Resolve("TestMachine_001/Oven/SetPoint");
|
|
|
|
scope.ClusterId.ShouldBe("c-warsaw");
|
|
scope.TagId.ShouldBe("TestMachine_001/Oven/SetPoint");
|
|
scope.Kind.ShouldBe(NodeHierarchyKind.Equipment);
|
|
}
|
|
|
|
[Fact]
|
|
public void Resolve_Leaves_UnsPath_Null_When_NoIndexSupplied()
|
|
{
|
|
var resolver = new NodeScopeResolver("c-1");
|
|
|
|
var scope = resolver.Resolve("tag-1");
|
|
|
|
// Cluster-only fallback path — used pre-ADR-001 and still the active path for
|
|
// unindexed references (e.g. driver-discovered tags that have no Tag row yet).
|
|
scope.NamespaceId.ShouldBeNull();
|
|
scope.UnsAreaId.ShouldBeNull();
|
|
scope.UnsLineId.ShouldBeNull();
|
|
scope.EquipmentId.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Resolve_Returns_IndexedScope_When_FullReferenceFound()
|
|
{
|
|
var index = new Dictionary<string, NodeScope>
|
|
{
|
|
["plcaddr-01"] = new NodeScope
|
|
{
|
|
ClusterId = "c-1", NamespaceId = "ns-plc", UnsAreaId = "area-1",
|
|
UnsLineId = "line-a", EquipmentId = "eq-oven-3", TagId = "plcaddr-01",
|
|
Kind = NodeHierarchyKind.Equipment,
|
|
},
|
|
};
|
|
var resolver = new NodeScopeResolver("c-1", index);
|
|
|
|
var scope = resolver.Resolve("plcaddr-01");
|
|
|
|
scope.UnsAreaId.ShouldBe("area-1");
|
|
scope.UnsLineId.ShouldBe("line-a");
|
|
scope.EquipmentId.ShouldBe("eq-oven-3");
|
|
scope.TagId.ShouldBe("plcaddr-01");
|
|
scope.NamespaceId.ShouldBe("ns-plc");
|
|
}
|
|
|
|
[Fact]
|
|
public void Resolve_FallsBack_To_ClusterOnly_When_Reference_NotIndexed()
|
|
{
|
|
var index = new Dictionary<string, NodeScope>
|
|
{
|
|
["plcaddr-01"] = new NodeScope { ClusterId = "c-1", TagId = "plcaddr-01", Kind = NodeHierarchyKind.Equipment },
|
|
};
|
|
var resolver = new NodeScopeResolver("c-1", index);
|
|
|
|
var scope = resolver.Resolve("not-in-index");
|
|
|
|
scope.ClusterId.ShouldBe("c-1");
|
|
scope.TagId.ShouldBe("not-in-index");
|
|
scope.EquipmentId.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Resolve_Throws_OnEmptyFullReference()
|
|
{
|
|
var resolver = new NodeScopeResolver("c-1");
|
|
|
|
Should.Throw<ArgumentException>(() => resolver.Resolve(""));
|
|
Should.Throw<ArgumentException>(() => resolver.Resolve(" "));
|
|
}
|
|
|
|
[Fact]
|
|
public void Ctor_Throws_OnEmptyClusterId()
|
|
{
|
|
Should.Throw<ArgumentException>(() => new NodeScopeResolver(""));
|
|
}
|
|
|
|
[Fact]
|
|
public void Resolver_IsStateless_AcrossCalls()
|
|
{
|
|
var resolver = new NodeScopeResolver("c");
|
|
var s1 = resolver.Resolve("tag-a");
|
|
var s2 = resolver.Resolve("tag-b");
|
|
|
|
s1.TagId.ShouldBe("tag-a");
|
|
s2.TagId.ShouldBe("tag-b");
|
|
s1.ClusterId.ShouldBe("c");
|
|
s2.ClusterId.ShouldBe("c");
|
|
}
|
|
}
|