using Serilog; using Serilog.Core; using Serilog.Events; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Client.CLI.Commands; using ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes; namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests; /// /// Regression test for Client.CLI-007: ConfigureLogging must dispose the previously assigned /// Log.Logger before replacing it, so repeated CLI invocations do not leak sinks. /// public class LoggerLifecycleTests { [Fact] public async Task ConfigureLogging_DisposesPreviousLogger_BeforeReassigning() { // Install a tracker logger before the command runs. var trackerSink = new DisposeTrackingSink(); var trackerLogger = new LoggerConfiguration() .WriteTo.Sink(trackerSink) .CreateLogger(); Log.Logger = trackerLogger; try { var fakeService = new FakeOpcUaClientService(); var factory = new FakeOpcUaClientServiceFactory(fakeService); var command = new ConnectCommand(factory) { Url = "opc.tcp://localhost:4840" }; using var console = TestConsoleHelper.CreateConsole(); await command.ExecuteAsync(console); // The command's ConfigureLogging should have disposed the tracker logger we installed. trackerSink.Disposed.ShouldBeTrue( "Previous Log.Logger should be disposed via Log.CloseAndFlush() before ConfigureLogging assigns a new one."); } finally { Log.CloseAndFlush(); } } private sealed class DisposeTrackingSink : ILogEventSink, IDisposable { public bool Disposed { get; private set; } public void Emit(LogEvent logEvent) { } public void Dispose() => Disposed = true; } }