diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxDataConsumer.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxDataConsumer.cs index 60f005a378..8d6bac34e1 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxDataConsumer.cs +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxDataConsumer.cs @@ -181,8 +181,7 @@ await _logger.LogDebugAsync($""" """).ConfigureAwait(false); } - if (_commandLineOptionsService.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName) - && !OperatingSystem.IsBrowser()) + if (TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptionsService)) { ApplicationStateGuard.Ensure(_trxTestApplicationLifecycleCallbacks is not null); ApplicationStateGuard.Ensure(_trxTestApplicationLifecycleCallbacks.NamedPipeClient is not null); @@ -236,11 +235,11 @@ public async Task OnTestSessionFinishingAsync(ITestSessionContext testSessionCon } // If crash dump is not enabled we run trx in-process only - if (!_commandLineOptionsService.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName)) + if (!TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptionsService)) { await _messageBus.PublishAsync(this, new SessionFileArtifact(testSessionContext.SessionUid, new FileInfo(reportFileName), ExtensionResources.TrxReportArtifactDisplayName, ExtensionResources.TrxReportArtifactDescription)).ConfigureAwait(false); } - else if (!OperatingSystem.IsBrowser()) + else { ApplicationStateGuard.Ensure(_trxTestApplicationLifecycleCallbacks is not null); ApplicationStateGuard.Ensure(_trxTestApplicationLifecycleCallbacks.NamedPipeClient is not null); diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxEnvironmentVariableProvider.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxEnvironmentVariableProvider.cs index ccbd8f1e4d..e2af2f8b2c 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxEnvironmentVariableProvider.cs +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxEnvironmentVariableProvider.cs @@ -36,7 +36,7 @@ public Task IsEnabledAsync() // TrxReportGenerator is enabled only when trx report is enabled _commandLineOptions.IsOptionSet(TrxReportGeneratorCommandLine.TrxReportOptionName) // If crash dump is not enabled we run trx in-process only - && _commandLineOptions.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName)); + && TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptions)); #pragma warning restore SA1114 // Parameter list should follow declaration public Task UpdateAsync(IEnvironmentVariables environmentVariables) diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxModeHelpers.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxModeHelpers.cs new file mode 100644 index 0000000000..44df8fc734 --- /dev/null +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxModeHelpers.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Testing.Platform.CommandLine; + +namespace Microsoft.Testing.Extensions.TrxReport; + +internal static class TrxModeHelpers +{ + [UnsupportedOSPlatformGuard("BROWSER")] + public static bool ShouldUseOutOfProcessTrxGeneration(ICommandLineOptions commandLineOptions) + => commandLineOptions.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName) && + !RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); +} diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxProcessLifetimeHandler.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxProcessLifetimeHandler.cs index ff58f493c3..f0dd136757 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxProcessLifetimeHandler.cs +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxProcessLifetimeHandler.cs @@ -22,7 +22,6 @@ namespace Microsoft.Testing.Extensions.TrxReport.Abstractions; -[UnsupportedOSPlatform("browser")] internal sealed class TrxProcessLifetimeHandler : ITestHostProcessLifetimeHandler, IDataConsumer, @@ -94,23 +93,36 @@ public Task IsEnabledAsync() // TrxReportGenerator is enabled only when trx report is enabled _commandLineOptions.IsOptionSet(TrxReportGeneratorCommandLine.TrxReportOptionName) // If crash dump is not enabled we run trx in-process only - && _commandLineOptions.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName)); + && TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptions)); #pragma warning restore SA1114 // Parameter list should follow declaration public Task BeforeTestHostProcessStartAsync(CancellationToken cancellation) { - _waitConnectionTask = _task.Run( + // IsEnabledAsync will only return true if we are out of process. + // If we are not out of process, then we are disabled. Hence, this won't be called. + // The extra check is to let the platform compatibility analyzer know that we are not running in browser. + if (!TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptions)) + { + throw ApplicationStateGuard.Unreachable(); + } + + // Note: Inlining this method produces a false positive warning for platform compatibility. + BeforeTestHostProcessStartCore(cancellation); + + return Task.CompletedTask; + } + + [UnsupportedOSPlatform("BROWSER")] + private void BeforeTestHostProcessStartCore(CancellationToken cancellationToken) + => _waitConnectionTask = _task.Run( async () => { - _singleConnectionNamedPipeServer = new(_pipeNameDescription, CallbackAsync, _environment, _logger, _task, cancellation); + _singleConnectionNamedPipeServer = new(_pipeNameDescription, CallbackAsync, _environment, _logger, _task, cancellationToken); _singleConnectionNamedPipeServer.RegisterSerializer(new ReportFileNameRequestSerializer(), typeof(ReportFileNameRequest)); _singleConnectionNamedPipeServer.RegisterSerializer(new TestAdapterInformationRequestSerializer(), typeof(TestAdapterInformationRequest)); _singleConnectionNamedPipeServer.RegisterSerializer(new VoidResponseSerializer(), typeof(VoidResponse)); - await _singleConnectionNamedPipeServer.WaitConnectionAsync(cancellation).TimeoutAfterAsync(TimeoutHelper.DefaultHangTimeSpanTimeout, cancellation).ConfigureAwait(false); - }, cancellation); - - return Task.CompletedTask; - } + await _singleConnectionNamedPipeServer.WaitConnectionAsync(cancellationToken).TimeoutAfterAsync(TimeoutHelper.DefaultHangTimeSpanTimeout, cancellationToken).ConfigureAwait(false); + }, cancellationToken); public async Task OnTestHostProcessStartedAsync(ITestHostProcessInformation testHostProcessInformation, CancellationToken cancellation) { @@ -233,7 +245,12 @@ public async ValueTask DisposeAsync() #endif public void Dispose() - => _singleConnectionNamedPipeServer?.Dispose(); + { + if (TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(_commandLineOptions)) + { + _singleConnectionNamedPipeServer?.Dispose(); + } + } private sealed class ExtensionInfo : IExtension { diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportExtensions.cs index af30ba25cf..571b661275 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxReportExtensions.cs @@ -44,10 +44,14 @@ public static void AddTrxReportProvider(this ITestApplicationBuilder builder) serviceProvider.GetTestFramework(), serviceProvider.GetTestFrameworkCapabilities(), serviceProvider.GetTestApplicationProcessExitCode(), - OperatingSystem.IsBrowser() ? null : serviceProvider.GetService(), + serviceProvider.GetService(), serviceProvider.GetLoggerFactory().CreateLogger())); +#if NETCOREAPP if (!OperatingSystem.IsBrowser()) +#else + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"))) +#endif { NonBrowserRegistrations(builder); } diff --git a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxTestApplicationLifecycleCallbacks.cs b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxTestApplicationLifecycleCallbacks.cs index 72f9d0b946..b29bdf6b26 100644 --- a/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxTestApplicationLifecycleCallbacks.cs +++ b/src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxTestApplicationLifecycleCallbacks.cs @@ -12,10 +12,11 @@ namespace Microsoft.Testing.Extensions.TrxReport.Abstractions; -[UnsupportedOSPlatform("browser")] internal sealed class TrxTestApplicationLifecycleCallbacks : ITestHostApplicationLifetime, IDisposable { + [UnsupportedOSPlatformGuard("BROWSER")] private readonly bool _isEnabled; + private readonly IEnvironment _environment; public TrxTestApplicationLifecycleCallbacks( @@ -26,7 +27,7 @@ public TrxTestApplicationLifecycleCallbacks( // TrxReportGenerator is enabled only when trx report is enabled commandLineOptionsService.IsOptionSet(TrxReportGeneratorCommandLine.TrxReportOptionName) && // If crash dump is not enabled we run trx in-process only - commandLineOptionsService.IsOptionSet(CrashDumpCommandLineOptions.CrashDumpOptionName); + TrxModeHelpers.ShouldUseOutOfProcessTrxGeneration(commandLineOptionsService); _environment = environment; } @@ -77,5 +78,11 @@ public async Task BeforeRunAsync(CancellationToken cancellationToken) } } - public void Dispose() => NamedPipeClient?.Dispose(); + public void Dispose() + { + if (_isEnabled) + { + NamedPipeClient?.Dispose(); + } + } }