using Shouldly; using Xunit; namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli.Tests; /// /// Driver.FOCAS.Cli-006: every FOCAS CLI command must call /// FlushLogging() in a finally block so buffered Serilog output /// emitted during driver shutdown is not silently dropped when the process exits. /// DriverCommandBase documents this requirement and every sibling CLI /// (Modbus / S7 / AbCip / AbLegacy / TwinCAT) honours it; the FOCAS CLI was /// the only one missing the call. /// [Trait("Category", "Unit")] public sealed class FlushLoggingConventionsTests { private static readonly string CommandsDir = LocateCommandsDir(); /// /// Verifies that a FOCAS CLI command source file contains a FlushLogging() /// call, matching the pattern used by every other driver CLI in the repo. /// /// The command source file name to inspect. [Theory] [InlineData("ProbeCommand.cs")] [InlineData("ReadCommand.cs")] [InlineData("WriteCommand.cs")] [InlineData("SubscribeCommand.cs")] public void Command_calls_FlushLogging_in_finally_block(string commandFile) { var path = Path.Combine(CommandsDir, commandFile); File.Exists(path).ShouldBeTrue($"Expected {path} to exist."); var source = File.ReadAllText(path); // DriverCommandBase.ConfigureLogging XML doc says: // "Call FlushLogging in a finally block to ensure buffered output is flushed // before the process exits." // Every other driver CLI (Modbus, AbCip, AbLegacy, TwinCAT) calls FlushLogging() // from a finally block. The FOCAS CLI must do the same so buffered Serilog output // during driver shutdown is not lost when the process exits abruptly. source.ShouldContain("FlushLogging()"); } 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.FOCAS.Cli", "Commands"); } }