diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/EnvironmentVariableHelper.cs b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/EnvironmentVariableHelper.cs
index 03f14207f3..bc249f5318 100644
--- a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/EnvironmentVariableHelper.cs
+++ b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/EnvironmentVariableHelper.cs
@@ -13,8 +13,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;
internal class EnvironmentVariableHelper : IEnvironmentVariableHelper
{
+ ///
public string GetEnvironmentVariable(string variable)
=> Environment.GetEnvironmentVariable(variable);
+
+ ///
+ public TEnum GetEnvironmentVariableAsEnum(string variable, TEnum defaultValue = default) where TEnum : struct, Enum
+ => Environment.GetEnvironmentVariable(variable) is string value && !string.IsNullOrEmpty(value)
+ ? Enum.TryParse(value, out var enumValue) ? enumValue : defaultValue
+ : defaultValue;
}
#endif
diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IEnvironmentVariableHelper.cs b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IEnvironmentVariableHelper.cs
index c936835a6b..2d7cd021a8 100644
--- a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IEnvironmentVariableHelper.cs
+++ b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/Interfaces/IEnvironmentVariableHelper.cs
@@ -3,9 +3,25 @@
#nullable disable
+using System;
+
namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
internal interface IEnvironmentVariableHelper
{
+ ///
+ /// Retrieves the value of an environment variable from the current process.
+ ///
+ /// The name of the environment variable.
+ /// The value of the environment variable specified by variable, or null if the environment variable is not found.
string GetEnvironmentVariable(string variable);
+
+ ///
+ /// Retrieves the value of an environment variable from the current process and converts it to the given type.
+ ///
+ /// The type used for conversion.
+ /// The name of the environment variable.
+ /// The default value to return if the environment variable is not found.
+ ///
+ TEnum GetEnvironmentVariableAsEnum(string variable, TEnum defaultValue = default) where TEnum : struct, Enum;
}
diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs
index 51e5359e8d..88a4d8b760 100644
--- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs
+++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs
@@ -17,6 +17,7 @@
using Microsoft.TestPlatform.TestHostProvider.Hosting;
using Microsoft.TestPlatform.TestHostProvider.Resources;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions;
+using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Helpers;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Helpers.Interfaces;
using Microsoft.VisualStudio.TestPlatform.DesktopTestHostRuntimeProvider;
@@ -57,6 +58,7 @@ public class DefaultTestHostManager : ITestRuntimeProvider2
private readonly IFileHelper _fileHelper;
private readonly IEnvironment _environment;
private readonly IDotnetHostHelper _dotnetHostHelper;
+ private readonly IEnvironmentVariableHelper _environmentVariableHelper;
private ITestHostLauncher _customTestHostLauncher;
private Process _testHostProcess;
@@ -68,7 +70,12 @@ public class DefaultTestHostManager : ITestRuntimeProvider2
/// Initializes a new instance of the class.
///
public DefaultTestHostManager()
- : this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment(), new DotnetHostHelper())
+ : this(
+ new ProcessHelper(),
+ new FileHelper(),
+ new DotnetHostHelper(),
+ new PlatformEnvironment(),
+ new EnvironmentVariableHelper())
{
}
@@ -79,12 +86,18 @@ public DefaultTestHostManager()
/// File helper instance.
/// Instance of platform environment.
/// Instance of dotnet host helper.
- internal DefaultTestHostManager(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment, IDotnetHostHelper dotnetHostHelper)
+ internal DefaultTestHostManager(
+ IProcessHelper processHelper,
+ IFileHelper fileHelper,
+ IDotnetHostHelper dotnetHostHelper,
+ IEnvironment environment,
+ IEnvironmentVariableHelper environmentVariableHelper)
{
_processHelper = processHelper;
_fileHelper = fileHelper;
- _environment = environment;
_dotnetHostHelper = dotnetHostHelper;
+ _environment = environment;
+ _environmentVariableHelper = environmentVariableHelper;
}
///
@@ -469,8 +482,31 @@ private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToke
_processHelper.SetExitCallback(processId, ExitCallBack);
}
+ if (_testHostProcess is null)
+ {
+ return false;
+ }
+
+ SetProcessPriority(_testHostProcess, _environmentVariableHelper);
OnHostLaunched(new HostProviderEventArgs("Test Runtime launched", 0, _testHostProcess.Id));
- return _testHostProcess != null;
+
+ return true;
+ }
+
+ internal static void SetProcessPriority(Process testHostProcess, IEnvironmentVariableHelper environmentVariableHelper)
+ {
+ ProcessPriorityClass testHostPriority = ProcessPriorityClass.BelowNormal;
+ try
+ {
+ testHostPriority = environmentVariableHelper.GetEnvironmentVariableAsEnum("VSTEST_HOST_INTERNAL_PRIORITY", testHostPriority);
+ testHostProcess.PriorityClass = testHostPriority;
+ EqtTrace.Verbose("Setting test host process priority to {0}", testHostProcess.PriorityClass);
+ }
+ // Setting the process Priority can fail with Win32Exception, NotSupportedException or InvalidOperationException.
+ catch (Exception ex)
+ {
+ EqtTrace.Error("Failed to set test host process priority to {0}. Exception: {1}", testHostPriority, ex);
+ }
}
private string GetUwpSources(string uwpSource)
diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
index 48f0cd64d8..34c4515d10 100644
--- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
+++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
@@ -688,9 +688,14 @@ private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToke
_processHelper.SetExitCallback(processId, ExitCallBack);
}
- OnHostLaunched(new HostProviderEventArgs("Test Runtime launched", 0, _testHostProcess.Id));
+ if (_testHostProcess is null)
+ {
+ return false;
+ }
- return _testHostProcess != null;
+ DefaultTestHostManager.SetProcessPriority(_testHostProcess, _environmentVariableHelper);
+ OnHostLaunched(new HostProviderEventArgs("Test Runtime launched", 0, _testHostProcess.Id));
+ return true;
}
private string GetTestHostPath(string runtimeConfigDevPath, string depsFilePath, string sourceDirectory)
diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs
index fed025f0c3..d66173a26c 100644
--- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs
+++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs
@@ -12,6 +12,7 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions;
+using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Helpers;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Helpers.Interfaces;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Hosting;
@@ -39,6 +40,7 @@ public class DefaultTestHostManagerTests
private readonly Mock _mockFileHelper;
private readonly Mock _mockDotnetHostHelper;
private readonly Mock _mockEnvironment;
+ private readonly Mock _mockEnvironmentVariable;
private readonly DefaultTestHostManager _testHostManager;
private TestableTestHostManager? _testableTestHostManager;
@@ -53,10 +55,11 @@ public DefaultTestHostManagerTests()
_mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns("vstest.console.exe");
_mockDotnetHostHelper = new Mock();
_mockEnvironment = new Mock();
+ _mockEnvironmentVariable = new Mock();
_mockMessageLogger = new Mock();
- _testHostManager = new DefaultTestHostManager(_mockProcessHelper.Object, _mockFileHelper.Object, _mockEnvironment.Object, _mockDotnetHostHelper.Object);
+ _testHostManager = new DefaultTestHostManager(_mockProcessHelper.Object, _mockFileHelper.Object, _mockDotnetHostHelper.Object, _mockEnvironment.Object, _mockEnvironmentVariable.Object);
_testHostManager.Initialize(_mockMessageLogger.Object, $" {Architecture.X64} {Framework.DefaultFramework} {false} ");
_startInfo = _testHostManager.GetTestHostProcessStartInfo(Enumerable.Empty(), null, default);
}
@@ -592,7 +595,7 @@ public TestableTestHostManager(
IProcessHelper processHelper,
bool shared,
IMessageLogger logger)
- : base(processHelper, new FileHelper(), new PlatformEnvironment(), new DotnetHostHelper())
+ : base(processHelper, new FileHelper(), new DotnetHostHelper(), new PlatformEnvironment(), new EnvironmentVariableHelper())
{
Initialize(logger, $" {architecture} {framework} {!shared} ");
}