Add ExtendedAttributes config toggle for system+user attributes
When GalaxyRepository.ExtendedAttributes is true, uses the extended attributes query that includes both primitive (system) and dynamic (user-defined) attributes. Default is false (dynamic only, preserving existing behavior). Extended mode returns ~564 attributes vs ~48. Adds PrimitiveName and AttributeSource fields to GalaxyAttributeInfo. Includes 5 new unit tests and 6 new integration tests covering both standard and extended attribute modes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Configuration;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.GalaxyRepository;
|
||||
|
||||
namespace ZB.MOM.WW.LmxOpcUa.IntegrationTests
|
||||
{
|
||||
public class GalaxyRepositoryServiceTests
|
||||
{
|
||||
private static GalaxyRepositoryConfiguration LoadConfig(bool extendedAttributes = false)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.test.json", optional: false)
|
||||
.Build();
|
||||
|
||||
var config = new GalaxyRepositoryConfiguration();
|
||||
configuration.GetSection("GalaxyRepository").Bind(config);
|
||||
config.ExtendedAttributes = extendedAttributes;
|
||||
return config;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_StandardMode_ReturnsRows()
|
||||
{
|
||||
var config = LoadConfig(extendedAttributes: false);
|
||||
var service = new GalaxyRepositoryService(config);
|
||||
|
||||
var results = await service.GetAttributesAsync();
|
||||
|
||||
results.ShouldNotBeEmpty();
|
||||
// Standard mode: PrimitiveName and AttributeSource should be empty
|
||||
results.ShouldAllBe(r => r.PrimitiveName == "" && r.AttributeSource == "");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_ExtendedMode_ReturnsMoreRows()
|
||||
{
|
||||
var standardConfig = LoadConfig(extendedAttributes: false);
|
||||
var extendedConfig = LoadConfig(extendedAttributes: true);
|
||||
var standardService = new GalaxyRepositoryService(standardConfig);
|
||||
var extendedService = new GalaxyRepositoryService(extendedConfig);
|
||||
|
||||
var standardResults = await standardService.GetAttributesAsync();
|
||||
var extendedResults = await extendedService.GetAttributesAsync();
|
||||
|
||||
extendedResults.Count.ShouldBeGreaterThan(standardResults.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_ExtendedMode_IncludesPrimitiveAttributes()
|
||||
{
|
||||
var config = LoadConfig(extendedAttributes: true);
|
||||
var service = new GalaxyRepositoryService(config);
|
||||
|
||||
var results = await service.GetAttributesAsync();
|
||||
|
||||
results.ShouldContain(r => r.AttributeSource == "primitive");
|
||||
results.ShouldContain(r => r.AttributeSource == "dynamic");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_ExtendedMode_PrimitiveNamePopulated()
|
||||
{
|
||||
var config = LoadConfig(extendedAttributes: true);
|
||||
var service = new GalaxyRepositoryService(config);
|
||||
|
||||
var results = await service.GetAttributesAsync();
|
||||
|
||||
// Some primitive attributes have non-empty primitive names
|
||||
// (though many have empty primitive_name for the root UDO)
|
||||
results.ShouldNotBeEmpty();
|
||||
// All should have an attribute source
|
||||
results.ShouldAllBe(r => r.AttributeSource == "primitive" || r.AttributeSource == "dynamic");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_StandardMode_AllHaveFullTagReference()
|
||||
{
|
||||
var config = LoadConfig(extendedAttributes: false);
|
||||
var service = new GalaxyRepositoryService(config);
|
||||
|
||||
var results = await service.GetAttributesAsync();
|
||||
|
||||
results.ShouldAllBe(r => !string.IsNullOrEmpty(r.FullTagReference));
|
||||
results.ShouldAllBe(r => r.FullTagReference.Contains("."));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAttributesAsync_ExtendedMode_AllHaveFullTagReference()
|
||||
{
|
||||
var config = LoadConfig(extendedAttributes: true);
|
||||
var service = new GalaxyRepositoryService(config);
|
||||
|
||||
var results = await service.GetAttributesAsync();
|
||||
|
||||
results.ShouldAllBe(r => !string.IsNullOrEmpty(r.FullTagReference));
|
||||
results.ShouldAllBe(r => r.FullTagReference.Contains("."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,27 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Configuration
|
||||
config.GalaxyRepository.ConnectionString.ShouldContain("ZB");
|
||||
config.GalaxyRepository.ChangeDetectionIntervalSeconds.ShouldBe(30);
|
||||
config.GalaxyRepository.CommandTimeoutSeconds.ShouldBe(30);
|
||||
config.GalaxyRepository.ExtendedAttributes.ShouldBe(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GalaxyRepository_ExtendedAttributes_DefaultsFalse()
|
||||
{
|
||||
var config = new GalaxyRepositoryConfiguration();
|
||||
config.ExtendedAttributes.ShouldBe(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GalaxyRepository_ExtendedAttributes_BindsFromJson()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddJsonFile("appsettings.json", optional: false)
|
||||
.AddInMemoryCollection(new[] { new System.Collections.Generic.KeyValuePair<string, string>("GalaxyRepository:ExtendedAttributes", "true") })
|
||||
.Build();
|
||||
|
||||
var config = new GalaxyRepositoryConfiguration();
|
||||
configuration.GetSection("GalaxyRepository").Bind(config);
|
||||
config.ExtendedAttributes.ShouldBe(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Tests.Domain
|
||||
{
|
||||
public class GalaxyAttributeInfoTests
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultValues_AreEmpty()
|
||||
{
|
||||
var info = new GalaxyAttributeInfo();
|
||||
info.PrimitiveName.ShouldBe("");
|
||||
info.AttributeSource.ShouldBe("");
|
||||
info.TagName.ShouldBe("");
|
||||
info.AttributeName.ShouldBe("");
|
||||
info.FullTagReference.ShouldBe("");
|
||||
info.DataTypeName.ShouldBe("");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtendedFields_CanBeSet()
|
||||
{
|
||||
var info = new GalaxyAttributeInfo
|
||||
{
|
||||
PrimitiveName = "UDO",
|
||||
AttributeSource = "primitive"
|
||||
};
|
||||
info.PrimitiveName.ShouldBe("UDO");
|
||||
info.AttributeSource.ShouldBe("primitive");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StandardAttributes_HaveEmptyExtendedFields()
|
||||
{
|
||||
var info = new GalaxyAttributeInfo
|
||||
{
|
||||
GobjectId = 1,
|
||||
TagName = "TestObj",
|
||||
AttributeName = "MachineID",
|
||||
FullTagReference = "TestObj.MachineID",
|
||||
MxDataType = 5
|
||||
};
|
||||
info.PrimitiveName.ShouldBe("");
|
||||
info.AttributeSource.ShouldBe("");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user