-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add more multithreaded tests #12994
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
Merged
Merged
Add more multithreaded tests #12994
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
02fe445
1st version
AR-May 7064f66
fix path to the asset
AR-May 880f29c
change binlog test so that it takes less time
AR-May 32dce8d
ensure tests isolation
AR-May 3d78e85
Isolate test asset
AR-May 29f2f92
Revert vs version change
AR-May 2b18fc1
Fix target framework in tests
AR-May 23daaf8
Test assets fixture should fail if restore fails.
AR-May 637bcfb
Fix path separator - this will fix unix tests,
AR-May b8d161f
Increase timeout for the tests
AR-May a402fa6
Add global.json to use bootstrap layout's SDK
OvesN b81f2e6
Merge
OvesN 13e7d14
Add non-sdk style tests
OvesN b69dafa
Clean up tests
OvesN 7e33069
Address review feedback:
OvesN 2f040b0
Remove IMessageSink
OvesN 199b07d
Remove pr-description.md file
OvesN File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/MSBuild.EndToEnd.Tests/Microsoft.Build.EndToEnd.Tests.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFrameworks>$(RuntimeOutputTargetFrameworks)</TargetFrameworks> | ||
| <PlatformTarget>$(RuntimeOutputPlatformTarget)</PlatformTarget> | ||
| <IsPackable>false</IsPackable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Reference Include="System.Net.Http" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" /> | ||
|
|
||
| <PackageReference Include="Shouldly" /> | ||
| <PackageReference Include="Microsoft.IO.Redist" Condition="'$(FeatureMSIORedist)' == 'true'" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Reference Include="System.IO.Compression" Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\MSBuild\MSBuild.csproj" /> | ||
| <ProjectReference Include="..\UnitTests.Shared\Microsoft.Build.UnitTests.Shared.csproj" /> | ||
| <ProjectReference Include="..\Xunit.NetCore.Extensions\Xunit.NetCore.Extensions.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Compile Remove="TestAssets\**\*.cs" /> | ||
| <None Include="TestAssets\**" CopyToOutputDirectory="PreserveNewest" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> | ||
190 changes: 190 additions & 0 deletions
190
src/MSBuild.EndToEnd.Tests/MultithreadedExecution_Tests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Linq; | ||
|
OvesN marked this conversation as resolved.
|
||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Build.UnitTests; | ||
| using Microsoft.Build.UnitTests.Shared; | ||
| using Shouldly; | ||
| using Xunit; | ||
|
|
||
| namespace Microsoft.Build.EndToEndTests | ||
| { | ||
| /// <summary> | ||
| /// Tests for multithreaded MSBuild execution scenarios using test assets. | ||
| /// </summary> | ||
| public class MultithreadedExecution_Tests : IClassFixture<TestSolutionAssetsFixture>, IDisposable | ||
| { | ||
| private readonly ITestOutputHelper _output; | ||
| private readonly TestEnvironment _env; | ||
| private readonly string _testAssetDir; | ||
|
|
||
| private readonly int _timeoutInMilliseconds = 180_000; | ||
|
|
||
| // Common parameters for all multithreaded tests: | ||
| // /nodereuse:false - Prevents MSBuild server processes from persisting between tests, | ||
| // ensuring proper test isolation and avoiding potential timeouts | ||
| // /v:minimal - Reduces log verbosity for cleaner test output and better performance | ||
| private const string CommonMSBuildArgs = "/nodereuse:false /v:minimal"; | ||
|
|
||
| public MultithreadedExecution_Tests(ITestOutputHelper output, TestSolutionAssetsFixture testAssetFixture) | ||
| { | ||
| _output = output; | ||
| _env = TestEnvironment.Create(output); | ||
| _testAssetDir = testAssetFixture.TestAssetDir; | ||
| } | ||
|
|
||
| public void Dispose() | ||
| { | ||
| _env.Dispose(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Prepares an isolated copy of test assets in a temporary directory for each test run. | ||
| /// This ensures fresh builds and proper test isolation. | ||
| /// </summary> | ||
| /// <param name="testAsset">Test asset</param> | ||
| /// <returns>TestSolutionAsset for the copied asset in a temporary folder.</returns> | ||
| private TestSolutionAsset PrepareIsolatedTestAssets(TestSolutionAsset testAsset) | ||
| { | ||
| string sourceAssetDir = Path.Combine(_testAssetDir, testAsset.SolutionFolder); | ||
|
|
||
| // Ensure source test asset exists | ||
| Directory.Exists(sourceAssetDir).ShouldBeTrue($"Test asset not found: {sourceAssetDir}."); | ||
|
|
||
| // Create isolated copy of entire test asset directory structure | ||
| TransientTestFolder workFolder = _env.CreateFolder(createFolder: true); | ||
|
|
||
| FileUtilities.CopyDirectory(sourceAssetDir, workFolder.Path); | ||
|
|
||
| // Return TestSolutionAsset with temp folder and project file | ||
| return new TestSolutionAsset(workFolder.Path, testAsset.ProjectRelativePath); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Helper method to resolve TestSolutionAsset instances by name. | ||
| /// This is the easiest way to work around the limitation that [InlineData] cannot pass complex objects like TestSolutionAsset directly. | ||
| /// </summary> | ||
| private static TestSolutionAsset GetTestAssetByName(string testAssetName) | ||
| { | ||
| return testAssetName switch | ||
| { | ||
| nameof(TestSolutionAssetsFixture.SingleProject) => TestSolutionAssetsFixture.SingleProject, | ||
| nameof(TestSolutionAssetsFixture.ProjectWithDependencies) => TestSolutionAssetsFixture.ProjectWithDependencies, | ||
| nameof(TestSolutionAssetsFixture.NonSdkSingleProject) => TestSolutionAssetsFixture.NonSdkSingleProject, | ||
| nameof(TestSolutionAssetsFixture.NonSdkProjectWithDependencies) => TestSolutionAssetsFixture.NonSdkProjectWithDependencies, | ||
| _ => throw new ArgumentException($"Unknown test asset name: {testAssetName}", nameof(testAssetName)) | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Builds a test asset with the given MSBuild args and verifies success. | ||
| /// </summary> | ||
| private void BuildAndVerify(string testAssetName, string multithreadingArgs) | ||
| { | ||
| // Resolve TestSolutionAsset from name | ||
| TestSolutionAsset testAsset = GetTestAssetByName(testAssetName); | ||
| // Prepare isolated copy of test assets to ensure fresh builds | ||
| TestSolutionAsset isolatedAsset = PrepareIsolatedTestAssets(testAsset); | ||
|
|
||
| string output = RunnerUtilities.ExecBootstrapedMSBuild( | ||
| $"\"{isolatedAsset.ProjectPath}\" {multithreadingArgs} {CommonMSBuildArgs}", | ||
| out bool success, | ||
| timeoutMilliseconds: _timeoutInMilliseconds); | ||
|
|
||
| success.ShouldBeTrue($"Build failed with args '{multithreadingArgs}' for {testAsset.SolutionFolder}. Output:\n{output}"); | ||
|
|
||
| _output.WriteLine($"Built {testAsset.SolutionFolder} with arguments {multithreadingArgs}."); | ||
| } | ||
|
OvesN marked this conversation as resolved.
|
||
|
|
||
| /// <summary> | ||
| /// Tests building projects with various multithreading flags. | ||
| /// </summary> | ||
| [Theory] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.SingleProject), "/m:1 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.SingleProject), "/m:8 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.SingleProject), "/mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.ProjectWithDependencies), "/m:1 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.ProjectWithDependencies), "/m:2 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.ProjectWithDependencies), "/m:8 /mt")] | ||
| public void MultithreadedBuild_Success(string testAssetName, string multithreadingArgs) | ||
| { | ||
| BuildAndVerify(testAssetName, multithreadingArgs); | ||
| } | ||
|
|
||
|
OvesN marked this conversation as resolved.
|
||
| /// <summary> | ||
| /// Builds a test asset with binary logging, then replays the binlog and verifies both succeed. | ||
| /// </summary> | ||
| private void BuildWithBinlogAndVerifyReplay(string testAssetName, string multithreadingArgs) | ||
| { | ||
| // Resolve TestSolutionAsset from name | ||
| TestSolutionAsset testAsset = GetTestAssetByName(testAssetName); | ||
|
|
||
| // Prepare isolated copy of test assets to ensure fresh builds | ||
| TestSolutionAsset isolatedAsset = PrepareIsolatedTestAssets(testAsset); | ||
|
|
||
| string binlogPath = Path.Combine(isolatedAsset.SolutionFolder, "build.binlog"); | ||
|
|
||
| // Build with binary logging | ||
| string output = RunnerUtilities.ExecBootstrapedMSBuild( | ||
| $"\"{isolatedAsset.ProjectPath}\" {multithreadingArgs} /bl:\"{binlogPath}\" {CommonMSBuildArgs}", | ||
| out bool success, | ||
| timeoutMilliseconds: _timeoutInMilliseconds); | ||
|
|
||
| success.ShouldBeTrue($"Build failed with args '{multithreadingArgs}' for {testAsset.SolutionFolder}. Output:\n{output}."); | ||
|
|
||
| // Verify binary log was created and has content | ||
| File.Exists(binlogPath).ShouldBeTrue("Binary log file was not created."); | ||
|
OvesN marked this conversation as resolved.
|
||
| new FileInfo(binlogPath).Length.ShouldBeGreaterThan(0, "Binary log file was created but is empty."); | ||
|
|
||
| // Test binlog replay | ||
| string replayOutput = RunnerUtilities.ExecBootstrapedMSBuild( | ||
| $"\"{binlogPath}\" {CommonMSBuildArgs}", | ||
| out bool replaySuccess, | ||
| timeoutMilliseconds: _timeoutInMilliseconds); | ||
|
|
||
| replaySuccess.ShouldBeTrue($"Binlog replay failed. Output:\n{replayOutput}"); | ||
|
|
||
| _output.WriteLine($"Built and replayed {testAsset.SolutionFolder} with arguments {multithreadingArgs}."); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Tests binary logging with multithreaded builds and verifies replay functionality. | ||
| /// </summary> | ||
| [Theory] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.SingleProject), "/m:8 /mt")] | ||
|
OvesN marked this conversation as resolved.
|
||
| [InlineData(nameof(TestSolutionAssetsFixture.ProjectWithDependencies), "/m:8 /mt")] | ||
| public void MultithreadedBuild_BinaryLogging(string testAssetName, string multithreadingArgs) | ||
| { | ||
| BuildWithBinlogAndVerifyReplay(testAssetName, multithreadingArgs); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Tests building non-SDK-style projects with multithreading flags. | ||
| /// </summary> | ||
| [WindowsOnlyTheory] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkSingleProject), "/m:1 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkSingleProject), "/m:8 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkSingleProject), "/mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkProjectWithDependencies), "/m:1 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkProjectWithDependencies), "/m:2 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkProjectWithDependencies), "/m:8 /mt")] | ||
| public void MultithreadedBuild_NonSdkStyle_Success(string testAssetName, string multithreadingArgs) | ||
| { | ||
| BuildAndVerify(testAssetName, multithreadingArgs); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Tests binary logging with non-SDK-style multithreaded builds and verifies replay functionality. | ||
| /// </summary> | ||
| [WindowsOnlyTheory] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkSingleProject), "/m:8 /mt")] | ||
| [InlineData(nameof(TestSolutionAssetsFixture.NonSdkProjectWithDependencies), "/m:8 /mt")] | ||
| public void MultithreadedBuild_NonSdkStyle_BinaryLogging(string testAssetName, string multithreadingArgs) | ||
| { | ||
| BuildWithBinlogAndVerifyReplay(testAssetName, multithreadingArgs); | ||
| } | ||
| } | ||
| } | ||
16 changes: 16 additions & 0 deletions
16
...uild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/ConsoleApp/ConsoleApp.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/> | ||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Program.cs" /> | ||
| </ItemGroup> | ||
| <ItemGroup> | ||
| <ProjectReference Include="..\Library1\Library1.csproj" /> | ||
| <ProjectReference Include="..\Library2\Library2.csproj" /> | ||
| </ItemGroup> | ||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
| </Project> |
15 changes: 15 additions & 0 deletions
15
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/ConsoleApp/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| using System; | ||
| using Library1; | ||
| using Library2; | ||
|
|
||
| namespace NonSdkConsoleApp | ||
| { | ||
| class Program | ||
| { | ||
| static void Main(string[] args) | ||
| { | ||
| var c1 = new Class1(); | ||
| var c2 = new Class2(); | ||
| } | ||
| } | ||
| } |
6 changes: 6 additions & 0 deletions
6
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/Library1/Class1.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| namespace Library1 | ||
| { | ||
| public class Class1 | ||
| { | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/Library1/Library1.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" /> | ||
| <PropertyGroup> | ||
| <OutputType>Library</OutputType> | ||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Class1.cs" /> | ||
| </ItemGroup> | ||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
| </Project> |
6 changes: 6 additions & 0 deletions
6
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/Library2/Class2.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| namespace Library2 | ||
| { | ||
| public class Class2 | ||
| { | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkProjectWithDependencies/Library2/Library2.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" /> | ||
| <PropertyGroup> | ||
| <OutputType>Library</OutputType> | ||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Class2.cs" /> | ||
| </ItemGroup> | ||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
| </Project> |
12 changes: 12 additions & 0 deletions
12
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkSingleProject/NonSdkSingleProject.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
| <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')"/> | ||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | ||
| </PropertyGroup> | ||
| <ItemGroup> | ||
| <Compile Include="Program.cs" /> | ||
| </ItemGroup> | ||
| <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||
| </Project> |
11 changes: 11 additions & 0 deletions
11
src/MSBuild.EndToEnd.Tests/TestAssets/NonSdkSingleProject/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| using System; | ||
|
|
||
| namespace NonSdkSingleProject | ||
| { | ||
| class Program | ||
| { | ||
| static void Main(string[] args) | ||
| { | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.