using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests.Mitsubishi; /// /// End-to-end smoke against the MELSEC mitsubishi.json pymodbus profile (or a real /// MELSEC QJ71MT91 / iQ-R / FX5U when MODBUS_SIM_ENDPOINT points at one). Drives /// the full + real stack. /// Success proves the driver initializes against the MELSEC sim, writes a known value, /// and reads it back — the baseline every Mitsubishi-specific test (PR 59+) builds on. /// [Collection(ModbusSimulatorCollection.Name)] [Trait("Category", "Integration")] [Trait("Device", "Mitsubishi")] public sealed class MitsubishiSmokeTests(ModbusSimulatorFixture sim) { [Fact] public async Task Mitsubishi_roundtrip_write_then_read_of_holding_register() { if (sim.SkipReason is not null) Assert.Skip(sim.SkipReason); if (!string.Equals(Environment.GetEnvironmentVariable("MODBUS_SIM_PROFILE"), "mitsubishi", StringComparison.OrdinalIgnoreCase)) { Assert.Skip("MODBUS_SIM_PROFILE != mitsubishi — skipping."); } var options = MitsubishiProfile.BuildOptions(sim.Host, sim.Port); await using var driver = new ModbusDriver(options, driverInstanceId: "melsec-smoke"); await driver.InitializeAsync(driverConfigJson: "{}", TestContext.Current.CancellationToken); var writeResults = await driver.WriteAsync( [new(FullReference: "Smoke_HReg200", Value: (short)MitsubishiProfile.SmokeHoldingValue)], TestContext.Current.CancellationToken); writeResults.Count.ShouldBe(1); writeResults[0].StatusCode.ShouldBe(0u, "write must succeed against the MELSEC pymodbus profile"); var readResults = await driver.ReadAsync( ["Smoke_HReg200"], TestContext.Current.CancellationToken); readResults.Count.ShouldBe(1); readResults[0].StatusCode.ShouldBe(0u); readResults[0].Value.ShouldBe((short)MitsubishiProfile.SmokeHoldingValue); } }