diff --git a/Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs b/Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs index 07f431dfd1..1540dc1e3b 100644 --- a/Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs +++ b/Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs @@ -31,7 +31,7 @@ public static (int exitCode, string result) Process ( { var output = string.Empty; - if (Console.IsInputRedirected || Console.IsOutputRedirected) + if (DriverImpl.DisableDriverRealIO) { return (-1, output); } diff --git a/Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs b/Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs index 6d8231d6b8..19f052ac7f 100644 --- a/Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs +++ b/Terminal.Gui/Drivers/AnsiDriver/AnsiInput.cs @@ -88,9 +88,9 @@ public AnsiInput () try { // Check if we have a real console first - if (!AnsiTerminalHelper.IsAttachedToTerminal (out bool inputAttached, out bool outputAttached)) + if (DriverImpl.DisableDriverRealIO) { - Trace.Lifecycle (nameof (AnsiInput), "Init", $"Console redirected (Output: {outputAttached}, Input: {inputAttached}). Running in degraded mode."); + Trace.Lifecycle (nameof (AnsiInput), "Init", "Console is running unit tests. Running in degraded mode."); return; } diff --git a/Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs b/Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs index d7ceff9e0e..3d2fb72204 100644 --- a/Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs +++ b/Terminal.Gui/Drivers/AnsiDriver/AnsiOutput.cs @@ -37,7 +37,7 @@ namespace Terminal.Gui.Drivers; public class AnsiOutput : OutputBase, IOutput { // Tracks which underlying platform APIs are in use - private readonly AnsiPlatform _platform; + internal readonly AnsiPlatform _platform; private Size _consoleSize = new (80, 25); private IOutputBuffer? _lastBuffer; @@ -61,9 +61,9 @@ public AnsiOutput () try { // Check if we have a real console first - if (!AnsiTerminalHelper.IsAttachedToTerminal (out bool inputAttached, out bool outputAttached)) + if (DriverImpl.DisableDriverRealIO) { - Trace.Lifecycle (nameof (AnsiOutput), "Init", $"Console redirected (Output: {outputAttached}, Input: {inputAttached}). Running in degraded mode."); + Trace.Lifecycle (nameof (AnsiOutput), "Init", "Console is running unit tests. Running in degraded mode."); return; } diff --git a/Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs b/Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs index ae73fe2043..734c0ccd82 100644 --- a/Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs +++ b/Terminal.Gui/Drivers/DotNetDriver/NetOutput.cs @@ -37,7 +37,7 @@ public Size GetSize () { try { - if (Console.IsInputRedirected || Console.IsOutputRedirected) + if (DriverImpl.DisableDriverRealIO) { return new Size (80, 25); } @@ -176,7 +176,7 @@ public void Suspend () Write (EscSeqUtils.CSI_DisableMouseEvents); // Check if we have a real console first - if (Console.IsInputRedirected || Console.IsOutputRedirected) + if (DriverImpl.DisableDriverRealIO) { Logging.Information ($"Console redirected (Output: {Console.IsOutputRedirected}, Input: {Console.IsInputRedirected}). Running in degraded mode."); diff --git a/Terminal.Gui/Drivers/DriverImpl.cs b/Terminal.Gui/Drivers/DriverImpl.cs index ca46daf3a7..e96b9d87d6 100644 --- a/Terminal.Gui/Drivers/DriverImpl.cs +++ b/Terminal.Gui/Drivers/DriverImpl.cs @@ -62,6 +62,27 @@ public DriverImpl (IComponentFactory componentFactory, #region Driver Lifecycle + /// + /// Determines whether the current execution context is within a unit test project. + /// + /// + /// This method leverages switches to ensure compatibility with + /// Native AOT and avoids trimming-related issues associated with reflection. + /// + /// For this to return true, the test project (e.g., xUnit v3) must define the + /// switch in its .csproj file: + /// + /// <ItemGroup> + /// <RuntimeHostConfigurationOption Include="Runtime.IsTestProject" Value="true" Trim="false" /> + /// </ItemGroup> + /// + /// + /// + /// + /// if the test execution flag is set; otherwise, . + /// + public static bool DisableDriverRealIO => AppContext.TryGetSwitch ("Runtime.IsTestProject", out bool isTest) && isTest; + /// public void Init () => throw new NotSupportedException (); diff --git a/Terminal.Gui/Drivers/Input/TestInputSource.cs b/Terminal.Gui/Drivers/Input/TestInputSource.cs index e5469039c2..b738a5526a 100644 --- a/Terminal.Gui/Drivers/Input/TestInputSource.cs +++ b/Terminal.Gui/Drivers/Input/TestInputSource.cs @@ -11,7 +11,7 @@ public class TestInputSource : IInputSource /// Initializes a new instance of the class. /// /// The time provider for timestamps. - public TestInputSource (ITimeProvider timeProvider) { TimeProvider = timeProvider; } + public TestInputSource (ITimeProvider timeProvider) => TimeProvider = timeProvider; /// public ITimeProvider TimeProvider { get; } diff --git a/Terminal.Gui/Drivers/UnixDriver/UnixTerminalHelper.cs b/Terminal.Gui/Drivers/UnixDriver/UnixTerminalHelper.cs index a2d8f57cf0..013680230c 100644 --- a/Terminal.Gui/Drivers/UnixDriver/UnixTerminalHelper.cs +++ b/Terminal.Gui/Drivers/UnixDriver/UnixTerminalHelper.cs @@ -101,9 +101,9 @@ public static void Suspend (IOutput output) output.Write (EscSeqUtils.CSI_DisableMouseEvents); // Check if we have a real console first - if (!AnsiTerminalHelper.IsAttachedToTerminal (out bool inputAttached, out bool outputAttached)) + if (DriverImpl.DisableDriverRealIO) { - Trace.Lifecycle (nameof (UnixTerminalHelper), "Suspend", $"Console redirected (Output: {outputAttached}, Input: {inputAttached}). Running in degraded mode."); + Trace.Lifecycle (nameof (UnixTerminalHelper), "Suspend", "Console is running unit tests. Running in degraded mode."); return; } diff --git a/Tests/IntegrationTests/IntegrationTests.csproj b/Tests/IntegrationTests/IntegrationTests.csproj index 8b1545686a..d3f942f7bb 100644 --- a/Tests/IntegrationTests/IntegrationTests.csproj +++ b/Tests/IntegrationTests/IntegrationTests.csproj @@ -20,7 +20,14 @@ true - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Tests/StressTests/StressTests.csproj b/Tests/StressTests/StressTests.csproj index a8c06c6afa..dd159b8248 100644 --- a/Tests/StressTests/StressTests.csproj +++ b/Tests/StressTests/StressTests.csproj @@ -12,8 +12,15 @@ enable true true - + + + + + true $(DefineConstants);DEBUG_IDISPOSABLE diff --git a/Tests/UnitTests/UnitTests.csproj b/Tests/UnitTests/UnitTests.csproj index 22b92ecdce..42bfae0e56 100644 --- a/Tests/UnitTests/UnitTests.csproj +++ b/Tests/UnitTests/UnitTests.csproj @@ -30,7 +30,15 @@ true + + + + + diff --git a/Tests/UnitTestsParallelizable/Input/InputInjectorTests.cs b/Tests/UnitTestsParallelizable/Input/InputInjectorTests.cs index 243b109c50..8261d2480e 100644 --- a/Tests/UnitTestsParallelizable/Input/InputInjectorTests.cs +++ b/Tests/UnitTestsParallelizable/Input/InputInjectorTests.cs @@ -127,7 +127,7 @@ public void InjectKey_DefaultOptions_UsesDirectMode () // BUGBUG: see https://github.com/gui-cs/Terminal.Gui/pull/4583#issuecomment-3769142085 [Fact (Skip = "Using Task.Delay (50) will cause failures in slow CI/CD runners")] - public async Task InjectKey_Pipeline_AccentedKeys_RaisesAllEvents () + public async Task InjectKey_Pipeline_AutoProcess_False_AccentedKeys_RaisesAllEvents () { // Arrange VirtualTimeProvider timeProvider = new (); @@ -185,7 +185,9 @@ public async Task InjectKey_Pipeline_AccentedKeys_RaisesAllEvents () await Task.Delay (50, TestContext.Current.CancellationToken); // Allow some time for processing injector.ProcessQueue (); - // Assert - Should raise exactly 3 KeyDown events + Assert.Equal (AnsiPlatform.Degraded, ((AnsiOutput)app.Driver?.GetOutput ()!)._platform); + + // Assert - Should raise exactly 34 KeyDown events Assert.Equal (34, receivedKeys.Count); Assert.Equal (new Key ('á'), receivedKeys [0]); Assert.Equal (new Key ('é'), receivedKeys [1]); @@ -227,7 +229,7 @@ public async Task InjectKey_Pipeline_AccentedKeys_RaisesAllEvents () // BUGBUG: when an accented char comes into the actual stdIn stream, only. // BUGBUG: see https://github.com/gui-cs/Terminal.Gui/pull/4583#issuecomment-3769142085 [Fact (Skip = "Using Task.Delay (50) will cause failures in slow CI/CD runners")] - public async Task InjectKey_PipelineMode_MultipleKeys_RaisesAllEvents () + public async Task InjectKey_PipelineMode_AutoProcess_True_MultipleKeys_RaisesAllEvents () { // Arrange VirtualTimeProvider timeProvider = new (); @@ -254,6 +256,8 @@ public async Task InjectKey_PipelineMode_MultipleKeys_RaisesAllEvents () await Task.Delay (50, TestContext.Current.CancellationToken); // Allow some time for processing injector.ProcessQueue (); + Assert.Equal (AnsiPlatform.Degraded, ((AnsiOutput)app.Driver?.GetOutput ()!)._platform); + // Assert - Should raise exactly 3 KeyDown events Assert.Equal (3, receivedKeys.Count); Assert.Equal (Key.A, receivedKeys [0]); diff --git a/Tests/UnitTestsParallelizable/UnitTests.Parallelizable.csproj b/Tests/UnitTestsParallelizable/UnitTests.Parallelizable.csproj index 37ac79b9c8..5b8567c067 100644 --- a/Tests/UnitTestsParallelizable/UnitTests.Parallelizable.csproj +++ b/Tests/UnitTestsParallelizable/UnitTests.Parallelizable.csproj @@ -25,6 +25,13 @@ true + + + + true $(DefineConstants);DEBUG_IDISPOSABLE