v3 batch1 WP1: greenfield DbContext + V3Initial squash + seeds + tests
DbContext (OtOpcUaConfigDbContext): - Drop Namespace/EquipmentImportBatch/EquipmentImportRow DbSets + Configure methods. - Add RawFolder/TagGroup/UnsTagReference DbSets + Configure methods with sibling-name filtered unique indexes over nullable parents (two-filtered pattern per level). - Reshape DriverInstance (RawFolderId + UX_DriverInstance_Folder_Name/_ClusterRoot_Name), Tag (required DeviceId, nullable TagGroupId, UX_Tag_Group_Name/_Device_Name, IX_Tag_Device), Equipment (drop DriverInstanceId/DeviceId + IX_Equipment_Driver), Device (UX_Device_Driver_Name). Migration squash -> V3Initial: - Delete the whole Migrations/ folder; scaffold one V3Initial (applies clean to a fresh DB). - Port the hand-written procs + AuthorizationGrants into V3Initial.StoredProcedures.cs. The v1 generation-model procs (ConfigGeneration/GenerationId, dead since V2HostingAlignment) are rewritten as v3-schema-valid retirement stubs that preserve the two-role EXECUTE-grant surface + AuthorizationTests behaviors; sp_ComputeGenerationDiff now references the v3 tables; sp_ReleaseExternalIdReservation ported verbatim. Compile-fixes for the build gate (Wave-C-owned, minimal + TODO(v3 WP4) markers): - DraftSnapshot/DraftSnapshotFactory: drop the retired Namespaces list. - DraftValidator: delete namespace-binding + Galaxy-FullName rules; collision rule now VirtualTag-only. Seeds -> v3 schema: - seed-clusters.sql summary SELECTs; all 5 scripts/smoke/seed-*.sql rewritten (DriverInstance RawFolderId, Device+DeviceConfig endpoint, Tag DeviceId, UnsTagReference; no ConfigGeneration/ Namespace/sp_PublishGeneration). Verified: all seeds apply clean against a fresh V3Initial DB. Tests (Configuration.Tests, 107 pass): - SchemaComplianceTests rewritten to v3 tables + filtered indexes. - New RawSchemaIntegrityTests: DB-enforced sibling-name uniqueness per raw level + UnsTagReference (Equipment,Tag) uniqueness. - Delete DraftValidatorGalaxyFullNameCorpusTests (WP2/WP6 replaces); fix DraftValidatorTests + DraftSnapshotFactoryTests to v3 shapes; repoint scripting-migration existence test to V3Initial.
This commit is contained in:
@@ -29,30 +29,32 @@ public sealed class DraftSnapshotFactoryTests : IDisposable
|
||||
/// <summary>Disposes the database context.</summary>
|
||||
public void Dispose() => _db.Dispose();
|
||||
|
||||
/// <summary>Seeds one Equipment plus a Tag and a VirtualTag sharing (EquipmentId, Name); the
|
||||
/// snapshot must carry both signal collections AND the validator must flag the collision.</summary>
|
||||
/// <summary>Seeds an Equipment plus a raw Tag and a VirtualTag; the snapshot must carry both
|
||||
/// signal collections. v3: Tags are raw-only, so the equipment-signal collision rule now operates
|
||||
/// on VirtualTags — two VirtualTags sharing (EquipmentId, Name) must surface the collision.</summary>
|
||||
[Fact]
|
||||
public async Task FromConfigDb_populates_Tags_and_VirtualTags_and_surfaces_collision()
|
||||
{
|
||||
SeedEquipment("eq-1");
|
||||
_db.Tags.Add(BuildTag(equipmentId: "eq-1", name: "speed"));
|
||||
_db.VirtualTags.Add(BuildVirtualTag(equipmentId: "eq-1", name: "speed"));
|
||||
_db.Tags.Add(BuildTag(name: "speed"));
|
||||
_db.VirtualTags.Add(BuildVirtualTag(equipmentId: "eq-1", name: "speed", suffix: "a"));
|
||||
_db.VirtualTags.Add(BuildVirtualTag(equipmentId: "eq-1", name: "speed", suffix: "b"));
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
var snapshot = await DraftSnapshotFactory.FromConfigDbAsync(_db);
|
||||
|
||||
snapshot.Tags.Count.ShouldBe(1);
|
||||
snapshot.VirtualTags.Count.ShouldBe(1);
|
||||
snapshot.VirtualTags.Count.ShouldBe(2);
|
||||
DraftValidator.Validate(snapshot).ShouldContain(e => e.Code == "EquipmentSignalNameCollision");
|
||||
}
|
||||
|
||||
/// <summary>A Tag and a VirtualTag with distinct names under the same equipment do not collide,
|
||||
/// so the snapshot validates clean of the collision code.</summary>
|
||||
/// <summary>Distinct VirtualTag names under the same equipment do not collide, so the snapshot
|
||||
/// validates clean of the collision code.</summary>
|
||||
[Fact]
|
||||
public async Task FromConfigDb_no_collision_when_names_differ()
|
||||
{
|
||||
SeedEquipment("eq-1");
|
||||
_db.Tags.Add(BuildTag(equipmentId: "eq-1", name: "speed"));
|
||||
_db.Tags.Add(BuildTag(name: "speed"));
|
||||
_db.VirtualTags.Add(BuildVirtualTag(equipmentId: "eq-1", name: "temperature"));
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
@@ -109,26 +111,25 @@ public sealed class DraftSnapshotFactoryTests : IDisposable
|
||||
EquipmentUuid = uuid,
|
||||
EquipmentId = equipmentId,
|
||||
Name = "eq",
|
||||
DriverInstanceId = "d",
|
||||
UnsLineId = "line-a",
|
||||
MachineCode = "m",
|
||||
});
|
||||
}
|
||||
|
||||
private static Tag BuildTag(string equipmentId, string name) => new()
|
||||
// v3: Tags are raw-only (DeviceId FK, no EquipmentId/DriverInstanceId).
|
||||
private static Tag BuildTag(string name) => new()
|
||||
{
|
||||
TagId = $"tag-{name}",
|
||||
DriverInstanceId = "d",
|
||||
EquipmentId = equipmentId,
|
||||
DeviceId = "dev-1",
|
||||
Name = name,
|
||||
DataType = "Float",
|
||||
AccessLevel = TagAccessLevel.Read,
|
||||
TagConfig = "{}",
|
||||
};
|
||||
|
||||
private static VirtualTag BuildVirtualTag(string equipmentId, string name) => new()
|
||||
private static VirtualTag BuildVirtualTag(string equipmentId, string name, string suffix = "") => new()
|
||||
{
|
||||
VirtualTagId = $"vtag-{name}",
|
||||
VirtualTagId = $"vtag-{name}{suffix}",
|
||||
EquipmentId = equipmentId,
|
||||
Name = name,
|
||||
DataType = "Float",
|
||||
|
||||
Reference in New Issue
Block a user