Skip to content

Commit d373954

Browse files
youssef-backport-botCopilotYoussef1313
authored
Fix DisableAppDomain default value when not running in isolation under VSTest by @Copilot in #6900 (backport to rel/4.0) (#6909)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: Youssef1313 <[email protected]> Co-authored-by: Youssef Victor <[email protected]>
1 parent af3a322 commit d373954

File tree

6 files changed

+181
-58
lines changed

6 files changed

+181
-58
lines changed

src/Adapter/MSTestAdapter.PlatformServices/Services/MSTestAdapterSettings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ public static bool IsAppDomainCreationDisabled(string? settingsXml)
191191
// Otherwise, we will not merge app.config properly, nor we will have correct BaseDirectory of current domain.
192192
#if NETFRAMEWORK
193193
if (AppDomain.CurrentDomain.Id == 1 &&
194-
AppDomain.CurrentDomain.FriendlyName.StartsWith("testhost.", StringComparison.Ordinal) &&
194+
(AppDomain.CurrentDomain.FriendlyName.StartsWith("testhost.", StringComparison.Ordinal) ||
195+
AppDomain.CurrentDomain.FriendlyName.StartsWith("vstest.console.", StringComparison.Ordinal)) &&
195196
AppDomain.CurrentDomain.FriendlyName.EndsWith(".exe", StringComparison.Ordinal))
196197
{
197198
disableAppDomain = false;

test/IntegrationTests/MSTest.Acceptance.IntegrationTests/AppDomainTests.cs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using Microsoft.MSTestV2.CLIAutomation;
45
using Microsoft.Testing.Platform.Acceptance.IntegrationTests;
56
using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers;
7+
using Microsoft.Testing.TestInfrastructure;
68

79
namespace MSTest.Acceptance.IntegrationTests;
810

@@ -90,7 +92,7 @@ public async Task RunTests_With_VSTest(bool? disableAppDomain)
9092
string disableAppDomainCommand = disableAppDomain switch
9193
{
9294
true => " -- RunConfiguration.DisableAppDomain=true",
93-
false => " -- RunConfiguration.EnableAppDomain=false",
95+
false => " -- RunConfiguration.DisableAppDomain=false",
9496
null => string.Empty,
9597
};
9698

@@ -115,13 +117,97 @@ public async Task DiscoverTests_With_VSTest(bool? disableAppDomain)
115117
string disableAppDomainCommand = disableAppDomain switch
116118
{
117119
true => " -- RunConfiguration.DisableAppDomain=true",
118-
false => " -- RunConfiguration.EnableAppDomain=false",
120+
false => " -- RunConfiguration.DisableAppDomain=false",
119121
null => string.Empty,
120122
};
121123

122124
DotnetMuxerResult compilationResult = await DotnetCli.RunAsync($"test {testAsset.TargetAssetPath} --list-tests{disableAppDomainCommand}", AcceptanceFixture.NuGetGlobalPackagesFolder.Path, workingDirectory: testAsset.TargetAssetPath, cancellationToken: TestContext.CancellationToken);
123125
Assert.AreEqual(0, compilationResult.ExitCode);
124126
}
125127

