feat(adminui): alias DTO + Galaxy gateway lookup + Source/IsAlias on tag rows
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Uns;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns;
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the read-side surface for Galaxy alias tags: that
|
||||
/// <see cref="UnsTreeService.LoadGalaxyGatewaysForEquipmentAsync"/> finds the
|
||||
/// <c>GalaxyMxGateway</c> drivers in the equipment's cluster (and only those), and that
|
||||
/// <see cref="UnsTreeService.LoadTagsForEquipmentAsync"/> flags alias tags (those bound to a Galaxy
|
||||
/// gateway) with <c>IsAlias = true</c> and a <c>Source</c> derived from the tag's <c>TagConfig</c>.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class UnsTreeServiceAliasTagTests
|
||||
{
|
||||
private const string ClusterId = "MAIN";
|
||||
private const string EquipmentId = "EQ-ALIAS-1";
|
||||
private const string GatewayDriverId = "DRV-GALAXY";
|
||||
private const string ModbusDriverId = "DRV-MODBUS";
|
||||
|
||||
/// <summary>
|
||||
/// Seeds a cluster with: a SystemPlatform namespace + GalaxyMxGateway driver, an Equipment-kind
|
||||
/// namespace + Modbus driver, and an area→line→equipment path. Returns the InMemory db name.
|
||||
/// </summary>
|
||||
private static string SeedCluster(bool withGalaxyGateway = true)
|
||||
{
|
||||
var dbName = $"uns-alias-{Guid.NewGuid():N}";
|
||||
|
||||
using var db = UnsTreeTestDb.CreateNamed(dbName);
|
||||
|
||||
db.ServerClusters.Add(new ServerCluster
|
||||
{
|
||||
ClusterId = ClusterId,
|
||||
Name = "Main",
|
||||
Enterprise = "zb",
|
||||
Site = "warsaw-west",
|
||||
RedundancyMode = RedundancyMode.None,
|
||||
CreatedBy = "test",
|
||||
});
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "AREA-1", ClusterId = ClusterId, Name = "a" });
|
||||
db.UnsLines.Add(new UnsLine { UnsLineId = "LINE-1", UnsAreaId = "AREA-1", Name = "l" });
|
||||
db.Equipment.Add(new Equipment
|
||||
{
|
||||
EquipmentId = EquipmentId,
|
||||
EquipmentUuid = Guid.NewGuid(),
|
||||
UnsLineId = "LINE-1",
|
||||
Name = "machine-1",
|
||||
MachineCode = "machine_001",
|
||||
});
|
||||
|
||||
// SystemPlatform namespace hosting the Galaxy gateway.
|
||||
db.Namespaces.Add(new Namespace
|
||||
{
|
||||
NamespaceId = "NS-SP",
|
||||
ClusterId = ClusterId,
|
||||
Kind = NamespaceKind.SystemPlatform,
|
||||
NamespaceUri = "urn:zb:sp",
|
||||
});
|
||||
if (withGalaxyGateway)
|
||||
{
|
||||
db.DriverInstances.Add(new DriverInstance
|
||||
{
|
||||
DriverInstanceId = GatewayDriverId,
|
||||
ClusterId = ClusterId,
|
||||
NamespaceId = "NS-SP",
|
||||
Name = "galaxy gateway",
|
||||
DriverType = "GalaxyMxGateway",
|
||||
DriverConfig = "{\"Galaxy\":{}}",
|
||||
});
|
||||
}
|
||||
|
||||
// Equipment-kind namespace hosting an ordinary (non-Galaxy) driver.
|
||||
db.Namespaces.Add(new Namespace
|
||||
{
|
||||
NamespaceId = "NS-EQ",
|
||||
ClusterId = ClusterId,
|
||||
Kind = NamespaceKind.Equipment,
|
||||
NamespaceUri = "urn:zb:eq",
|
||||
});
|
||||
db.DriverInstances.Add(new DriverInstance
|
||||
{
|
||||
DriverInstanceId = ModbusDriverId,
|
||||
ClusterId = ClusterId,
|
||||
NamespaceId = "NS-EQ",
|
||||
Name = "modbus driver",
|
||||
DriverType = "Modbus",
|
||||
DriverConfig = "{}",
|
||||
});
|
||||
|
||||
db.SaveChanges();
|
||||
return dbName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The gateway lookup returns exactly the GalaxyMxGateway driver (with its id, a display string,
|
||||
/// and its DriverConfig) and never the cluster's Modbus driver.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task LoadGalaxyGatewaysForEquipment_returns_only_galaxy_gateway()
|
||||
{
|
||||
var dbName = SeedCluster();
|
||||
var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName));
|
||||
|
||||
var gateways = await service.LoadGalaxyGatewaysForEquipmentAsync(EquipmentId);
|
||||
|
||||
gateways.Count.ShouldBe(1);
|
||||
gateways[0].DriverInstanceId.ShouldBe(GatewayDriverId);
|
||||
gateways[0].Display.ShouldContain(GatewayDriverId);
|
||||
gateways[0].Display.ShouldContain("galaxy gateway");
|
||||
gateways[0].DriverConfig.ShouldBe("{\"Galaxy\":{}}");
|
||||
gateways.ShouldNotContain(g => g.DriverInstanceId == ModbusDriverId);
|
||||
}
|
||||
|
||||
/// <summary>An equipment whose cluster has no GalaxyMxGateway driver yields an empty list.</summary>
|
||||
[Fact]
|
||||
public async Task LoadGalaxyGatewaysForEquipment_returns_empty_when_no_gateway()
|
||||
{
|
||||
var dbName = SeedCluster(withGalaxyGateway: false);
|
||||
var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName));
|
||||
|
||||
var gateways = await service.LoadGalaxyGatewaysForEquipmentAsync(EquipmentId);
|
||||
|
||||
gateways.ShouldBeEmpty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A tag bound to the Galaxy gateway is an alias (<c>IsAlias = true</c>, <c>Source</c> derived from
|
||||
/// its TagConfig FullName); a tag bound to the Modbus driver is not (<c>IsAlias = false</c>,
|
||||
/// <c>Source = null</c>).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task LoadTagsForEquipment_flags_galaxy_alias_rows()
|
||||
{
|
||||
var dbName = SeedCluster();
|
||||
|
||||
using (var db = UnsTreeTestDb.CreateNamed(dbName))
|
||||
{
|
||||
db.Tags.Add(new Tag
|
||||
{
|
||||
TagId = "TAG-ALIAS",
|
||||
DriverInstanceId = GatewayDriverId,
|
||||
EquipmentId = EquipmentId,
|
||||
Name = "aliased-speed",
|
||||
DataType = "Float",
|
||||
AccessLevel = TagAccessLevel.Read,
|
||||
TagConfig = "{\"FullName\":\"TestMachine_020.Speed\"}",
|
||||
});
|
||||
db.Tags.Add(new Tag
|
||||
{
|
||||
TagId = "TAG-NORMAL",
|
||||
DriverInstanceId = ModbusDriverId,
|
||||
EquipmentId = EquipmentId,
|
||||
Name = "raw-speed",
|
||||
DataType = "Int32",
|
||||
AccessLevel = TagAccessLevel.Read,
|
||||
TagConfig = "{}",
|
||||
});
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName));
|
||||
|
||||
var rows = await service.LoadTagsForEquipmentAsync(EquipmentId);
|
||||
|
||||
var alias = rows.ShouldHaveSingleItem(r => r.TagId == "TAG-ALIAS");
|
||||
alias.IsAlias.ShouldBeTrue();
|
||||
alias.Source.ShouldBe("galaxy:TestMachine_020.Speed");
|
||||
|
||||
var normal = rows.ShouldHaveSingleItem(r => r.TagId == "TAG-NORMAL");
|
||||
normal.IsAlias.ShouldBeFalse();
|
||||
normal.Source.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Small Shouldly-style helper for "exactly one match" assertions used by these tests.</summary>
|
||||
internal static class SingleItemAssertions
|
||||
{
|
||||
public static T ShouldHaveSingleItem<T>(this IEnumerable<T> source, Func<T, bool> predicate)
|
||||
{
|
||||
var matches = source.Where(predicate).ToList();
|
||||
matches.Count.ShouldBe(1);
|
||||
return matches[0];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user