feat(validation): allow GalaxyMxGateway under Equipment; rename Galaxy-tag FullName check

This commit is contained in:
Joseph Doherty
2026-06-12 21:11:06 -04:00
parent 1c4052ee83
commit 499c9b9165
2 changed files with 23 additions and 74 deletions
@@ -123,24 +123,11 @@ public sealed class DraftValidatorTests
}
/// <summary>Verifies that the canonical Galaxy driver type (GalaxyMxGateway, per PR 7.2 —
/// it was "Galaxy" pre-PR-7.2) is allowed in a SystemPlatform namespace, i.e. produces no
/// kind-mismatch error.</summary>
/// it was "Galaxy" pre-PR-7.2) is now a standard Equipment-kind driver: binding it to an
/// Equipment namespace produces no kind-mismatch error (the SystemPlatform namespace split
/// is being retired — Galaxy under Equipment is valid).</summary>
[Fact]
public void GalaxyMxGateway_driver_in_SystemPlatform_namespace_is_allowed()
{
var draft = new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
Namespaces = [new Namespace { NamespaceId = "ns-1", ClusterId = "c", NamespaceUri = "urn:x", Kind = NamespaceKind.SystemPlatform }],
DriverInstances = [new DriverInstance { DriverInstanceId = "d-1", ClusterId = "c", NamespaceId = "ns-1", Name = "drv", DriverType = "GalaxyMxGateway", DriverConfig = "{}" }],
};
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "DriverNamespaceKindMismatch");
}
/// <summary>Verifies that the canonical Galaxy driver type cannot be placed in an Equipment namespace.</summary>
[Fact]
public void GalaxyMxGateway_driver_in_Equipment_namespace_is_rejected()
public void GalaxyMxGateway_driver_in_Equipment_namespace_is_allowed()
{
var draft = new DraftSnapshot
{
@@ -149,21 +136,7 @@ public sealed class DraftValidatorTests
DriverInstances = [new DriverInstance { DriverInstanceId = "d-1", ClusterId = "c", NamespaceId = "ns-1", Name = "drv", DriverType = "GalaxyMxGateway", DriverConfig = "{}" }],
};
DraftValidator.Validate(draft).ShouldContain(e => e.Code == "DriverNamespaceKindMismatch");
}
/// <summary>Verifies that a non-Galaxy driver cannot be placed in a SystemPlatform namespace.</summary>
[Fact]
public void NonGalaxy_driver_in_SystemPlatform_namespace_is_rejected()
{
var draft = new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
Namespaces = [new Namespace { NamespaceId = "ns-1", ClusterId = "c", NamespaceUri = "urn:x", Kind = NamespaceKind.SystemPlatform }],
DriverInstances = [new DriverInstance { DriverInstanceId = "d-1", ClusterId = "c", NamespaceId = "ns-1", Name = "drv", DriverType = "ModbusTcp", DriverConfig = "{}" }],
};
DraftValidator.Validate(draft).ShouldContain(e => e.Code == "DriverNamespaceKindMismatch");
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "DriverNamespaceKindMismatch");
}
/// <summary>Verifies that all validation errors are reported simultaneously.</summary>
@@ -181,7 +154,6 @@ public sealed class DraftValidatorTests
var errors = DraftValidator.Validate(draft);
errors.ShouldContain(e => e.Code == "BadCrossClusterNamespaceBinding");
errors.ShouldContain(e => e.Code == "DriverNamespaceKindMismatch");
errors.ShouldContain(e => e.Code == "EquipmentIdNotDerived");
errors.ShouldContain(e => e.Code == "UnsSegmentInvalid");
}
@@ -432,54 +404,54 @@ public sealed class DraftValidatorTests
};
// ------------------------------------------------------------------------------------
// ValidateAliasTagFullName — Galaxy alias tags must carry TagConfig.FullName
// ValidateGalaxyTagFullName — Galaxy equipment tags must carry TagConfig.FullName
// ------------------------------------------------------------------------------------
/// <summary>Verifies that an equipment-scoped Tag bound to a GalaxyMxGateway driver whose
/// TagConfig has no FullName (an alias with no Galaxy reference) is rejected — it would
/// TagConfig has no FullName (a Galaxy tag with no Galaxy reference) is rejected — it would
/// subscribe to nothing.</summary>
[Fact]
public void AliasTag_missing_FullName_is_rejected()
public void GalaxyTag_missing_FullName_is_rejected()
{
var draft = new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
DriverInstances = [new DriverInstance { DriverInstanceId = "d-galaxy", ClusterId = "c", NamespaceId = "ns-1", Name = "Galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}" }],
Tags = [BuildTag(equipmentId: "eq-1", name: "alias", folderPath: null, driverInstanceId: "d-galaxy", tagConfig: "{}")],
Tags = [BuildTag(equipmentId: "eq-1", name: "galaxytag", folderPath: null, driverInstanceId: "d-galaxy", tagConfig: "{}")],
};
DraftValidator.Validate(draft).ShouldContain(e => e.Code == "AliasTagMissingReference" && e.Context == "tag-alias");
DraftValidator.Validate(draft).ShouldContain(e => e.Code == "GalaxyTagMissingReference" && e.Context == "tag-galaxytag");
}
/// <summary>Verifies that an equipment-scoped Galaxy alias tag carrying a TagConfig.FullName
/// <summary>Verifies that an equipment-scoped Galaxy tag carrying a TagConfig.FullName
/// reference is accepted.</summary>
[Fact]
public void AliasTag_with_FullName_is_accepted()
public void GalaxyTag_with_FullName_is_accepted()
{
var draft = new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
DriverInstances = [new DriverInstance { DriverInstanceId = "d-galaxy", ClusterId = "c", NamespaceId = "ns-1", Name = "Galaxy", DriverType = "GalaxyMxGateway", DriverConfig = "{}" }],
Tags = [BuildTag(equipmentId: "eq-1", name: "alias", folderPath: null, driverInstanceId: "d-galaxy", tagConfig: "{\"FullName\":\"X.Y\"}")],
Tags = [BuildTag(equipmentId: "eq-1", name: "galaxytag", folderPath: null, driverInstanceId: "d-galaxy", tagConfig: "{\"FullName\":\"X.Y\"}")],
};
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "AliasTagMissingReference");
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "GalaxyTagMissingReference");
}
/// <summary>Verifies that an equipment-scoped Tag bound to a NON-Galaxy driver with an empty
/// TagConfig is NOT flagged as an alias missing its reference — only GalaxyMxGateway-bound
/// equipment tags are aliases.</summary>
/// TagConfig is NOT flagged as a Galaxy tag missing its reference — only GalaxyMxGateway-bound
/// equipment tags carry the Galaxy FullName requirement.</summary>
[Fact]
public void AliasTag_check_skips_nonGalaxy_equipment_tag()
public void GalaxyTag_check_skips_nonGalaxy_equipment_tag()
{
var draft = new DraftSnapshot
{
GenerationId = 1, ClusterId = "c",
DriverInstances = [new DriverInstance { DriverInstanceId = "d-modbus", ClusterId = "c", NamespaceId = "ns-1", Name = "Modbus", DriverType = "Modbus", DriverConfig = "{}" }],
Tags = [BuildTag(equipmentId: "eq-1", name: "alias", folderPath: null, driverInstanceId: "d-modbus", tagConfig: "{}")],
Tags = [BuildTag(equipmentId: "eq-1", name: "galaxytag", folderPath: null, driverInstanceId: "d-modbus", tagConfig: "{}")],
};
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "AliasTagMissingReference");
DraftValidator.Validate(draft).ShouldNotContain(e => e.Code == "GalaxyTagMissingReference");
}
// ------------------------------------------------------------------------------------