Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add env var to control host priority #3740

Merged
merged 3 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;

internal class EnvironmentVariableHelper : IEnvironmentVariableHelper
{
/// <inheritdoc />
public string GetEnvironmentVariable(string variable)
=> Environment.GetEnvironmentVariable(variable);

/// <inheritdoc />
public TEnum GetEnvironmentVariableAsEnum<TEnum>(string variable, TEnum defaultValue = default) where TEnum : struct, Enum
=> Environment.GetEnvironmentVariable(variable) is string value && !string.IsNullOrEmpty(value)
? Enum.TryParse<TEnum>(value, out var enumValue) ? enumValue : defaultValue
: defaultValue;
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@

#nullable disable

using System;

namespace Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

internal interface IEnvironmentVariableHelper
{
/// <summary>
/// Retrieves the value of an environment variable from the current process.
/// </summary>
/// <param name="variable">The name of the environment variable.</param>
/// <returns>The value of the environment variable specified by variable, or null if the environment variable is not found.</returns>
string GetEnvironmentVariable(string variable);

/// <summary>
/// Retrieves the value of an environment variable from the current process and converts it to the given type.
/// </summary>
/// <typeparam name="TEnum">The type used for conversion.</typeparam>
/// <param name="variable">The name of the environment variable.</param>
/// <param name="defaultValue">The default value to return if the environment variable is not found.</param>
/// <returns></returns>
TEnum GetEnvironmentVariableAsEnum<TEnum>(string variable, TEnum defaultValue = default) where TEnum : struct, Enum;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -68,7 +70,12 @@ public class DefaultTestHostManager : ITestRuntimeProvider2
/// Initializes a new instance of the <see cref="DefaultTestHostManager"/> class.
/// </summary>
public DefaultTestHostManager()
: this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment(), new DotnetHostHelper())
: this(
new ProcessHelper(),
new FileHelper(),
new DotnetHostHelper(),
new PlatformEnvironment(),
new EnvironmentVariableHelper())
{
}

Expand All @@ -79,12 +86,18 @@ public DefaultTestHostManager()
/// <param name="fileHelper">File helper instance.</param>
/// <param name="environment">Instance of platform environment.</param>
/// <param name="dotnetHostHelper">Instance of dotnet host helper.</param>
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;
}

/// <inheritdoc/>
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -39,6 +40,7 @@ public class DefaultTestHostManagerTests
private readonly Mock<IFileHelper> _mockFileHelper;
private readonly Mock<IDotnetHostHelper> _mockDotnetHostHelper;
private readonly Mock<IEnvironment> _mockEnvironment;
private readonly Mock<IEnvironmentVariableHelper> _mockEnvironmentVariable;
private readonly DefaultTestHostManager _testHostManager;

private TestableTestHostManager? _testableTestHostManager;
Expand All @@ -53,10 +55,11 @@ public DefaultTestHostManagerTests()
_mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns("vstest.console.exe");
_mockDotnetHostHelper = new Mock<IDotnetHostHelper>();
_mockEnvironment = new Mock<IEnvironment>();
_mockEnvironmentVariable = new Mock<IEnvironmentVariableHelper>();

_mockMessageLogger = new Mock<IMessageLogger>();

_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, $"<?xml version=\"1.0\" encoding=\"utf-8\"?><RunSettings> <RunConfiguration> <TargetPlatform>{Architecture.X64}</TargetPlatform> <TargetFrameworkVersion>{Framework.DefaultFramework}</TargetFrameworkVersion> <DisableAppDomain>{false}</DisableAppDomain> </RunConfiguration> </RunSettings>");
_startInfo = _testHostManager.GetTestHostProcessStartInfo(Enumerable.Empty<string>(), null, default);
}
Expand Down Expand Up @@ -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, $"<?xml version=\"1.0\" encoding=\"utf-8\"?><RunSettings> <RunConfiguration> <TargetPlatform>{architecture}</TargetPlatform> <TargetFrameworkVersion>{framework}</TargetFrameworkVersion> <DisableAppDomain>{!shared}</DisableAppDomain> </RunConfiguration> </RunSettings>");
}
Expand Down