Files
lmxopcua/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DraftSnapshotFactoryTests.cs
T

100 lines
3.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
using ZB.MOM.WW.OtOpcUa.Configuration.Validation;
namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;
/// <summary>
/// Verifies <see cref="DraftSnapshotFactory.FromConfigDbAsync"/> materialises a
/// <see cref="DraftSnapshot"/> from the live config DB whose Tag/VirtualTag rows feed the
/// equipment-signal collision rule — the one rule wired into the deploy gate (Task 3).
/// </summary>
[Trait("Category", "Unit")]
public sealed class DraftSnapshotFactoryTests : IDisposable
{
private readonly OtOpcUaConfigDbContext _db;
/// <summary>Initializes a new instance with an isolated in-memory config DB.</summary>
public DraftSnapshotFactoryTests()
{
var options = new DbContextOptionsBuilder<OtOpcUaConfigDbContext>()
.UseInMemoryDatabase($"draft-snapshot-{Guid.NewGuid():N}")
.Options;
_db = new OtOpcUaConfigDbContext(options);
}
/// <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>
[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"));
await _db.SaveChangesAsync();
var snapshot = await DraftSnapshotFactory.FromConfigDbAsync(_db);
snapshot.Tags.Count.ShouldBe(1);
snapshot.VirtualTags.Count.ShouldBe(1);
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>
[Fact]
public async Task FromConfigDb_no_collision_when_names_differ()
{
SeedEquipment("eq-1");
_db.Tags.Add(BuildTag(equipmentId: "eq-1", name: "speed"));
_db.VirtualTags.Add(BuildVirtualTag(equipmentId: "eq-1", name: "temperature"));
await _db.SaveChangesAsync();
var snapshot = await DraftSnapshotFactory.FromConfigDbAsync(_db);
snapshot.Tags.Count.ShouldBe(1);
snapshot.VirtualTags.Count.ShouldBe(1);
DraftValidator.Validate(snapshot).ShouldNotContain(e => e.Code == "EquipmentSignalNameCollision");
}
private void SeedEquipment(string equipmentId)
{
var uuid = Guid.NewGuid();
_db.Equipment.Add(new Equipment
{
EquipmentUuid = uuid,
EquipmentId = equipmentId,
Name = "eq",
DriverInstanceId = "d",
UnsLineId = "line-a",
MachineCode = "m",
});
}
private static Tag BuildTag(string equipmentId, string name) => new()
{
TagId = $"tag-{name}",
DriverInstanceId = "d",
EquipmentId = equipmentId,
Name = name,
DataType = "Float",
AccessLevel = TagAccessLevel.Read,
TagConfig = "{}",
};
private static VirtualTag BuildVirtualTag(string equipmentId, string name) => new()
{
VirtualTagId = $"vtag-{name}",
EquipmentId = equipmentId,
Name = name,
DataType = "Float",
ScriptId = "s-1",
};
}