diff --git a/scripts/build.ps1 b/scripts/build.ps1
index ee4471e121..9dff0a63d5 100644
--- a/scripts/build.ps1
+++ b/scripts/build.ps1
@@ -95,6 +95,9 @@ $TPB_TargetFrameworkUap = "uap10.0"
$TPB_TargetFrameworkNS2_0 = "netstandard2.0"
$TPB_Configuration = $Configuration
$TPB_TargetRuntime = $TargetRuntime
+$TPB_X64_Runtime = "win7-x64"
+$TPB_X86_Runtime = "win7-x86"
+
# Version suffix is empty for RTM releases
$TPB_Version = if ($VersionSuffix -ne '') { $Version + "-" + $VersionSuffix } else { $Version }
$TPB_CIBuild = $CIBuild
@@ -223,6 +226,8 @@ function Publish-Package
$testHostx86Project = Join-Path $env:TP_ROOT_DIR "src\testhost.x86\testhost.x86.csproj"
$testhostFullPackageDir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFramework\$TPB_TargetRuntime")
$testhostCorePackageDir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkCore20")
+ $testhostCorePackageX64Dir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkCore20\$TPB_X64_Runtime")
+ $testhostCorePackageX86Dir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkCore20\$TPB_X86_Runtime")
$testhostUapPackageDir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkUap")
$vstestConsoleProject = Join-Path $env:TP_ROOT_DIR "src\vstest.console\vstest.console.csproj"
$settingsMigratorProject = Join-Path $env:TP_ROOT_DIR "src\SettingsMigrator\SettingsMigrator.csproj"
@@ -252,10 +257,12 @@ function Publish-Package
Publish-PackageInternal $testHostProject $TPB_TargetFramework $testhostFullPackageDir
Publish-PackageInternal $testHostProject $TPB_TargetFrameworkCore20 $testhostCorePackageDir
Publish-PackageInternal $testHostProject $TPB_TargetFrameworkCore20 $testhostUapPackageDir
+ Publish-PackageWithRuntimeInternal $testHostProject $TPB_TargetFrameworkCore20 $TPB_X64_Runtime false $testhostCorePackageX64Dir
Write-Log "Package: Publish testhost.x86\testhost.x86.csproj"
- Publish-PackageInternal $testHostx86Project $TPB_TargetFramework $testhostFullPackageDir
-
+ Publish-PackageInternal $testHostx86Project $TPB_TargetFramework $testhostFullPackageDir
+ Publish-PackageWithRuntimeInternal $testHostx86Project $TPB_TargetFrameworkCore20 $TPB_X86_Runtime false $testhostCorePackageX86Dir
+
# Copy over the Full CLR built testhost package assemblies to the Core CLR and Full CLR package folder.
$coreCLRFull_Dir = "TestHost"
$fullDestDir = Join-Path $coreCLR20PackageDir $coreCLRFull_Dir
@@ -292,6 +299,7 @@ function Publish-Package
$extensions_Dir = "Extensions"
$fullCLRExtensionsDir = Join-Path $fullCLRPackageDir $extensions_Dir
$coreCLRExtensionsDir = Join-Path $coreCLR20PackageDir $extensions_Dir
+
# Create an extensions directory.
New-Item -ItemType directory -Path $fullCLRExtensionsDir -Force | Out-Null
New-Item -ItemType directory -Path $coreCLRExtensionsDir -Force | Out-Null
@@ -437,6 +445,14 @@ function Publish-PackageInternal($packagename, $framework, $output)
Set-ScriptFailedOnError
}
+function Publish-PackageWithRuntimeInternal($packagename, $framework, $runtime, $selfcontained, $output)
+{
+ Write-Verbose "$dotnetExe publish $packagename --configuration $TPB_Configuration --framework $framework --runtime $runtime --output $output -v:minimal -p:Version=$TPB_Version -p:CIBuild=$TPB_CIBuild -p:LocalizedBuild=$TPB_LocalizedBuild"
+ & $dotnetExe publish $packagename --configuration $TPB_Configuration --framework $framework --runtime $runtime --self-contained $selfcontained --output $output -v:minimal -p:Version=$TPB_Version -p:CIBuild=$TPB_CIBuild -p:LocalizedBuild=$TPB_LocalizedBuild
+
+ Set-ScriptFailedOnError
+}
+
function Copy-Loc-Files($sourceDir, $destinationDir, $dllName)
{
foreach($lang in $language) {
@@ -582,7 +598,10 @@ function Create-NugetPackages
$testhostUapPackageDir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkUap")
Copy-Item $tpNuspecDir\uap\"Microsoft.TestPlatform.TestHost.Uap.props" $testhostUapPackageDir\Microsoft.TestPlatform.TestHost.props -Force
Copy-Item $tpNuspecDir\uap\"Microsoft.TestPlatform.TestHost.Uap.targets" $testhostUapPackageDir\Microsoft.TestPlatform.TestHost.targets -Force
-
+
+ $testhostCorePackageDir = $(Join-Path $env:TP_OUT_DIR "$TPB_Configuration\Microsoft.TestPlatform.TestHost\$TPB_TargetFrameworkCore20")
+ Copy-Item $tpNuspecDir\"Microsoft.TestPlatform.TestHost.NetCore.props" $testhostCorePackageDir\Microsoft.TestPlatform.TestHost.props -Force
+
# Call nuget pack on these components.
$nugetExe = Join-Path $env:TP_PACKAGES_DIR -ChildPath "Nuget.CommandLine" | Join-Path -ChildPath $env:NUGET_EXE_Version | Join-Path -ChildPath "tools\NuGet.exe"
diff --git a/scripts/verify-nupkgs.ps1 b/scripts/verify-nupkgs.ps1
index b002ab1610..8eb5d9adaa 100644
--- a/scripts/verify-nupkgs.ps1
+++ b/scripts/verify-nupkgs.ps1
@@ -20,7 +20,7 @@ function Verify-Nuget-Packages($packageDirectory)
"Microsoft.TestPlatform.Extensions.TrxLogger" = 33;
"Microsoft.TestPlatform.ObjectModel" = 62;
"Microsoft.TestPlatform.Portable" = 502;
- "Microsoft.TestPlatform.TestHost" = 140;
+ "Microsoft.TestPlatform.TestHost" = 145;
"Microsoft.TestPlatform.TranslationLayer" = 121}
$nugetPackages = Get-ChildItem -Filter "*.nupkg" $packageDirectory | % { $_.FullName}
diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj
index 83aae901cf..e112259a49 100644
--- a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj
+++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj
@@ -10,6 +10,7 @@
netstandard2.0;netcoreapp2.1
false
true
+ NU1605
diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
index 3391e9ea97..0492b8eed8 100644
--- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
+++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs
@@ -48,7 +48,7 @@ public class DotnetTestHostManager : ITestRuntimeProvider
private const string DataCollectorRegexPattern = @"Collector.dll";
private IDotnetHostHelper dotnetHostHelper;
-
+ private IEnvironment platformEnvironment;
private IProcessHelper processHelper;
private IFileHelper fileHelper;
@@ -65,11 +65,13 @@ public class DotnetTestHostManager : ITestRuntimeProvider
private string hostPackageVersion = "15.0.0";
+ private Architecture architecture;
+
///
/// Initializes a new instance of the class.
///
public DotnetTestHostManager()
- : this(new ProcessHelper(), new FileHelper(), new DotnetHostHelper())
+ : this(new ProcessHelper(), new FileHelper(), new DotnetHostHelper(), new PlatformEnvironment())
{
}
@@ -79,14 +81,17 @@ public DotnetTestHostManager()
/// Process helper instance.
/// File helper instance.
/// DotnetHostHelper helper instance.
+ /// Platform Environment
internal DotnetTestHostManager(
IProcessHelper processHelper,
IFileHelper fileHelper,
- IDotnetHostHelper dotnetHostHelper)
+ IDotnetHostHelper dotnetHostHelper,
+ IEnvironment platformEnvironment)
{
this.processHelper = processHelper;
this.fileHelper = fileHelper;
this.dotnetHostHelper = dotnetHostHelper;
+ this.platformEnvironment = platformEnvironment;
}
///
@@ -135,6 +140,9 @@ public void Initialize(IMessageLogger logger, string runsettingsXml)
{
this.messageLogger = logger;
this.hostExitedEventRaised = false;
+
+ var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runsettingsXml);
+ this.architecture = runConfiguration.TargetPlatform;
}
///
@@ -163,25 +171,8 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo(
{
var startInfo = new TestProcessStartInfo();
- var currentProcessPath = this.processHelper.GetCurrentProcessFileName();
-
- // This host manager can create process start info for dotnet core targets only.
- // If already running with the dotnet executable, use it; otherwise pick up the dotnet available on path.
- // Wrap the paths with quotes in case dotnet executable is installed on a path with whitespace.
- if (currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase)
- || currentProcessPath.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase))
- {
- startInfo.FileName = currentProcessPath;
- }
- else
- {
- startInfo.FileName = this.dotnetHostHelper.GetDotnetPath();
- }
-
- EqtTrace.Verbose("DotnetTestHostmanager: Full path of dotnet.exe is {0}", startInfo.FileName);
-
// .NET core host manager is not a shared host. It will expect a single test source to be provided.
- var args = "exec";
+ var args = string.Empty;
var sourcePath = sources.Single();
var sourceFile = Path.GetFileNameWithoutExtension(sourcePath);
var sourceDirectory = Path.GetDirectoryName(sourcePath);
@@ -212,11 +203,41 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo(
EqtTrace.Verbose("DotnetTestHostmanager: File {0}, doesnot exist", depsFilePath);
}
- var runtimeConfigDevPath = Path.Combine(sourceDirectory, string.Concat(sourceFile, ".runtimeconfig.dev.json"));
- var testHostPath = this.GetTestHostPath(runtimeConfigDevPath, depsFilePath, sourceDirectory);
+ // If Testhost.exe is available use it
+ var exeName = this.architecture == Architecture.X86 ? "testhost.x86.exe" : "testhost.exe";
+ var fullExePath = Path.Combine(sourceDirectory, exeName);
+ if (this.platformEnvironment.OperatingSystem.Equals(PlatformOperatingSystem.Windows) && this.fileHelper.Exists(fullExePath))
+ {
+ startInfo.FileName = fullExePath;
+ }
+ else
+ {
+ var currentProcessPath = this.processHelper.GetCurrentProcessFileName();
+
+ // This host manager can create process start info for dotnet core targets only.
+ // If already running with the dotnet executable, use it; otherwise pick up the dotnet available on path.
+ // Wrap the paths with quotes in case dotnet executable is installed on a path with whitespace.
+ if (currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase)
+ || currentProcessPath.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase))
+ {
+ startInfo.FileName = currentProcessPath;
+ }
+ else
+ {
+ startInfo.FileName = this.dotnetHostHelper.GetDotnetPath();
+ }
+
+ var runtimeConfigDevPath = Path.Combine(sourceDirectory, string.Concat(sourceFile, ".runtimeconfig.dev.json"));
+ var testHostPath = this.GetTestHostPath(runtimeConfigDevPath, depsFilePath, sourceDirectory);
+
+ EqtTrace.Verbose("DotnetTestHostmanager: Full path of testhost.dll is {0}", testHostPath);
+ args = "exec" + args;
+ args += " " + testHostPath.AddDoubleQuote();
+ }
+
+ EqtTrace.Verbose("DotnetTestHostmanager: Full path of host exe is {0}", startInfo.FileName);
- EqtTrace.Verbose("DotnetTestHostmanager: Full path of testhost.dll is {0}", testHostPath);
- args += " " + testHostPath.AddDoubleQuote() + " " + connectionInfo.ToCommandLineOptions();
+ args += " " + connectionInfo.ToCommandLineOptions();
// Create a additional probing path args with Nuget.Client
// args += "--additionalprobingpath xxx"
diff --git a/src/package/nuspec/Microsoft.TestPlatform.TestHost.NetCore.props b/src/package/nuspec/Microsoft.TestPlatform.TestHost.NetCore.props
new file mode 100644
index 0000000000..fd9adc4d16
--- /dev/null
+++ b/src/package/nuspec/Microsoft.TestPlatform.TestHost.NetCore.props
@@ -0,0 +1,27 @@
+
+
+
+
+ testhost.x86.exe
+ PreserveNewest
+ False
+
+
+ testhost.x86.dll
+ PreserveNewest
+ False
+
+
+
+
+ testhost.exe
+ PreserveNewest
+ False
+
+
+ testhost.dll
+ PreserveNewest
+ False
+
+
+
\ No newline at end of file
diff --git a/src/package/nuspec/TestPlatform.TestHost.nuspec b/src/package/nuspec/TestPlatform.TestHost.nuspec
index 51b7d05eb9..d2f1343ff5 100644
--- a/src/package/nuspec/TestPlatform.TestHost.nuspec
+++ b/src/package/nuspec/TestPlatform.TestHost.nuspec
@@ -1,4 +1,4 @@
-
+
Microsoft.TestPlatform.TestHost
@@ -41,7 +41,14 @@
-
+
+
+
+
+
+
+
+
diff --git a/src/testhost.x86/testhost.x86.csproj b/src/testhost.x86/testhost.x86.csproj
index 86de0abf0e..d35578cbfb 100644
--- a/src/testhost.x86/testhost.x86.csproj
+++ b/src/testhost.x86/testhost.x86.csproj
@@ -13,8 +13,6 @@
true
Exe
app.manifest
-
-
win7-x86
false
diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs
index 8a5a634f0f..1f6f8ed63a 100644
--- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs
+++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs
@@ -528,7 +528,7 @@ public TestableDotnetTestHostManager(
bool checkRequired,
IProcessHelper processHelper,
IFileHelper fileHelper,
- IEnvironment environment) : base(processHelper, fileHelper, new DotnetHostHelper(fileHelper, environment))
+ IEnvironment environment) : base(processHelper, fileHelper, new DotnetHostHelper(fileHelper, environment), environment)
{
this.isVersionCheckRequired = checkRequired;
}
diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs
index b0476e0893..fc3e857c9d 100644
--- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs
+++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs
@@ -19,6 +19,7 @@ namespace TestPlatform.TestHostProvider.UnitTests.Hosting
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
+ using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions;
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -39,6 +40,8 @@ public class DotnetTestHostManagerTests
private readonly Mock mockMessageLogger;
+ private readonly Mock mockEnvironment;
+
private readonly TestRunnerConnectionInfo defaultConnectionInfo;
private readonly string[] testSource = { "test.dll" };
@@ -60,7 +63,7 @@ public DotnetTestHostManagerTests()
this.mockProcessHelper = new Mock();
this.mockFileHelper = new Mock();
this.mockMessageLogger = new Mock();
- var mockEnvironment = new Mock();
+ this.mockEnvironment = new Mock();
this.defaultConnectionInfo = new TestRunnerConnectionInfo { Port = 123, ConnectionInfo = new TestHostConnectionInfo { Endpoint = "127.0.0.1:123", Role = ConnectionRole.Client }, RunnerProcessId = 0 };
string defaultSourcePath = Path.Combine($"{Path.DirectorySeparatorChar}tmp", "test.dll");
@@ -68,7 +71,8 @@ public DotnetTestHostManagerTests()
this.dotnetHostManager = new TestableDotnetTestHostManager(
this.mockProcessHelper.Object,
this.mockFileHelper.Object,
- new DotnetHostHelper(this.mockFileHelper.Object, mockEnvironment.Object));
+ new DotnetHostHelper(this.mockFileHelper.Object, this.mockEnvironment.Object),
+ this.mockEnvironment.Object);
this.dotnetHostManager.Initialize(this.mockMessageLogger.Object, string.Empty);
this.dotnetHostManager.HostExited += this.DotnetHostManagerHostExited;
@@ -235,6 +239,43 @@ public void GetTestHostProcessStartIfRuntimeConfigAndDepsFilePresentAndTestHostN
Assert.AreEqual(ex.Message, "Unable to find testhost.dll. Please publish your test project and retry.");
}
+ [TestMethod]
+ public void GetTestHostProcessStartInfoShouldUseTestHostX86ExePresentOnWindows()
+ {
+ var testhostExePath = "testhost.x86.exe";
+ this.mockFileHelper.Setup(ph => ph.Exists(testhostExePath)).Returns(true);
+ this.mockEnvironment.Setup(ev => ev.OperatingSystem).Returns(PlatformOperatingSystem.Windows);
+
+ var startInfo = this.GetDefaultStartInfo();
+
+ StringAssert.Contains(startInfo.FileName, testhostExePath);
+ }
+
+ [TestMethod]
+ public void GetTestHostProcessStartInfoShouldUseDotnetExeOnUnix()
+ {
+ this.mockFileHelper.Setup(ph => ph.Exists("testhost.x86.exe")).Returns(true);
+ this.mockFileHelper.Setup(ph => ph.Exists("testhost.dll")).Returns(true);
+ this.mockEnvironment.Setup(ev => ev.OperatingSystem).Returns(PlatformOperatingSystem.Unix);
+
+ var startInfo = this.GetDefaultStartInfo();
+
+ StringAssert.Contains(startInfo.FileName, "dotnet");
+ }
+
+ [TestMethod]
+ public void GetTestHostProcessStartInfoShouldUseTestHostExeIsPresentOnWindows()
+ {
+ var testhostExePath = "testhost.exe";
+ this.mockFileHelper.Setup(ph => ph.Exists(testhostExePath)).Returns(true);
+ this.mockEnvironment.Setup(ev => ev.OperatingSystem).Returns(PlatformOperatingSystem.Windows);
+
+ this.dotnetHostManager.Initialize(this.mockMessageLogger.Object, "x64");
+ var startInfo = this.GetDefaultStartInfo();
+
+ StringAssert.Contains(startInfo.FileName, testhostExePath);
+ }
+
[TestMethod]
public void LaunchTestHostShouldLaunchProcessWithNullEnvironmentVariablesOrArgs()
{
@@ -806,8 +847,9 @@ internal class TestableDotnetTestHostManager : DotnetTestHostManager
public TestableDotnetTestHostManager(
IProcessHelper processHelper,
IFileHelper fileHelper,
- IDotnetHostHelper dotnetTestHostHelper)
- : base(processHelper, fileHelper, dotnetTestHostHelper)
+ IDotnetHostHelper dotnetTestHostHelper,
+ IEnvironment environment)
+ : base(processHelper, fileHelper, dotnetTestHostHelper, environment)
{
}
}