diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/DotnetHostHelper.cs b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/DotnetHostHelper.cs index 6c9efbd274..613c9a7cb6 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Helpers/DotnetHostHelper.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Helpers/DotnetHostHelper.cs @@ -119,7 +119,7 @@ private bool TryGetExecutablePath(string executableBaseName, out string executab public bool TryGetDotnetPathByArchitecture(PlatformArchitecture targetArchitecture, out string muxerPath) { - if (this.environment.Architecture == targetArchitecture) + if (this.processHelper.GetCurrentProcessArchitecture() == targetArchitecture) { string currentProcessFileName = this.processHelper.GetCurrentProcessFileName(); if (Path.GetFileName(currentProcessFileName) != this.muxerName) diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/common/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/common/System/ProcessHelper.cs index a020deb376..64070fddb5 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/common/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/common/System/ProcessHelper.cs @@ -186,17 +186,6 @@ public int GetProcessId(object process) return proc?.Id ?? -1; } - /// - public PlatformArchitecture GetCurrentProcessArchitecture() - { - if (IntPtr.Size == 8) - { - return PlatformArchitecture.X64; - } - - return PlatformArchitecture.X86; - } - /// public string GetNativeDllDirectory() { diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs index 8093a753ac..bbe8abb06d 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/net451/System/ProcessHelper.cs @@ -23,6 +23,17 @@ public IntPtr GetProcessHandle(int processId) { return Process.GetProcessById(processId).Handle; } + + /// + public PlatformArchitecture GetCurrentProcessArchitecture() + { + if (IntPtr.Size == 8) + { + return PlatformArchitecture.X64; + } + + return PlatformArchitecture.X86; + } } } diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs index 74d6cb45a2..a952145341 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netcore/System/ProcessHelper.cs @@ -9,6 +9,7 @@ namespace Microsoft.VisualStudio.TestPlatform.PlatformAbstractions using System.Diagnostics; using System.IO; using System.Reflection; + using System.Runtime.InteropServices; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; public partial class ProcessHelper : IProcessHelper @@ -26,6 +27,29 @@ public IntPtr GetProcessHandle(int processId) // If the handle has been marked invalid with SetHandleAsInvalid, this method still returns the original handle value, which can be a stale value. return Process.GetProcessById(processId).SafeHandle.DangerousGetHandle(); } + + public PlatformArchitecture GetCurrentProcessArchitecture() + { + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.X86: + return PlatformArchitecture.X86; + case Architecture.X64: + return PlatformArchitecture.X64; + case Architecture.Arm: + return PlatformArchitecture.ARM; + case Architecture.Arm64: + return PlatformArchitecture.ARM64; + + // The symbolic value is only available with .NET 6 + // preview 6 or later, so use the numerical value for now. + // case System.Runtime.InteropServices.Architecture.S390x: + case (Architecture)5: + return PlatformArchitecture.S390x; + default: + throw new NotSupportedException(); + } + } } } diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index e9cb3c90f9..caa1eeb0b1 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -406,7 +406,8 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( // We silently force x64 only if the target architecture is the default one and is not specified by user // through --arch or runsettings or -- RunConfiguration.TargetPlatform=arch bool forceToX64 = SilentlyForceToX64() && this.runsettingHelper.IsDefaultTargetArchitecture; - bool isSameArchitecture = IsSameArchitecture(this.architecture, this.platformEnvironment.Architecture); + EqtTrace.Verbose($"DotnetTestHostmanager: Current process architetcure '{this.processHelper.GetCurrentProcessArchitecture()}'"); + bool isSameArchitecture = IsSameArchitecture(this.architecture, this.processHelper.GetCurrentProcessArchitecture()); var currentProcessPath = this.processHelper.GetCurrentProcessFileName(); bool isRunningWithDotnetMuxer = IsRunningWithDotnetMuxer(currentProcessPath); if (useCustomDotnetHostpath) @@ -423,10 +424,10 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( else { PlatformArchitecture targetArchitecture = TranslateToPlatformArchitecture(this.architecture); - EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Searching muxer for the architecture '{targetArchitecture}', OS '{this.platformEnvironment.OperatingSystem}' framework '{this.targetFramework}' SDK platform architecture '{this.platformEnvironment.Architecture}'"); + EqtTrace.Verbose($"DotnetTestHostmanager: Searching muxer for the architecture '{targetArchitecture}', OS '{this.platformEnvironment.OperatingSystem}' framework '{this.targetFramework}' SDK platform architecture '{this.platformEnvironment.Architecture}'"); if (forceToX64) { - EqtTrace.Verbose($"DotnetTestHostmanager.LaunchTestHostAsync: Forcing the search to x64 architecure, IsDefaultTargetArchitecture '{this.runsettingHelper.IsDefaultTargetArchitecture}' OS '{this.platformEnvironment.OperatingSystem}' framework '{this.targetFramework}'"); + EqtTrace.Verbose($"DotnetTestHostmanager: Forcing the search to x64 architecure, IsDefaultTargetArchitecture '{this.runsettingHelper.IsDefaultTargetArchitecture}' OS '{this.platformEnvironment.OperatingSystem}' framework '{this.targetFramework}'"); } PlatformArchitecture finalTargetArchitecture = forceToX64 ? PlatformArchitecture.X64 : targetArchitecture; @@ -440,7 +441,7 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( startInfo.FileName = muxerPath; } - EqtTrace.Verbose("DotnetTestHostmanager.LaunchTestHostAsync: Full path of testhost.dll is {0}", testHostPath); + EqtTrace.Verbose("DotnetTestHostmanager: Full path of testhost.dll is {0}", testHostPath); args = "exec" + args; args += " " + testHostPath.AddDoubleQuote(); } diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs index 698975f79d..61f75604b1 100644 --- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs +++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs @@ -36,6 +36,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestPlatform.Utilities; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Payloads; + using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; /// /// Defines the test request manger which can fire off discovery and test run requests. @@ -618,8 +619,9 @@ private bool UpdateRunSettingsIfRequired( // it can be specified by user on the command line with --arch or through runsettings. // If it's not specified by user will be filled by current processor architecture; // should be the same as SDK. - defaultArchitecture = runConfiguration.TargetPlatform; - EqtTrace.Verbose($"Default architecture: {defaultArchitecture}"); + defaultArchitecture = RunSettingsHelper.Instance.IsDefaultTargetArchitecture ? + TranslateToArchitecture(processHelper.GetCurrentProcessArchitecture()) : + runConfiguration.TargetPlatform; #else // We are running in vstest.console.exe that was built against .NET // Framework. This console prefers 32-bit because it needs to run as 32-bit @@ -630,6 +632,7 @@ private bool UpdateRunSettingsIfRequired( // We want to find 64-bit SDK because it is more likely to be installed. defaultArchitecture = Environment.Is64BitOperatingSystem ? Architecture.X64 : Architecture.X86; #endif + EqtTrace.Verbose($"Default architecture: {defaultArchitecture} IsDefaultTargetArchitecture: {RunSettingsHelper.Instance.IsDefaultTargetArchitecture}"); } settingsUpdated |= this.UpdatePlatform( @@ -656,6 +659,27 @@ private bool UpdateRunSettingsIfRequired( } return settingsUpdated; + +#if NETCOREAPP + Architecture TranslateToArchitecture(PlatformArchitecture targetArchitecture) + { + switch (targetArchitecture) + { + case PlatformArchitecture.X86: + return Architecture.X86; + case PlatformArchitecture.X64: + return Architecture.X64; + case PlatformArchitecture.ARM: + return Architecture.ARM; + case PlatformArchitecture.ARM64: + return Architecture.ARM64; + default: + break; + } + + throw new TestPlatformException($"Invalid target architecture '{targetArchitecture}'"); + } +#endif } private bool AddOrUpdateConsoleLogger( diff --git a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs index 10e27fa429..41ee4db786 100644 --- a/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs +++ b/test/Microsoft.TestPlatform.CoreUtilities.UnitTests/Helpers/DotnetHostHelperTest.cs @@ -34,6 +34,7 @@ public void GetDotnetPathByArchitecture_SameArchitecture() environmentHelper.SetupGet(x => x.OperatingSystem).Returns(PlatformOperatingSystem.Windows); environmentHelper.SetupGet(x => x.Architecture).Returns(PlatformArchitecture.X64); processHelper.Setup(x => x.GetCurrentProcessFileName()).Returns(finalMuxerPath); + processHelper.Setup(x => x.GetCurrentProcessArchitecture()).Returns(PlatformArchitecture.X64); // Act & Assert Assert.IsTrue(dotnetHostHelper.TryGetDotnetPathByArchitecture(PlatformArchitecture.X64, out string muxerPath)); diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs index ff2b077199..1db6e0f02f 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs @@ -97,6 +97,7 @@ public DotnetTestHostManagerTests() // Setup a dummy current process for tests this.mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns(DefaultDotnetPath); this.mockProcessHelper.Setup(ph => ph.GetTestEngineDirectory()).Returns(DefaultDotnetPath); + this.mockProcessHelper.Setup(ph => ph.GetCurrentProcessArchitecture()).Returns(PlatformArchitecture.X64); this.mockEnvironmentVariable.Setup(ev => ev.GetEnvironmentVariable(It.IsAny())).Returns(Path.GetDirectoryName(DefaultDotnetPath)); this.mockFileHelper.Setup(ph => ph.Exists(this.defaultTestHostPath)).Returns(true); this.mockFileHelper.Setup(ph => ph.Exists(DefaultDotnetPath)).Returns(true);