128+
[TestMethod]
129+
[DataRow(true)]
130+
[DataRow(false)]
131+
[DataRow(null)]
132+
public async Task RunTests_With_VSTestConsole_Directly(bool? disableAppDomain)
133+
{
134+
using TestAsset testAsset = await TestAsset.GenerateAssetAsync(
135+
AssetName,
136+
SingleTestSourceCode
137+
.PatchCodeWithReplace("$MSTestVersion$", MSTestVersion)
138+
.PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetFramework[0]));
139+
140+
// Build the test project
141+
DotnetMuxerResult buildResult = await DotnetCli.RunAsync(
142+
$"build {testAsset.TargetAssetPath} -c Debug",
143+
AcceptanceFixture.NuGetGlobalPackagesFolder.Path,
144+
workingDirectory: testAsset.TargetAssetPath,
145+
cancellationToken: TestContext.CancellationToken);
146+
Assert.AreEqual(0, buildResult.ExitCode, $"Build failed: {buildResult.StandardOutput}");
147+
148+
// Get the DLL path
149+
string dllPath = GetTestDllPath(testAsset.TargetAssetPath, TargetFrameworks.NetFramework[0]);
150+
Assert.IsTrue(File.Exists(dllPath), $"Test DLL not found at {dllPath}");
151+
152+
// Run tests using vstest.console.exe directly
153+
string vstestConsolePath = VSTestConsoleLocator.GetConsoleRunnerPath();
154+
string disableAppDomainCommand = disableAppDomain switch
155+
{
156+
true => " -- RunConfiguration.DisableAppDomain=true",
157+
false => " -- RunConfiguration.DisableAppDomain=false",
158+
null => string.Empty,
159+
};
160+
161+
string arguments = $"\"{dllPath}\"{disableAppDomainCommand}";
162+
163+
using var commandLine = new CommandLine();
164+
await commandLine.RunAsync(
165+
$"\"{vstestConsolePath}\" {arguments}",
166+
cancellationToken: TestContext.CancellationToken);
167+
}
168+
169+
[TestMethod]
170+
[DataRow(true)]
171+
[DataRow(false)]
172+
[DataRow(null)]
173+
public async Task DiscoverTests_With_VSTestConsole_Directly(bool? disableAppDomain)
174+
{
175+
using TestAsset testAsset = await TestAsset.GenerateAssetAsync(
176+
AssetName,
177+
SingleTestSourceCode
178+
.PatchCodeWithReplace("$MSTestVersion$", MSTestVersion)
179+
.PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetFramework[0]));
180+
181+
// Build the test project
182+
DotnetMuxerResult buildResult = await DotnetCli.RunAsync(
183+
$"build {testAsset.TargetAssetPath} -c Debug",
184+
AcceptanceFixture.NuGetGlobalPackagesFolder.Path,
185+
workingDirectory: testAsset.TargetAssetPath,
186+
cancellationToken: TestContext.CancellationToken);
187+
Assert.AreEqual(0, buildResult.ExitCode, $"Build failed: {buildResult.StandardOutput}");
188+
189+
// Get the DLL path
190+
string dllPath = GetTestDllPath(testAsset.TargetAssetPath, TargetFrameworks.NetFramework[0]);
191+
Assert.IsTrue(File.Exists(dllPath), $"Test DLL not found at {dllPath}");
192+
193+
// Run discovery using vstest.console.exe directly
194+
string vstestConsolePath = VSTestConsoleLocator.GetConsoleRunnerPath();
195+
string disableAppDomainCommand = disableAppDomain switch
196+
{
197+
true => " -- RunConfiguration.DisableAppDomain=true",
198+
false => " -- RunConfiguration.DisableAppDomain=false",
199+
null => string.Empty,
200+
};
201+
string arguments = $"\"{dllPath}\" /ListTests{disableAppDomainCommand}";
202+
203+
using var commandLine = new CommandLine();
204+
await commandLine.RunAsync(
205+
$"\"{vstestConsolePath}\" {arguments}",
206+
cancellationToken: TestContext.CancellationToken);
207+
}
208+
209+
private static string GetTestDllPath(string assetPath, string targetFramework) =>
210+
Path.Combine(assetPath, "bin", "Debug", targetFramework, $"{AssetName}.dll");
211+
126212
public TestContext TestContext { get; set; }
127213
}

test/IntegrationTests/MSTest.Acceptance.IntegrationTests/MSTest.Acceptance.IntegrationTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<Compile Include="$(RepoRoot)test\IntegrationTests\Microsoft.Testing.Platform.Acceptance.IntegrationTests\Helpers\AcceptanceFixture.cs" Link="Helpers\AcceptanceFixture.cs" />
1414
<Compile Include="$(RepoRoot)test\IntegrationTests\Microsoft.Testing.Platform.Acceptance.IntegrationTests\Helpers\AcceptanceTestBase.cs" Link="Helpers\AcceptanceTestBase.cs" />
1515
<Compile Include="$(RepoRoot)test\IntegrationTests\Microsoft.Testing.Platform.Acceptance.IntegrationTests\ServerMode\**\*.cs" Link="ServerMode\%(RecursiveDir)%(FileName)%(Extension)" />
16+
<Compile Include="$(RepoRoot)test\Utilities\Automation.CLI\VSTestConsoleLocator.cs" Link="Helpers\VSTestConsoleLocator.cs" />
1617
</ItemGroup>
1718

