using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy; using ZB.MOM.WW.MxGateway.Server.Galaxy; using ZB.MOM.WW.MxGateway.Server.Sessions; namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Sessions; public sealed class ArrayAddressNormalizerTests { /// Verifies a bare array attribute name gains the trailing array suffix. [Fact] public void Normalize_BareArrayName_AppendsArraySuffix() { ArrayAddressNormalizer normalizer = CreateNormalizer(); Assert.Equal("Obj.Arr[]", normalizer.Normalize("Obj.Arr")); } /// Verifies an already-suffixed address is returned unchanged. [Fact] public void Normalize_AlreadySuffixed_ReturnsUnchanged() { ArrayAddressNormalizer normalizer = CreateNormalizer(); Assert.Equal("Obj.Arr[]", normalizer.Normalize("Obj.Arr[]")); } /// Verifies a scalar attribute is returned unchanged. [Fact] public void Normalize_ScalarAttribute_ReturnsUnchanged() { ArrayAddressNormalizer normalizer = CreateNormalizer(); Assert.Equal("Obj.Scalar", normalizer.Normalize("Obj.Scalar")); } /// Verifies an address absent from the cache is returned unchanged. [Fact] public void Normalize_UnknownAddress_ReturnsUnchanged() { ArrayAddressNormalizer normalizer = CreateNormalizer(); Assert.Equal("Obj.Unknown", normalizer.Normalize("Obj.Unknown")); } /// Verifies null, empty, and whitespace addresses are returned unchanged. [Theory] [InlineData("")] [InlineData(" ")] public void Normalize_BlankAddress_ReturnsUnchanged(string address) { ArrayAddressNormalizer normalizer = CreateNormalizer(); Assert.Equal(address, normalizer.Normalize(address)); } private static ArrayAddressNormalizer CreateNormalizer() { IReadOnlyList objects = [ new GalaxyObject { GobjectId = 1, TagName = "Obj", ContainedName = "Obj", Attributes = { new GalaxyAttribute { AttributeName = "Arr", // Galaxy SQL already appends "[]" to array attribute references. FullTagReference = "Obj.Arr[]", IsArray = true, }, new GalaxyAttribute { AttributeName = "Scalar", FullTagReference = "Obj.Scalar", IsArray = false, }, }, }, ]; GalaxyHierarchyCacheEntry entry = GalaxyHierarchyCacheEntry.Empty with { Status = GalaxyCacheStatus.Healthy, Objects = objects, Index = GalaxyHierarchyIndex.Build(objects), }; return new ArrayAddressNormalizer(new StubGalaxyHierarchyCache(entry)); } private sealed class StubGalaxyHierarchyCache(GalaxyHierarchyCacheEntry current) : IGalaxyHierarchyCache { /// Gets the current cache entry. public GalaxyHierarchyCacheEntry Current { get; } = current; /// public Task RefreshAsync(CancellationToken cancellationToken) => Task.CompletedTask; /// public Task WaitForFirstLoadAsync(CancellationToken cancellationToken) => Task.CompletedTask; } }