using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Cli.Tests; /// /// Driver.S7.Cli-009: every S7 CLI command that catches /// must use the /// when (ct.IsCancellationRequested) exception filter so that a /// driver-internal timeout (thrown with a different cancellation token) does not get /// mis-handled as a user Ctrl+C. Source-level check mirrors /// . /// [Trait("Category", "Unit")] public sealed class CancellationHandlingTests { private static readonly string CommandsDir = LocateCommandsDir(); /// /// Verifies that ProbeCommand uses the ct.IsCancellationRequested guard on its /// OperationCanceledException catch block so a driver-internal timeout is not /// swallowed as a user-cancelled operation. /// [Fact] public void ProbeCommand_uses_ct_IsCancellationRequested_guard() { // Driver.S7.Cli-009: the bare `catch (OperationCanceledException)` without a // `when` filter would mis-classify a driver-internal timeout as a Ctrl+C and // either re-throw from the wrong catch block or swallow the error. var source = File.ReadAllText(Path.Combine(CommandsDir, "ProbeCommand.cs")); source.ShouldContain("when (ct.IsCancellationRequested)"); } /// /// Verifies that ReadCommand provides quiet cancellation handling for Ctrl+C. /// [Fact] public void ReadCommand_handles_OperationCanceledException_quietly() { // Driver.S7.Cli-009: ReadCommand must catch OperationCanceledException and // print "Cancelled." (matching the Modbus CLI pattern) rather than letting // CliFx render an unhandled exception on Ctrl+C. var source = File.ReadAllText(Path.Combine(CommandsDir, "ReadCommand.cs")); source.ShouldContain("OperationCanceledException"); source.ShouldContain("Cancelled."); } /// /// Verifies that WriteCommand provides quiet cancellation handling for Ctrl+C. /// [Fact] public void WriteCommand_handles_OperationCanceledException_quietly() { // Driver.S7.Cli-009: WriteCommand must catch OperationCanceledException and // print "Cancelled." (matching the Modbus CLI pattern) rather than letting // CliFx render an unhandled exception on Ctrl+C. var source = File.ReadAllText(Path.Combine(CommandsDir, "WriteCommand.cs")); source.ShouldContain("OperationCanceledException"); source.ShouldContain("Cancelled."); } private static string LocateCommandsDir() { var dir = new DirectoryInfo(AppContext.BaseDirectory); while (dir is not null && !File.Exists(Path.Combine(dir.FullName, "ZB.MOM.WW.OtOpcUa.slnx"))) dir = dir.Parent; dir.ShouldNotBeNull("Could not find solution root (ZB.MOM.WW.OtOpcUa.slnx)."); return Path.Combine( dir!.FullName, "src", "Drivers", "Cli", "ZB.MOM.WW.OtOpcUa.Driver.S7.Cli", "Commands"); } }