diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs index 335b055609..f0bf7c3909 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/AttachmentsProcessing/DataCollectorAttachmentsProcessorsFactory.cs @@ -15,6 +15,7 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.TestRunAttachmentsProcessing; @@ -23,6 +24,13 @@ internal class DataCollectorAttachmentsProcessorsFactory : IDataCollectorAttachm private const string CoverageFriendlyName = "Code Coverage"; private static readonly ConcurrentDictionary DataCollectorExtensionManagerCache = new(); + private readonly IRunSettingsHelper _runSettingsHelper; + + public DataCollectorAttachmentsProcessorsFactory(IRunSettingsHelper? runSettingsHelper = null) + { + _runSettingsHelper = runSettingsHelper ?? RunSettingsHelper.Instance; + } + public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[]? invokedDataCollectors, IMessageLogger? logger) { IDictionary> datacollectorsAttachmentsProcessors = new Dictionary>(); @@ -52,7 +60,7 @@ public DataCollectorAttachmentProcessor[] Create(InvokedDataCollector[]? invoked #endif // If we're in design mode we need to load the extension inside a different AppDomain to avoid to lock extension file containers. - if (canUseAppDomains && RunSettingsHelper.Instance.IsDesignMode) + if (canUseAppDomains && _runSettingsHelper.IsDesignMode) { #if NETFRAMEWORK try diff --git a/src/vstest.console/CommandLine/Executor.cs b/src/vstest.console/CommandLine/Executor.cs index 11f996557c..a2daebfb8c 100644 --- a/src/vstest.console/CommandLine/Executor.cs +++ b/src/vstest.console/CommandLine/Executor.cs @@ -26,6 +26,8 @@ using Abstraction::Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; @@ -61,6 +63,7 @@ internal class Executor private readonly IProcessHelper _processHelper; private readonly IEnvironment _environment; private readonly IRunSettingsProvider _runSettingsProvider; + private readonly IRunSettingsHelper _runSettingsHelper; private bool _showHelp; /// @@ -91,11 +94,16 @@ internal class Executor } internal Executor(IOutput output, ITestPlatformEventSource testPlatformEventSource, IProcessHelper processHelper, IEnvironment environment) - : this(output, testPlatformEventSource, processHelper, environment, RunSettingsManager.Instance) + : this(output, testPlatformEventSource, processHelper, environment, RunSettingsManager.Instance, RunSettingsHelper.Instance) { } internal Executor(IOutput output, ITestPlatformEventSource testPlatformEventSource, IProcessHelper processHelper, IEnvironment environment, IRunSettingsProvider runSettingsProvider) + : this(output, testPlatformEventSource, processHelper, environment, runSettingsProvider, RunSettingsHelper.Instance) + { + } + + internal Executor(IOutput output, ITestPlatformEventSource testPlatformEventSource, IProcessHelper processHelper, IEnvironment environment, IRunSettingsProvider runSettingsProvider, IRunSettingsHelper runSettingsHelper) { DebuggerBreakpoint.AttachVisualStudioDebugger(WellKnownDebugEnvironmentVariables.VSTEST_RUNNER_DEBUG_ATTACHVS); DebuggerBreakpoint.WaitForNativeDebugger(WellKnownDebugEnvironmentVariables.VSTEST_RUNNER_NATIVE_DEBUG); @@ -107,6 +115,7 @@ internal Executor(IOutput output, ITestPlatformEventSource testPlatformEventSour _processHelper = processHelper; _environment = environment; _runSettingsProvider = runSettingsProvider; + _runSettingsHelper = runSettingsHelper; } /// @@ -228,7 +237,7 @@ private int GetArgumentProcessors(string[] args, out List pr { processors = new List(); int result = 0; - var processorFactory = ArgumentProcessorFactory.Create(runSettingsProvider: _runSettingsProvider); + var processorFactory = ArgumentProcessorFactory.Create(runSettingsProvider: _runSettingsProvider, runSettingsHelper: _runSettingsHelper); for (var index = 0; index < args.Length; index++) { var arg = args[index]; diff --git a/src/vstest.console/Processors/CLIRunSettingsArgumentProcessor.cs b/src/vstest.console/Processors/CLIRunSettingsArgumentProcessor.cs index a6ddc77bc6..a5ac978b14 100644 --- a/src/vstest.console/Processors/CLIRunSettingsArgumentProcessor.cs +++ b/src/vstest.console/Processors/CLIRunSettingsArgumentProcessor.cs @@ -11,7 +11,7 @@ using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; @@ -30,10 +30,12 @@ internal class CliRunSettingsArgumentProcessor : IArgumentProcessor private Lazy? _metadata; private Lazy? _executor; private readonly IRunSettingsProvider _runSettingsProvider; + private readonly IRunSettingsHelper _runSettingsHelper; - public CliRunSettingsArgumentProcessor(IRunSettingsProvider runSettingsProvider) + public CliRunSettingsArgumentProcessor(IRunSettingsProvider runSettingsProvider, IRunSettingsHelper runSettingsHelper) { _runSettingsProvider = runSettingsProvider; + _runSettingsHelper = runSettingsHelper; } /// @@ -49,7 +51,7 @@ public Lazy Metadata public Lazy? Executor { get => _executor ??= new Lazy(() => - new CliRunSettingsArgumentExecutor(_runSettingsProvider, CommandLineOptions.Instance)); + new CliRunSettingsArgumentExecutor(_runSettingsProvider, CommandLineOptions.Instance, _runSettingsHelper)); set => _executor = value; } @@ -74,11 +76,13 @@ internal class CliRunSettingsArgumentExecutor : IArgumentsExecutor { private readonly IRunSettingsProvider _runSettingsManager; private readonly CommandLineOptions _commandLineOptions; + private readonly IRunSettingsHelper _runSettingsHelper; - internal CliRunSettingsArgumentExecutor(IRunSettingsProvider runSettingsManager, CommandLineOptions commandLineOptions) + internal CliRunSettingsArgumentExecutor(IRunSettingsProvider runSettingsManager, CommandLineOptions commandLineOptions, IRunSettingsHelper runSettingsHelper) { _runSettingsManager = runSettingsManager; _commandLineOptions = commandLineOptions; + _runSettingsHelper = runSettingsHelper; } public void Initialize(string? argument) @@ -239,7 +243,7 @@ private void UpdateFrameworkAndPlatform(string key, string value) bool success = Enum.TryParse(value, true, out var architecture); if (success) { - RunSettingsHelper.Instance.IsDefaultTargetArchitecture = false; + _runSettingsHelper.IsDefaultTargetArchitecture = false; _commandLineOptions.TargetArchitecture = architecture; } } diff --git a/src/vstest.console/Processors/PlatformArgumentProcessor.cs b/src/vstest.console/Processors/PlatformArgumentProcessor.cs index 621d3688b3..5a1835be13 100644 --- a/src/vstest.console/Processors/PlatformArgumentProcessor.cs +++ b/src/vstest.console/Processors/PlatformArgumentProcessor.cs @@ -9,7 +9,7 @@ using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; -using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; @@ -29,10 +29,12 @@ internal class PlatformArgumentProcessor : IArgumentProcessor private Lazy? _metadata; private Lazy? _executor; private readonly IRunSettingsProvider _runSettingsProvider; + private readonly IRunSettingsHelper _runSettingsHelper; - public PlatformArgumentProcessor(IRunSettingsProvider runSettingsProvider) + public PlatformArgumentProcessor(IRunSettingsProvider runSettingsProvider, IRunSettingsHelper runSettingsHelper) { _runSettingsProvider = runSettingsProvider; + _runSettingsHelper = runSettingsHelper; } /// @@ -48,7 +50,7 @@ public Lazy Metadata public Lazy? Executor { get => _executor ??= new Lazy(() => - new PlatformArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider)); + new PlatformArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider, _runSettingsHelper)); set => _executor = value; } @@ -80,6 +82,8 @@ internal class PlatformArgumentExecutor : IArgumentExecutor private readonly IRunSettingsProvider _runSettingsManager; + private readonly IRunSettingsHelper _runSettingsHelper; + public const string RunSettingsPath = "RunConfiguration.TargetPlatform"; /// @@ -87,12 +91,15 @@ internal class PlatformArgumentExecutor : IArgumentExecutor /// /// The options. /// The runsettings manager. - public PlatformArgumentExecutor(CommandLineOptions options, IRunSettingsProvider runSettingsManager) + /// The runsettings helper. + public PlatformArgumentExecutor(CommandLineOptions options, IRunSettingsProvider runSettingsManager, IRunSettingsHelper runSettingsHelper) { ValidateArg.NotNull(options, nameof(options)); ValidateArg.NotNull(runSettingsManager, nameof(runSettingsManager)); + ValidateArg.NotNull(runSettingsHelper, nameof(runSettingsHelper)); _commandLineOptions = options; _runSettingsManager = runSettingsManager; + _runSettingsHelper = runSettingsHelper; } @@ -125,7 +132,7 @@ public void Initialize(string? argument) if (validPlatform) { - RunSettingsHelper.Instance.IsDefaultTargetArchitecture = false; + _runSettingsHelper.IsDefaultTargetArchitecture = false; _commandLineOptions.TargetArchitecture = platform; _runSettingsManager.UpdateRunSettingsNode(RunSettingsPath, platform.ToString()); } diff --git a/src/vstest.console/Processors/PortArgumentProcessor.cs b/src/vstest.console/Processors/PortArgumentProcessor.cs index f5fbbe818b..0e12dc46cf 100644 --- a/src/vstest.console/Processors/PortArgumentProcessor.cs +++ b/src/vstest.console/Processors/PortArgumentProcessor.cs @@ -12,7 +12,7 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Abstraction::Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Abstraction::Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; -using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommandLineResources = Microsoft.VisualStudio.TestPlatform.CommandLine.Resources.Resources; @@ -30,6 +30,12 @@ internal class PortArgumentProcessor : IArgumentProcessor private Lazy? _metadata; private Lazy? _executor; + private readonly IRunSettingsHelper _runSettingsHelper; + + public PortArgumentProcessor(IRunSettingsHelper runSettingsHelper) + { + _runSettingsHelper = runSettingsHelper; + } /// /// Gets the metadata. @@ -43,7 +49,7 @@ public Lazy Metadata public Lazy? Executor { get => _executor ??= new Lazy(() => - new PortArgumentExecutor(CommandLineOptions.Instance, TestRequestManager.Instance)); + new PortArgumentExecutor(CommandLineOptions.Instance, TestRequestManager.Instance, _runSettingsHelper)); set => _executor = value; } @@ -99,6 +105,11 @@ internal class PortArgumentExecutor : IArgumentExecutor /// private readonly IProcessHelper _processHelper; + /// + /// Used to flag that the run was started from an Editor or IDE. + /// + private readonly IRunSettingsHelper _runSettingsHelper; + /// /// Default constructor. /// @@ -106,32 +117,33 @@ internal class PortArgumentExecutor : IArgumentExecutor /// The options. /// /// Test request manager - public PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager) - : this(options, testRequestManager, InitializeDesignMode, new ProcessHelper()) + /// The runsettings helper. + public PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager, IRunSettingsHelper runSettingsHelper) + : this(options, testRequestManager, InitializeDesignMode, new ProcessHelper(), runSettingsHelper) { } /// /// For Unit testing only /// - internal PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager, IProcessHelper processHelper) - : this(options, testRequestManager, InitializeDesignMode, processHelper) + internal PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager, IProcessHelper processHelper, IRunSettingsHelper runSettingsHelper) + : this(options, testRequestManager, InitializeDesignMode, processHelper, runSettingsHelper) { } /// /// For Unit testing only /// - internal PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager, Func designModeInitializer, IProcessHelper processHelper) + internal PortArgumentExecutor(CommandLineOptions options, ITestRequestManager testRequestManager, Func designModeInitializer, IProcessHelper processHelper, IRunSettingsHelper runSettingsHelper) { ValidateArg.NotNull(options, nameof(options)); _commandLineOptions = options; _testRequestManager = testRequestManager; _designModeInitializer = designModeInitializer; _processHelper = processHelper; + _runSettingsHelper = runSettingsHelper; } - #region IArgumentExecutor /// @@ -148,7 +160,7 @@ public void Initialize(string? argument) _port = portNumber; _commandLineOptions.Port = portNumber; _commandLineOptions.IsDesignMode = true; - RunSettingsHelper.Instance.IsDesignMode = true; + _runSettingsHelper.IsDesignMode = true; _designModeClient = _designModeInitializer?.Invoke(_commandLineOptions.ParentProcessId, _processHelper); } diff --git a/src/vstest.console/Processors/RunSettingsArgumentProcessor.cs b/src/vstest.console/Processors/RunSettingsArgumentProcessor.cs index 84517a465a..053c8aa147 100644 --- a/src/vstest.console/Processors/RunSettingsArgumentProcessor.cs +++ b/src/vstest.console/Processors/RunSettingsArgumentProcessor.cs @@ -31,10 +31,12 @@ internal class RunSettingsArgumentProcessor : IArgumentProcessor private Lazy? _metadata; private Lazy? _executor; private readonly IRunSettingsProvider _runSettingsProvider; + private readonly IRunSettingsHelper _runSettingsHelper; - public RunSettingsArgumentProcessor(IRunSettingsProvider runSettingsProvider) + public RunSettingsArgumentProcessor(IRunSettingsProvider runSettingsProvider, IRunSettingsHelper runSettingsHelper) { _runSettingsProvider = runSettingsProvider; + _runSettingsHelper = runSettingsHelper; } /// @@ -50,7 +52,7 @@ public Lazy Metadata public Lazy? Executor { get => _executor ??= new Lazy(() => - new RunSettingsArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider)); + new RunSettingsArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider, _runSettingsHelper)); set => _executor = value; } @@ -75,13 +77,15 @@ internal class RunSettingsArgumentExecutor : IArgumentExecutor { private readonly CommandLineOptions _commandLineOptions; private readonly IRunSettingsProvider _runSettingsManager; + private readonly IRunSettingsHelper _runSettingsHelper; internal IFileHelper FileHelper { get; set; } - internal RunSettingsArgumentExecutor(CommandLineOptions commandLineOptions, IRunSettingsProvider runSettingsManager) + internal RunSettingsArgumentExecutor(CommandLineOptions commandLineOptions, IRunSettingsProvider runSettingsManager, IRunSettingsHelper runSettingsHelper) { _commandLineOptions = commandLineOptions; _runSettingsManager = runSettingsManager; + _runSettingsHelper = runSettingsHelper; FileHelper = new FileHelper(); } @@ -150,7 +154,7 @@ private void ExtractFrameworkAndPlatform() var platformStr = _runSettingsManager.QueryRunSettingsNode(PlatformArgumentExecutor.RunSettingsPath); if (Enum.TryParse(platformStr, true, out var architecture)) { - RunSettingsHelper.Instance.IsDefaultTargetArchitecture = false; + _runSettingsHelper.IsDefaultTargetArchitecture = false; _commandLineOptions.TargetArchitecture = architecture; } } diff --git a/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs b/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs index d05037f287..f0ad9115a6 100644 --- a/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs +++ b/src/vstest.console/Processors/Utilities/ArgumentProcessorFactory.cs @@ -11,6 +11,8 @@ using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; @@ -51,11 +53,17 @@ protected ArgumentProcessorFactory(IEnumerable argumentProce /// Defaults to the ambient when not provided, so that /// callers (and the composition root) can inject an isolated instance instead of sharing static state. /// + /// + /// The run settings helper that the created argument processors write request-scoped flags to. + /// Defaults to the ambient when not provided, so that + /// callers (and the composition root) can inject an isolated instance instead of sharing static state. + /// /// ArgumentProcessorFactory. - internal static ArgumentProcessorFactory Create(IFeatureFlag? featureFlag = null, IRunSettingsProvider? runSettingsProvider = null) + internal static ArgumentProcessorFactory Create(IFeatureFlag? featureFlag = null, IRunSettingsProvider? runSettingsProvider = null, IRunSettingsHelper? runSettingsHelper = null) { runSettingsProvider ??= RunSettingsManager.Instance; - var defaultArgumentProcessor = GetDefaultArgumentProcessors(runSettingsProvider); + runSettingsHelper ??= RunSettingsHelper.Instance; + var defaultArgumentProcessor = GetDefaultArgumentProcessors(runSettingsProvider, runSettingsHelper); if (!(featureFlag ?? FeatureFlag.Instance).IsSet(FeatureFlag.VSTEST_DISABLE_ARTIFACTS_POSTPROCESSING)) { @@ -189,7 +197,7 @@ public IEnumerable GetArgumentProcessorsToAlwaysExecute() .Where(lazyProcessor => lazyProcessor.Metadata.Value.IsSpecialCommand && lazyProcessor.Metadata.Value.AlwaysExecute); } - private static IList GetDefaultArgumentProcessors(IRunSettingsProvider runSettingsProvider) => new List { + private static IList GetDefaultArgumentProcessors(IRunSettingsProvider runSettingsProvider, IRunSettingsHelper runSettingsHelper) => new List { new HelpArgumentProcessor(), new TestSourceArgumentProcessor(), new ListTestsArgumentProcessor(runSettingsProvider), @@ -199,14 +207,14 @@ public IEnumerable GetArgumentProcessorsToAlwaysExecute() new TestAdapterLoadingStrategyArgumentProcessor(runSettingsProvider), new TestCaseFilterArgumentProcessor(), new ParentProcessIdArgumentProcessor(), - new PortArgumentProcessor(), - new RunSettingsArgumentProcessor(runSettingsProvider), - new PlatformArgumentProcessor(runSettingsProvider), + new PortArgumentProcessor(runSettingsHelper), + new RunSettingsArgumentProcessor(runSettingsProvider, runSettingsHelper), + new PlatformArgumentProcessor(runSettingsProvider, runSettingsHelper), new FrameworkArgumentProcessor(runSettingsProvider), new EnableLoggerArgumentProcessor(runSettingsProvider), new ParallelArgumentProcessor(runSettingsProvider), new EnableDiagArgumentProcessor(), - new CliRunSettingsArgumentProcessor(runSettingsProvider), + new CliRunSettingsArgumentProcessor(runSettingsProvider, runSettingsHelper), new ResultsDirectoryArgumentProcessor(runSettingsProvider), new InIsolationArgumentProcessor(runSettingsProvider), new CollectArgumentProcessor(runSettingsProvider), diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs index cbc665aec0..c74264a588 100644 --- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs +++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs @@ -66,6 +66,7 @@ internal class TestRequestManager : ITestRequestManager private readonly ITestRunAttachmentsProcessingManager _attachmentsProcessingManager; private readonly IEnvironment _environment; private readonly IEnvironmentVariableHelper _environmentVariableHelper; + private readonly IRunSettingsHelper _runSettingsHelper; /// /// Maintains the current active execution request. @@ -108,7 +109,8 @@ public TestRequestManager() new ProcessHelper(), new TestRunAttachmentsProcessingManager(TestPlatformEventSource.Instance, new DataCollectorAttachmentsProcessorsFactory()), new PlatformEnvironment(), - new EnvironmentVariableHelper()) + new EnvironmentVariableHelper(), + RunSettingsHelper.Instance) { } @@ -123,6 +125,33 @@ internal TestRequestManager( ITestRunAttachmentsProcessingManager attachmentsProcessingManager, IEnvironment environment, IEnvironmentVariableHelper environmentVariableHelper) + : this( + commandLineOptions, + testPlatform, + testRunResultAggregator, + testPlatformEventSource, + inferHelper, + metricsPublisher, + processHelper, + attachmentsProcessingManager, + environment, + environmentVariableHelper, + RunSettingsHelper.Instance) + { + } + + internal TestRequestManager( + CommandLineOptions commandLineOptions, + ITestPlatform testPlatform, + TestRunResultAggregator testRunResultAggregator, + ITestPlatformEventSource testPlatformEventSource, + InferHelper inferHelper, + Task metricsPublisher, + IProcessHelper processHelper, + ITestRunAttachmentsProcessingManager attachmentsProcessingManager, + IEnvironment environment, + IEnvironmentVariableHelper environmentVariableHelper, + IRunSettingsHelper runSettingsHelper) { _testPlatform = testPlatform; _commandLineOptions = commandLineOptions; @@ -134,6 +163,7 @@ internal TestRequestManager( _attachmentsProcessingManager = attachmentsProcessingManager; _environment = environment; _environmentVariableHelper = environmentVariableHelper; + _runSettingsHelper = runSettingsHelper; } /// @@ -779,7 +809,7 @@ private bool UpdateRunSettingsIfRequired( // Other scenarios, most notably .NET Framework with MultiTFM disabled, will use the old default X86 architecture. } - EqtTrace.Verbose($"TestRequestManager.UpdateRunSettingsIfRequired: Default architecture: {defaultArchitecture} IsDefaultTargetArchitecture: {RunSettingsHelper.Instance.IsDefaultTargetArchitecture}, Current process architecture: {_processHelper.GetCurrentProcessArchitecture()} OperatingSystem: {_environment.OperatingSystem}."); + EqtTrace.Verbose($"TestRequestManager.UpdateRunSettingsIfRequired: Default architecture: {defaultArchitecture} IsDefaultTargetArchitecture: {_runSettingsHelper.IsDefaultTargetArchitecture}, Current process architecture: {_processHelper.GetCurrentProcessArchitecture()} OperatingSystem: {_environment.OperatingSystem}."); // True when runsettings don't set platforml. False when runsettings force platform // in both cases the sourceToArchitectureMap is populated with the real architecture as we inferred it @@ -856,7 +886,7 @@ private bool UpdateRunSettingsIfRequired( Architecture GetDefaultArchitecture(RunConfiguration runConfiguration) { - if (!RunSettingsHelper.Instance.IsDefaultTargetArchitecture) + if (!_runSettingsHelper.IsDefaultTargetArchitecture) { return runConfiguration.TargetPlatform; } diff --git a/test/vstest.console.UnitTests/Processors/CLIRunSettingsArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/CLIRunSettingsArgumentProcessorTests.cs index 08dc751cd2..91a499962b 100644 --- a/test/vstest.console.UnitTests/Processors/CLIRunSettingsArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/CLIRunSettingsArgumentProcessorTests.cs @@ -9,6 +9,8 @@ using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -22,6 +24,7 @@ public class CliRunSettingsArgumentProcessorTests private readonly TestableRunSettingsProvider _settingsProvider; private readonly CliRunSettingsArgumentExecutor _executor; private readonly CommandLineOptions _commandLineOptions; + private readonly IRunSettingsHelper _runSettingsHelper; private readonly string _defaultRunSettings = string.Join(Environment.NewLine, "", "", @@ -56,7 +59,8 @@ public CliRunSettingsArgumentProcessorTests() { _commandLineOptions = CommandLineOptions.Instance; _settingsProvider = new TestableRunSettingsProvider(); - _executor = new CliRunSettingsArgumentExecutor(_settingsProvider, _commandLineOptions); + _runSettingsHelper = new RunSettingsHelper(); + _executor = new CliRunSettingsArgumentExecutor(_settingsProvider, _commandLineOptions, _runSettingsHelper); } [TestCleanup] @@ -68,14 +72,14 @@ public void Cleanup() [TestMethod] public void GetMetadataShouldReturnRunSettingsArgumentProcessorCapabilities() { - var processor = new CliRunSettingsArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new CliRunSettingsArgumentProcessor(new TestableRunSettingsProvider(), _runSettingsHelper); Assert.IsTrue(processor.Metadata.Value is CliRunSettingsArgumentProcessorCapabilities); } [TestMethod] public void GetExecuterShouldReturnRunSettingsArgumentProcessorCapabilities() { - var processor = new CliRunSettingsArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new CliRunSettingsArgumentProcessor(new TestableRunSettingsProvider(), _runSettingsHelper); Assert.IsTrue(processor.Executor!.Value is CliRunSettingsArgumentExecutor); } diff --git a/test/vstest.console.UnitTests/Processors/PlatformArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/PlatformArgumentProcessorTests.cs index ae9ccacd08..22091e8bd2 100644 --- a/test/vstest.console.UnitTests/Processors/PlatformArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/PlatformArgumentProcessorTests.cs @@ -5,6 +5,8 @@ using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using Microsoft.VisualStudio.TestPlatform.Common.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; using vstest.console.UnitTests.Processors; @@ -16,11 +18,13 @@ public class PlatformArgumentProcessorTests { private readonly PlatformArgumentExecutor _executor; private readonly TestableRunSettingsProvider _runSettingsProvider; + private readonly IRunSettingsHelper _runSettingsHelper; public PlatformArgumentProcessorTests() { _runSettingsProvider = new TestableRunSettingsProvider(); - _executor = new PlatformArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider); + _runSettingsHelper = new RunSettingsHelper(); + _executor = new PlatformArgumentExecutor(CommandLineOptions.Instance, _runSettingsProvider, _runSettingsHelper); } [TestCleanup] @@ -32,14 +36,14 @@ public void TestCleanup() [TestMethod] public void GetMetadataShouldReturnPlatformArgumentProcessorCapabilities() { - var processor = new PlatformArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new PlatformArgumentProcessor(new TestableRunSettingsProvider(), _runSettingsHelper); Assert.IsTrue(processor.Metadata.Value is PlatformArgumentProcessorCapabilities); } [TestMethod] public void GetExecuterShouldReturnPlatformArgumentExecutor() { - var processor = new PlatformArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new PlatformArgumentProcessor(new TestableRunSettingsProvider(), _runSettingsHelper); Assert.IsTrue(processor.Executor!.Value is PlatformArgumentExecutor); } diff --git a/test/vstest.console.UnitTests/Processors/PortArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/PortArgumentProcessorTests.cs index 09e78728de..45b694314e 100644 --- a/test/vstest.console.UnitTests/Processors/PortArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/PortArgumentProcessorTests.cs @@ -11,6 +11,8 @@ using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -23,6 +25,7 @@ public class PortArgumentProcessorTests private readonly Mock _mockProcessHelper; private readonly Mock _testDesignModeClient; private readonly Mock _testRequestManager; + private readonly IRunSettingsHelper _runSettingsHelper; private PortArgumentExecutor _executor; public PortArgumentProcessorTests() @@ -30,20 +33,21 @@ public PortArgumentProcessorTests() _mockProcessHelper = new Mock(); _testDesignModeClient = new Mock(); _testRequestManager = new Mock(); - _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object); + _runSettingsHelper = new RunSettingsHelper(); + _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object, _runSettingsHelper); } [TestMethod] public void GetMetadataShouldReturnPortArgumentProcessorCapabilities() { - var processor = new PortArgumentProcessor(); + var processor = new PortArgumentProcessor(_runSettingsHelper); Assert.IsTrue(processor.Metadata.Value is PortArgumentProcessorCapabilities); } [TestMethod] public void GetExecutorShouldReturnPortArgumentProcessorCapabilities() { - var processor = new PortArgumentProcessor(); + var processor = new PortArgumentProcessor(_runSettingsHelper); Assert.IsTrue(processor.Executor!.Value is PortArgumentExecutor); } @@ -102,12 +106,13 @@ public void ExecutorInitializeShouldSetDesignMode() _executor.Initialize(port.ToString(CultureInfo.InvariantCulture)); Assert.IsTrue(CommandLineOptions.Instance.IsDesignMode); + Assert.IsTrue(_runSettingsHelper.IsDesignMode); } [TestMethod] public void ExecutorInitializeShouldSetProcessExitCallback() { - _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object, _mockProcessHelper.Object); + _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object, _mockProcessHelper.Object, _runSettingsHelper); int port = 2345; #if NET5_0_OR_GREATER var pid = Environment.ProcessId; @@ -127,7 +132,7 @@ public void ExecutorInitializeShouldSetProcessExitCallback() public void ExecutorExecuteForValidConnectionReturnsArgumentProcessorResultSuccess() { _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object, - (parentProcessId, ph) => _testDesignModeClient.Object, _mockProcessHelper.Object); + (parentProcessId, ph) => _testDesignModeClient.Object, _mockProcessHelper.Object, _runSettingsHelper); int port = 2345; _executor.Initialize(port.ToString(CultureInfo.InvariantCulture)); @@ -143,7 +148,7 @@ public void ExecutorExecuteForValidConnectionReturnsArgumentProcessorResultSucce public void ExecutorExecuteForFailedConnectionShouldThrowCommandLineException() { _executor = new PortArgumentExecutor(CommandLineOptions.Instance, _testRequestManager.Object, - (parentProcessId, ph) => _testDesignModeClient.Object, _mockProcessHelper.Object); + (parentProcessId, ph) => _testDesignModeClient.Object, _mockProcessHelper.Object, _runSettingsHelper); _testDesignModeClient.Setup(td => td.ConnectToClientAndProcessRequests(It.IsAny(), It.IsAny())).Callback(() => throw new TimeoutException()); @@ -171,7 +176,8 @@ public void ExecutorExecuteSetsParentProcessIdOnDesignModeInitializer() actualParentProcessId = ppid; return _testDesignModeClient.Object; }, - _mockProcessHelper.Object + _mockProcessHelper.Object, + _runSettingsHelper ); int port = 2345; diff --git a/test/vstest.console.UnitTests/Processors/RunSettingsArgumentProcessorTests.cs b/test/vstest.console.UnitTests/Processors/RunSettingsArgumentProcessorTests.cs index 535b6877e4..3067f333a4 100644 --- a/test/vstest.console.UnitTests/Processors/RunSettingsArgumentProcessorTests.cs +++ b/test/vstest.console.UnitTests/Processors/RunSettingsArgumentProcessorTests.cs @@ -12,6 +12,7 @@ using Microsoft.VisualStudio.TestPlatform.Common.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -40,14 +41,14 @@ public void TestCleanup() [TestMethod] public void GetMetadataShouldReturnRunSettingsArgumentProcessorCapabilities() { - var processor = new RunSettingsArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new RunSettingsArgumentProcessor(new TestableRunSettingsProvider(), new RunSettingsHelper()); Assert.IsTrue(processor.Metadata.Value is RunSettingsArgumentProcessorCapabilities); } [TestMethod] public void GetExecuterShouldReturnRunSettingsArgumentExecutor() { - var processor = new RunSettingsArgumentProcessor(new TestableRunSettingsProvider()); + var processor = new RunSettingsArgumentProcessor(new TestableRunSettingsProvider(), new RunSettingsHelper()); Assert.IsTrue(processor.Executor!.Value is RunSettingsArgumentExecutor); } @@ -77,14 +78,14 @@ public void CapabilitiesShouldReturnAppropriateProperties() [TestMethod] public void InitializeShouldThrowExceptionIfArgumentIsNull() { - var ex = Assert.ThrowsExactly(() => new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!).Initialize(null)); + var ex = Assert.ThrowsExactly(() => new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!, new RunSettingsHelper()).Initialize(null)); Assert.Contains("The /Settings parameter requires a settings file to be provided.", ex.Message); } [TestMethod] public void InitializeShouldThrowExceptionIfArgumentIsWhiteSpace() { - var ex = Assert.ThrowsExactly(() => new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!).Initialize(" ")); + var ex = Assert.ThrowsExactly(() => new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!, new RunSettingsHelper()).Initialize(" ")); Assert.Contains("The /Settings parameter requires a settings file to be provided.", ex.Message); } @@ -93,7 +94,7 @@ public void InitializeShouldThrowExceptionIfFileDoesNotExist() { var fileName = "C:\\Imaginary\\nonExistentFile.txt"; - var executor = new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!); + var executor = new RunSettingsArgumentExecutor(CommandLineOptions.Instance, null!, new RunSettingsHelper()); var mockFileHelper = new Mock(); mockFileHelper.Setup(fh => fh.Exists(It.IsAny())).Returns(false); @@ -407,7 +408,7 @@ internal TestableRunSettingsArgumentExecutor( CommandLineOptions commandLineOptions, IRunSettingsProvider runSettingsManager, string? runSettings) - : base(commandLineOptions, runSettingsManager) + : base(commandLineOptions, runSettingsManager, new RunSettingsHelper()) { _runSettingsString = runSettings; diff --git a/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorFactoryTests.cs b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorFactoryTests.cs index 3ce52e3728..6ae5264754 100644 --- a/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorFactoryTests.cs +++ b/test/vstest.console.UnitTests/Processors/Utilities/ArgumentProcessorFactoryTests.cs @@ -8,6 +8,8 @@ using Microsoft.VisualStudio.TestPlatform.CommandLine.Processors; using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -167,11 +169,18 @@ private static IEnumerable GetArgumentProcessors(bool specia foreach (var processor in allProcessors) { - // Some processors require an IRunSettingsProvider via constructor injection; the rest are parameterless. - var runSettingsCtor = processor.GetConstructor([typeof(IRunSettingsProvider)]); - var instance = (runSettingsCtor is not null - ? runSettingsCtor.Invoke([new TestableRunSettingsProvider()]) - : Activator.CreateInstance(processor)) as IArgumentProcessor; + // Processors declare different constructor shapes: some take an IRunSettingsProvider, some take + // an IRunSettingsHelper, some take both, and the rest are parameterless. Pick the matching one. + var runSettingsProvider = new TestableRunSettingsProvider(); + var runSettingsHelper = new RunSettingsHelper(); + + var instance = (processor.GetConstructor([typeof(IRunSettingsProvider), typeof(IRunSettingsHelper)]) is { } providerAndHelperCtor + ? providerAndHelperCtor.Invoke([runSettingsProvider, runSettingsHelper]) + : processor.GetConstructor([typeof(IRunSettingsProvider)]) is { } providerCtor + ? providerCtor.Invoke([runSettingsProvider]) + : processor.GetConstructor([typeof(IRunSettingsHelper)]) is { } helperCtor + ? helperCtor.Invoke([runSettingsHelper]) + : Activator.CreateInstance(processor)) as IArgumentProcessor; Assert.IsNotNull(instance, $"Unable to instantiate processor: {processor}"); var specialProcessor = instance.Metadata.Value.IsSpecialCommand; diff --git a/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs b/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs index b6484c8ebe..5a86330724 100644 --- a/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs +++ b/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs @@ -63,6 +63,7 @@ public class TestRequestManagerTests private readonly Mock _mockAttachmentsProcessingManager; private readonly Mock _mockEnvironment; private readonly Mock _mockEnvironmentVariableHelper; + private readonly IRunSettingsHelper _runSettingsHelper; private const string DefaultRunsettings = @" @@ -85,6 +86,7 @@ public TestRequestManagerTests() _mockProcessHelper = new Mock(); _mockEnvironment = new Mock(); _mockEnvironmentVariableHelper = new Mock(); + _runSettingsHelper = new RunSettingsHelper(); _mockMetricsPublisher = new Mock(); _mockMetricsPublisherTask = Task.FromResult(_mockMetricsPublisher.Object); @@ -99,7 +101,8 @@ public TestRequestManagerTests() _mockProcessHelper.Object, _mockAttachmentsProcessingManager.Object, _mockEnvironment.Object, - _mockEnvironmentVariableHelper.Object); + _mockEnvironmentVariableHelper.Object, + _runSettingsHelper); _mockTestPlatform.Setup(tp => tp.CreateDiscoveryRequest(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) .Returns(_mockDiscoveryRequest.Object); _mockTestPlatform.Setup(tp => tp.CreateTestRunRequest(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny())) @@ -2842,14 +2845,13 @@ private void DiscoverTestsIfThrowsExceptionShouldThrowOut(Exception exception) [DataRow("x86")] [DataRow("x64")] [DataRow("arm64")] - // Don't parallelize because we can run into conflict with GetDefaultArchitecture -> RunSettingsHelper.Instance.IsDefaultTargetArchitecture - // which is set by some other test. - [DoNotParallelize] public void SettingDefaultPlatformUsesItForAnyCPUSourceButNotForNonAnyCPUSource(string defaultPlatform) { // -- Arrange - RunSettingsHelper.Instance.IsDefaultTargetArchitecture = true; + // GetDefaultArchitecture reads IsDefaultTargetArchitecture from the injected IRunSettingsHelper, so we set it + // on that per-test instance rather than the shared RunSettingsHelper.Instance static. That keeps the test isolated. + _runSettingsHelper.IsDefaultTargetArchitecture = true; var payload = new DiscoveryRequestPayload() { Sources = new List() { "AnyCPU.dll", "x64.dll" },