diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs index 5e61617f1a..08a2a113d5 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/TestEngine.cs @@ -35,25 +35,31 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine; public class TestEngine : ITestEngine { private readonly ITestRuntimeProviderManager _testHostProviderManager; - private ITestExtensionManager _testExtensionManager; private readonly IProcessHelper _processHelper; + private readonly IEnvironment _environment; + + private ITestExtensionManager _testExtensionManager; - public TestEngine() : this(TestRuntimeProviderManager.Instance, new ProcessHelper()) + public TestEngine() + : this(TestRuntimeProviderManager.Instance, new ProcessHelper()) { } protected internal TestEngine( TestRuntimeProviderManager testHostProviderManager, - IProcessHelper processHelper) : this((ITestRuntimeProviderManager)testHostProviderManager, processHelper) + IProcessHelper processHelper) + : this(testHostProviderManager, processHelper, new PlatformEnvironment()) { } internal TestEngine( ITestRuntimeProviderManager testHostProviderManager, - IProcessHelper processHelper) + IProcessHelper processHelper, + IEnvironment environment) { _testHostProviderManager = testHostProviderManager; _processHelper = processHelper; + _environment = environment; } #region ITestEngine implementation @@ -492,15 +498,21 @@ private int VerifyParallelSettingAndCalculateParallelLevel( // Check the user parallel setting. int userParallelSetting = RunSettingsUtilities.GetMaxCpuCount(runSettings); parallelLevelToUse = userParallelSetting == 0 - // TODO: use environment helper so we can control this from tests. - ? Environment.ProcessorCount + ? _environment.ProcessorCount : userParallelSetting; - var enableParallel = parallelLevelToUse > 1; EqtTrace.Verbose( "TestEngine: Initializing Parallel Execution as MaxCpuCount is set to: {0}", parallelLevelToUse); + // TODO: EXPERIMENTAL FEATURE - will need to be removed or strengthen/tested. + // A negative value is used to indicate that the value should be used as a percentage of the number of cores. + if (parallelLevelToUse < 0) + { + parallelLevelToUse = (int)Math.Max(1, Math.Round((double)-parallelLevelToUse * _environment.ProcessorCount / 100.0, MidpointRounding.AwayFromZero)); + } + + var enableParallel = parallelLevelToUse > 1; // Verify if the number of sources is less than user setting of parallel. // We should use number of sources as the parallel level, if sources count is less // than parallel level. diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IEnvironment.cs index 6e3e745cb1..7af77732e5 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Interfaces/System/IEnvironment.cs @@ -34,4 +34,7 @@ public interface IEnvironment /// /// Returns the thread Id int GetCurrentManagedThreadId(); + + /// + int ProcessorCount { get; } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/PublicAPI/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.PlatformAbstractions/PublicAPI/PublicAPI.Shipped.txt index 9a6ec487a0..759b9e899a 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/PublicAPI/PublicAPI.Shipped.txt +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/PublicAPI/PublicAPI.Shipped.txt @@ -36,6 +36,7 @@ Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IAssemblyRes Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IAssemblyResolver.AssemblyResolve -> Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.AssemblyResolveEventHandler? Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment.Architecture.get -> Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformArchitecture +Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment.ProcessorCount.get -> int Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment.Exit(int exitcode) -> void Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment.GetCurrentManagedThreadId() -> int Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces.IEnvironment.OperatingSystem.get -> Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformOperatingSystem @@ -79,6 +80,7 @@ Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformAssemblyResolve Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformAssemblyResolver.PlatformAssemblyResolver() -> void Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment.Architecture.get -> Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformArchitecture +Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment.ProcessorCount.get -> int Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment.Exit(int exitcode) -> void Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment.GetCurrentManagedThreadId() -> int Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformEnvironment.OperatingSystem.get -> Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformOperatingSystem diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/PlatformEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/PlatformEnvironment.cs index 202263d19f..09fb1ea528 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/PlatformEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/PlatformEnvironment.cs @@ -73,6 +73,9 @@ public PlatformOperatingSystem OperatingSystem /// public string OperatingSystemVersion => Environment.OSVersion.ToString(); + /// + public int ProcessorCount => Environment.ProcessorCount; + /// public void Exit(int exitcode) { diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/PlatformEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/PlatformEnvironment.cs index 61e73c0455..10d4a61570 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/PlatformEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/PlatformEnvironment.cs @@ -56,6 +56,9 @@ public string OperatingSystemVersion } } + /// + public int ProcessorCount => Environment.ProcessorCount; + /// public void Exit(int exitcode) { diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/System/PlatformEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/System/PlatformEnvironment.cs index 61d274b2bd..377cf4b4d4 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/System/PlatformEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/System/PlatformEnvironment.cs @@ -39,6 +39,9 @@ public string OperatingSystemVersion } } + /// + public int ProcessorCount => throw new NotImplementedException(); + /// public void Exit(int exitcode) { diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/PlatformEnvironment.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/PlatformEnvironment.cs index 3be2617a80..9c53b9b678 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/PlatformEnvironment.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/uap10.0/System/PlatformEnvironment.cs @@ -33,6 +33,9 @@ public PlatformOperatingSystem OperatingSystem /// public string OperatingSystemVersion => RuntimeInformation.OSDescription; + /// + public int ProcessorCount => Environment.ProcessorCount; + /// public void Exit(int exitcode) { diff --git a/test/vstest.ProgrammerTests/Fakes/FakeEnvironment.cs b/test/vstest.ProgrammerTests/Fakes/FakeEnvironment.cs index ea82d8501b..415c42f5b9 100644 --- a/test/vstest.ProgrammerTests/Fakes/FakeEnvironment.cs +++ b/test/vstest.ProgrammerTests/Fakes/FakeEnvironment.cs @@ -16,6 +16,8 @@ internal class FakeEnvironment : IEnvironment public string OperatingSystemVersion => _environment.OperatingSystemVersion; + public int ProcessorCount => _environment.ProcessorCount; + public void Exit(int exitcode) => _environment.Exit(exitcode); public int GetCurrentManagedThreadId() => _environment.GetCurrentManagedThreadId(); diff --git a/test/vstest.ProgrammerTests/Fakes/Fixture.cs b/test/vstest.ProgrammerTests/Fakes/Fixture.cs index 60a38bfc35..afddd891d9 100644 --- a/test/vstest.ProgrammerTests/Fakes/Fixture.cs +++ b/test/vstest.ProgrammerTests/Fakes/Fixture.cs @@ -107,7 +107,7 @@ internal TestRequestManagerTestHelper BuildTestRequestManager( throw new InvalidOperationException("There are runtime providers registered for FakeTestRuntimeProviderManager."); - TestEngine = new TestEngine(TestRuntimeProviderManager, ProcessHelper); + TestEngine = new TestEngine(TestRuntimeProviderManager, ProcessHelper, Environment); TestPlatform = new TestPlatform(TestEngine, FileHelper, TestRuntimeProviderManager); TestRunResultAggregator = new TestRunResultAggregator();