using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Configuration.Entities; using ZB.MOM.WW.OtOpcUa.Configuration.Validation; namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests; /// /// Gitea #628 (decision b): an MTConnect driver instance binds every tag through one agent client, so a /// second /raw Device under it is a deploy error — while the normal single-Device layout stays valid. /// [Trait("Category", "Unit")] public sealed class DraftValidatorMTConnectDeviceTests { private const string Code = DraftValidator.MTConnectMultipleDevicesCode; private static DriverInstance Driver(string id, string type) => new() { DriverInstanceId = id, ClusterId = "c", Name = id, DriverType = type, DriverConfig = "{}", }; private static Device Dev(string id, string driverId) => new() { DeviceId = id, DriverInstanceId = driverId, Name = id, DeviceConfig = "{}", }; private static DraftSnapshot Draft(DriverInstance[] drivers, params Device[] devices) => new() { GenerationId = 1, ClusterId = "c", DriverInstances = drivers, Devices = devices, }; [Fact] public void Two_devices_under_one_MTConnect_driver_is_a_deploy_error() { var errors = DraftValidator.Validate(Draft([Driver("mt", "MTConnect")], Dev("d1", "mt"), Dev("d2", "mt"))); var e = errors.Where(x => x.Code == Code).ShouldHaveSingleItem(); e.Context.ShouldBe("mt"); e.Message.ShouldContain("one MTConnect driver per agent device"); } [Fact] public void The_normal_single_device_layout_stays_valid() => DraftValidator.Validate(Draft([Driver("mt", "MTConnect")], Dev("d1", "mt"))) .ShouldNotContain(x => x.Code == Code); [Fact] public void A_driver_with_no_device_is_not_this_rules_concern() => DraftValidator.Validate(Draft([Driver("mt", "MTConnect")])) .ShouldNotContain(x => x.Code == Code); [Fact] public void Several_devices_under_a_non_MTConnect_driver_are_unaffected_and_devices_are_counted_per_driver() { var errors = DraftValidator.Validate(Draft( [Driver("mb", "Modbus"), Driver("mt1", "MTConnect"), Driver("mt2", "MTConnect")], Dev("a", "mb"), Dev("b", "mb"), Dev("c", "mt1"), Dev("d", "mt2"))); errors.ShouldNotContain(x => x.Code == Code); } }