1819
<ItemGroup>

test/Utilities/Automation.CLI/CLITestBase.common.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ protected static XmlDocument ReadCPMFile()
3030
return versionPropsXml;
3131
}
3232

33-
protected static string GetTestPlatformVersion()
34-
{
35-
XmlDocument cpmXml = ReadCPMFile();
36-
XmlNode testSdkVersion = cpmXml.DocumentElement.SelectSingleNode("PropertyGroup/MicrosoftNETTestSdkVersion");
37-
38-
return testSdkVersion.InnerText;
39-
}
40-
4133
protected static string GetArtifactsBinFolderPath()
4234
{
4335
string assemblyLocation = Assembly.GetExecutingAssembly().Location;

test/Utilities/Automation.CLI/CLITestBase.e2e.cs

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public abstract partial class CLITestBase
1515
protected CLITestBase()
1616
{
1717
s_vsTestConsoleWrapper = new(
18-
GetConsoleRunnerPath(),
18+
VSTestConsoleLocator.GetConsoleRunnerPath(),
1919
new()
2020
{
2121
EnvironmentVariables = new()
@@ -65,52 +65,6 @@ public void InvokeVsTestForExecution(string[] sources, string runSettings = "",
6565
}
6666
}
6767

68-
public static string GetNugetPackageFolder()
69-
{
70-
string nugetPackagesFolderPath = Environment.GetEnvironmentVariable("NUGET_PACKAGES");
71-
if (!string.IsNullOrEmpty(nugetPackagesFolderPath))
72-
{
73-
Assert.IsTrue(Directory.Exists(nugetPackagesFolderPath), $"Found environment variable 'NUGET_PACKAGES' and NuGet package folder '{nugetPackagesFolderPath}' should exist");
74-
75-
return nugetPackagesFolderPath;
76-
}
77-
78-
string userProfile = Environment.GetEnvironmentVariable("USERPROFILE");
79-
nugetPackagesFolderPath = Path.Combine(userProfile, ".nuget", "packages");
80-
Assert.IsTrue(Directory.Exists(nugetPackagesFolderPath), $"NuGet package folder '{nugetPackagesFolderPath}' should exist");
81-
82-
return nugetPackagesFolderPath;
83-
}
84-
85-
/// <summary>
86-
/// Gets the path to <c>vstest.console.exe</c>.
87-
/// </summary>
88-
/// <returns>Full path to <c>vstest.console.exe</c>.</returns>
89-
public static string GetConsoleRunnerPath()
90-
{
91-
string testPlatformNuGetPackageFolder = Path.Combine(
92-
GetNugetPackageFolder(),
93-
TestPlatformCLIPackageName,
94-
GetTestPlatformVersion());
95-
if (!Directory.Exists(testPlatformNuGetPackageFolder))
96-
{
97-
throw new DirectoryNotFoundException($"Test platform NuGet package folder '{testPlatformNuGetPackageFolder}' does not exist");
98-
}
99-
100-
string vstestConsolePath = Path.Combine(
101-
testPlatformNuGetPackageFolder,
102-
"tools",
103-
"net462",
104-
"Common7",
105-
"IDE",
106-
"Extensions",
107-
"TestPlatform",
108-
"vstest.console.exe");
109-
return !File.Exists(vstestConsolePath)
110-
? throw new InvalidOperationException($"Could not find vstest.console.exe in {vstestConsolePath}")
111-
: vstestConsolePath;
112-
}
113-
11468
/// <summary>
11569
/// Validate if the discovered tests list contains provided tests.
11670
/// </summary>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Assert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
5+
6+
namespace Microsoft.MSTestV2.CLIAutomation;
7+
8+
/// <summary>
9+
/// Helper class to locate vstest.console.exe.
10+
/// </summary>
11+
public static class VSTestConsoleLocator
12+
{
13+
private const string TestPlatformCLIPackageName = "Microsoft.TestPlatform";
14+
15+
/// <summary>
16+
/// Gets the path to <c>vstest.console.exe</c>.
17+
/// </summary>
18+
/// <returns>Full path to <c>vstest.console.exe</c>.</returns>
19+
public static string GetConsoleRunnerPath()
20+
{
21+
string testPlatformNuGetPackageFolder = Path.Combine(
22+
GetNugetPackageFolder(),
23+
TestPlatformCLIPackageName,
24+
GetTestPlatformVersion());
25+
if (!Directory.Exists(testPlatformNuGetPackageFolder))
26+
{
27+
throw new DirectoryNotFoundException($"Test platform NuGet package folder '{testPlatformNuGetPackageFolder}' does not exist");
28+
}
29+
30+
string vstestConsolePath = Path.Combine(
31+
testPlatformNuGetPackageFolder,
32+
"tools",
33+
"net462",
34+
"Common7",
35+
"IDE",
36+
"Extensions",
37+
"TestPlatform",
38+
"vstest.console.exe");
39+
return !File.Exists(vstestConsolePath)
40+
? throw new InvalidOperationException($"Could not find vstest.console.exe in {vstestConsolePath}")
41+
: vstestConsolePath;
42+
}
43+
44+
private static string GetNugetPackageFolder()
45+
{
46+
string? nugetPackagesFolderPath = Environment.GetEnvironmentVariable("NUGET_PACKAGES");
47+
if (!string.IsNullOrEmpty(nugetPackagesFolderPath))
48+
{
49+
Assert.IsTrue(Directory.Exists(nugetPackagesFolderPath), $"Found environment variable 'NUGET_PACKAGES' and NuGet package folder '{nugetPackagesFolderPath}' should exist");
50+
51+
return nugetPackagesFolderPath;
52+
}
53+
54+
string? userProfile = Environment.GetEnvironmentVariable("USERPROFILE");
55+
if (string.IsNullOrEmpty(userProfile))
56+
{
57+
throw new InvalidOperationException("USERPROFILE environment variable is not set");
58+
}
59+
60+
nugetPackagesFolderPath = Path.Combine(userProfile, ".nuget", "packages");
61+
Assert.IsTrue(Directory.Exists(nugetPackagesFolderPath), $"NuGet package folder '{nugetPackagesFolderPath}' should exist");
62+
63+
return nugetPackagesFolderPath;
64+
}
65+
66+
private static string GetTestPlatformVersion()
67+
{
68+
string cpmFilePath = Path.Combine(GetArtifactsBinFolderPath(), "..", "..", "Directory.Packages.props");
69+
using FileStream fileStream = File.OpenRead(cpmFilePath);
70+
#pragma warning disable CA3075 // Insecure DTD processing in XML
71+
using var xmlTextReader = new XmlTextReader(fileStream) { Namespaces = false };
72+
#pragma warning restore CA3075 // Insecure DTD processing in XML
73+
var cpmXml = new XmlDocument();
74+
cpmXml.Load(xmlTextReader);
75+
76+
return cpmXml.DocumentElement?.SelectSingleNode("PropertyGroup/MicrosoftNETTestSdkVersion")?.InnerText
77+
?? throw new InvalidOperationException($"Could not find MicrosoftNETTestSdkVersion in {cpmFilePath}");
78+
}
79+
80+
private static string GetArtifactsBinFolderPath()
81+
{
82+
string assemblyLocation = Assembly.GetExecutingAssembly().Location;
83+
84+
string artifactsBinFolder = Path.GetFullPath(Path.Combine(assemblyLocation, @"..\..\..\.."));
85+
Assert.IsTrue(Directory.Exists(artifactsBinFolder));
86+
87+
return artifactsBinFolder;
88+
}
89+
}

0 commit comments

Comments
 (0)