using CliFx.Infrastructure; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Commands; namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests; /// /// Covers Driver.Modbus.Cli-005: probe / read / write must swallow /// so a Ctrl+C during InitializeAsync exits /// cleanly instead of dumping a full stack trace through CliFx. SubscribeCommand /// already handles this around its Task.Delay; these tests pin the same behaviour /// to the connect/read/write commands. /// The test pre-cancels the CliFx ; the driver's /// ConnectAsync observes the token via Dns.GetHostAddressesAsync and throws /// OCE before any socket I/O happens, so the test is hermetic — no real PLC needed. /// [Trait("Category", "Unit")] public sealed class CommandCancellationTests { [Fact] public async Task ProbeCommand_swallows_cancellation_during_initialize() { using var console = new FakeInMemoryConsole(); console.RequestCancellation(); // simulate Ctrl+C before ExecuteAsync runs var sut = new ProbeCommand { Host = "127.0.0.1" }; await Should.NotThrowAsync(async () => await sut.ExecuteAsync(console)); } [Fact] public async Task ReadCommand_swallows_cancellation_during_initialize() { using var console = new FakeInMemoryConsole(); console.RequestCancellation(); var sut = new ReadCommand { Host = "127.0.0.1", Region = ModbusRegion.HoldingRegisters, Address = 0, DataType = ModbusDataType.UInt16, }; await Should.NotThrowAsync(async () => await sut.ExecuteAsync(console)); } [Fact] public async Task WriteCommand_swallows_cancellation_during_initialize() { using var console = new FakeInMemoryConsole(); console.RequestCancellation(); var sut = new WriteCommand { Host = "127.0.0.1", Region = ModbusRegion.HoldingRegisters, Address = 0, DataType = ModbusDataType.UInt16, Value = "42", }; await Should.NotThrowAsync(async () => await sut.ExecuteAsync(console)); } }