diff --git a/src/Build.UnitTests/NetTaskHost_E2E_Tests.cs b/src/Build.UnitTests/NetTaskHost_E2E_Tests.cs index 22f01c69e9b..a0b35a6ed39 100644 --- a/src/Build.UnitTests/NetTaskHost_E2E_Tests.cs +++ b/src/Build.UnitTests/NetTaskHost_E2E_Tests.cs @@ -36,7 +36,7 @@ public void NetTaskHostTest() string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTask", "TestNetTask.csproj"); - string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask); + string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask); if (!successTestTask) { @@ -63,7 +63,7 @@ public void NetTaskHost_CorrectPathsEscapingTest() using TestEnvironment env = TestEnvironment.Create(_output); var dotnetPath = env.GetEnvironmentVariable("DOTNET_ROOT"); string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTask", "TestNetTask.csproj"); - string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask); + string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask); if (!successTestTask) { @@ -124,7 +124,7 @@ public void MSBuildTaskInNetHostTest() string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestMSBuildTaskInNet", "TestMSBuildTaskInNet.csproj"); - string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask); + string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask); if (!successTestTask) { @@ -143,7 +143,7 @@ public void NetTaskWithImplicitHostParamsTest() string testProjectPath = Path.Combine(TestAssetsRootPath, "ExampleNetTask", "TestNetTaskWithImplicitParams", "TestNetTaskWithImplicitParams.csproj"); - string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n", out bool successTestTask); + string testTaskOutput = RunnerUtilities.ExecBootstrapedMSBuild($"{testProjectPath} -restore -v:n -p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool successTestTask); if (!successTestTask) { @@ -164,4 +164,4 @@ public void NetTaskWithImplicitHostParamsTest() testTaskOutput.ShouldContain("Found item: Banana"); } } -} +} \ No newline at end of file diff --git a/src/Build.UnitTests/TaskHostFactoryLifecycle_E2E_Tests.cs b/src/Build.UnitTests/TaskHostFactoryLifecycle_E2E_Tests.cs index b82ca9693ba..464ca7672da 100644 --- a/src/Build.UnitTests/TaskHostFactoryLifecycle_E2E_Tests.cs +++ b/src/Build.UnitTests/TaskHostFactoryLifecycle_E2E_Tests.cs @@ -95,7 +95,7 @@ private string ExecuteBuildWithTaskHost(string runtimeToUse, string taskFactoryT string testProjectPath = Path.Combine(TestAssetsRootPath, "TaskHostLifecycleTestApp.csproj"); string output = RunnerUtilities.ExecBootstrapedMSBuild( - $"{testProjectPath} -v:n -restore /p:RuntimeToUse={runtimeToUse} /p:TaskFactoryToUse={taskFactoryToUse}", + $"{testProjectPath} -v:n -restore /p:RuntimeToUse={runtimeToUse} /p:TaskFactoryToUse={taskFactoryToUse} /p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool success, outputHelper: _output); diff --git a/src/Build.UnitTests/TerminalLogger_Tests.cs b/src/Build.UnitTests/TerminalLogger_Tests.cs index 59d55089d7b..6b078789892 100644 --- a/src/Build.UnitTests/TerminalLogger_Tests.cs +++ b/src/Build.UnitTests/TerminalLogger_Tests.cs @@ -1011,7 +1011,7 @@ public async Task ProjectFinishedReportsTargetFrameworkAndRuntimeIdentifier() { // this project will report a TFM and a RID and so will show a both in the output var buildOutputEvent = MakeBuildOutputEventArgs(_projectFile); - InvokeLoggerCallbacksForSimpleProject(succeeded: true, properties: [("TargetFramework", "net10.0"), ("RuntimeIdentifier", "win-x64")], additionalCallbacks: () => + InvokeLoggerCallbacksForSimpleProject(succeeded: true, properties: [("TargetFramework", RunnerUtilities.LatestDotNetCoreForMSBuild), ("RuntimeIdentifier", "win-x64")], additionalCallbacks: () => { _centralNodeEventSource.InvokeMessageRaised(buildOutputEvent); }); diff --git a/src/Build.UnitTests/TestAssets/ExampleNetTask/ExampleTask/ExampleTask.csproj b/src/Build.UnitTests/TestAssets/ExampleNetTask/ExampleTask/ExampleTask.csproj index 36add8bbb2b..7a5976334e9 100644 --- a/src/Build.UnitTests/TestAssets/ExampleNetTask/ExampleTask/ExampleTask.csproj +++ b/src/Build.UnitTests/TestAssets/ExampleNetTask/ExampleTask/ExampleTask.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) diff --git a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestMSBuildTaskInNet/TestMSBuildTaskInNet.csproj b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestMSBuildTaskInNet/TestMSBuildTaskInNet.csproj index d40cbcf9d52..094d5e93791 100644 --- a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestMSBuildTaskInNet/TestMSBuildTaskInNet.csproj +++ b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestMSBuildTaskInNet/TestMSBuildTaskInNet.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) enable enable diff --git a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTask/TestNetTask.csproj b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTask/TestNetTask.csproj index 0ed5a43fb8d..2f63d513a2e 100644 --- a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTask/TestNetTask.csproj +++ b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTask/TestNetTask.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) diff --git a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskWithImplicitParams/TestNetTaskWithImplicitParams.csproj b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskWithImplicitParams/TestNetTaskWithImplicitParams.csproj index 7419e72c777..75ec454fc07 100644 --- a/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskWithImplicitParams/TestNetTaskWithImplicitParams.csproj +++ b/src/Build.UnitTests/TestAssets/ExampleNetTask/TestNetTaskWithImplicitParams/TestNetTaskWithImplicitParams.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) diff --git a/src/Build.UnitTests/TestAssets/TaskHostLifecycle/TaskHostLifecycleTestApp.csproj b/src/Build.UnitTests/TestAssets/TaskHostLifecycle/TaskHostLifecycleTestApp.csproj index adb43e0de99..76f52173659 100644 --- a/src/Build.UnitTests/TestAssets/TaskHostLifecycle/TaskHostLifecycleTestApp.csproj +++ b/src/Build.UnitTests/TestAssets/TaskHostLifecycle/TaskHostLifecycleTestApp.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) $([System.IO.Path]::GetFullPath('$([System.IO.Path]::Combine('$(AssemblyLocation)', '..'))')) $([System.IO.Path]::Combine('$(TestProjectFolder)', '$(TargetFramework)', 'ExampleTask.dll')) diff --git a/src/BuildCheck.UnitTests/EndToEndTests.cs b/src/BuildCheck.UnitTests/EndToEndTests.cs index d251e8f5ecc..82472057d0f 100644 --- a/src/BuildCheck.UnitTests/EndToEndTests.cs +++ b/src/BuildCheck.UnitTests/EndToEndTests.cs @@ -21,7 +21,6 @@ namespace Microsoft.Build.BuildCheck.UnitTests; public class EndToEndTests : IDisposable { private const string EditorConfigFileName = ".editorconfig"; - private const string LatestDotNetCoreForMSBuild = "net10.0"; private readonly TestEnvironment _env; @@ -171,7 +170,7 @@ private EmbedResourceTestOutput RunEmbeddedResourceTest(string resourceXmlToAdd, _env.SetCurrentDirectory(Path.Combine(workFolder.Path, entryProjectName)); - string output = RunnerUtilities.ExecBootstrapedMSBuild("-check -restore /p:WarnOnCultureOverwritten=True /p:RespectCulture=" + (respectCulture ? "True" : "\"\""), out bool success, timeoutMilliseconds: timeoutInMilliseconds); + string output = RunnerUtilities.ExecBootstrapedMSBuild($"-check -restore /p:WarnOnCultureOverwritten=True /p:RespectCulture={(respectCulture ? "True" : "\"\"")} /p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool success, timeoutMilliseconds: timeoutInMilliseconds); _env.Output.WriteLine(output); _env.Output.WriteLine("========================="); success.ShouldBeTrue(); @@ -232,7 +231,7 @@ private readonly record struct CopyTestOutput( private CopyTestOutput RunCopyToOutputTest(bool restore, bool skipUnchangedDuringCopy) { - string output = RunnerUtilities.ExecBootstrapedMSBuild($"-check {(restore ? "-restore" : null)} /p:SkipUnchanged={(skipUnchangedDuringCopy ? "True" : "\"\"")}", out bool success, timeoutMilliseconds: timeoutInMilliseconds); + string output = RunnerUtilities.ExecBootstrapedMSBuild($"-check {(restore ? "-restore" : null)} /p:SkipUnchanged={(skipUnchangedDuringCopy ? "True" : "\"\"")} /p:LatestDotNetCoreForMSBuild={RunnerUtilities.LatestDotNetCoreForMSBuild}", out bool success, timeoutMilliseconds: timeoutInMilliseconds); _env.Output.WriteLine(output); _env.Output.WriteLine("========================="); success.ShouldBeTrue(); @@ -361,19 +360,26 @@ public void WarningsCountExceedsLimitTest(bool buildInOutOfProcessNode, bool lim } } + private const string testAssetsFolder = "TFMConfusionCheck"; + + public static IEnumerable TFMConfusionCheckTestData() + { + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild}""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild};net472""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild};net472""", $" /p:TargetFramework={RunnerUtilities.LatestDotNetCoreForMSBuild}", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild};net472""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild};net472""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild}""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild}""", "", false]; + yield return [$"""{RunnerUtilities.LatestDotNetCoreForMSBuild}{RunnerUtilities.LatestDotNetCoreForMSBuild};net472""", "", true]; + } + [Theory] - [InlineData($"""{LatestDotNetCoreForMSBuild}""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild};net472""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild};net472""", $" /p:TargetFramework={LatestDotNetCoreForMSBuild}", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild};net472""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild};net472""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild}""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild}""", "", false)] - [InlineData($"""{LatestDotNetCoreForMSBuild}{LatestDotNetCoreForMSBuild};net472""", "", true)] + [MemberData(nameof(TFMConfusionCheckTestData))] public void TFMConfusionCheckTest(string tfmString, string cliSuffix, bool shouldTriggerCheck) { const string testAssetsFolderName = "TFMConfusionCheck"; - const string projectName = testAssetsFolderName; + const string projectName = testAssetsFolder; const string templateToReplace = "###TFM"; TransientTestFolder workFolder = _env.CreateFolder(createFolder: true); @@ -407,56 +413,61 @@ void ReplaceStringInFile(string filePath, string original, string replacement) } } + public static IEnumerable TFMinNonSdkCheckTestData() + { + yield return [ + """ + + + net48 + + + + + + """, + false]; + yield return [ + $""" + + + {RunnerUtilities.LatestDotNetCoreForMSBuild} + + + """, + false]; + yield return [ + """ + + + Library + v4.8 + bin\Debug\ + CS2008 + + + + """, + false]; + yield return [ + """ + + + Library + v4.8 + v4.8 + bin\Debug\ + CS2008 + + + + """, + true]; + } + // Windows only - due to targeting NetFx [WindowsOnlyTheory] - [InlineData( - """ - - - net48 - - - - - - """, - false)] - [InlineData( - $""" - - - {LatestDotNetCoreForMSBuild} - - - """, - false)] - [InlineData( - """ - - - Library - v4.8 - bin\Debug\ - CS2008 - - - - """, - false)] - [InlineData( - """ - - - Library - v4.8 - v4.8 - bin\Debug\ - CS2008 - - - - """, - true)] + [MemberData(nameof(TFMinNonSdkCheckTestData))] public void TFMinNonSdkCheckTest(string projectContent, bool expectCheckTrigger) { TransientTestFolder workFolder = _env.CreateFolder(createFolder: true); diff --git a/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/EntryProject/EntryProject.csproj b/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/EntryProject/EntryProject.csproj index f5ae000b48e..169b2f4d2bb 100644 --- a/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/EntryProject/EntryProject.csproj +++ b/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/EntryProject/EntryProject.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) enable enable diff --git a/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/ReferencedProject/ReferencedProject.csproj b/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/ReferencedProject/ReferencedProject.csproj index 9709c2acc31..aa00a8f26a6 100644 --- a/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/ReferencedProject/ReferencedProject.csproj +++ b/src/BuildCheck.UnitTests/TestAssets/CopyAlwaysTest/ReferencedProject/ReferencedProject.csproj @@ -1,7 +1,7 @@ - net10.0 + $(LatestDotNetCoreForMSBuild) enable enable diff --git a/src/BuildCheck.UnitTests/TestAssets/EmbeddedResourceTest/EntryProject/EntryProject.csproj b/src/BuildCheck.UnitTests/TestAssets/EmbeddedResourceTest/EntryProject/EntryProject.csproj index 16852d41a1b..2742526793e 100644 --- a/src/BuildCheck.UnitTests/TestAssets/EmbeddedResourceTest/EntryProject/EntryProject.csproj +++ b/src/BuildCheck.UnitTests/TestAssets/EmbeddedResourceTest/EntryProject/EntryProject.csproj @@ -1,7 +1,7 @@  - net10.0 + $(LatestDotNetCoreForMSBuild) enable enable true diff --git a/src/Tasks.UnitTests/Copy_Tests.cs b/src/Tasks.UnitTests/Copy_Tests.cs index 9b3bf954125..63062fcf3a5 100644 --- a/src/Tasks.UnitTests/Copy_Tests.cs +++ b/src/Tasks.UnitTests/Copy_Tests.cs @@ -21,6 +21,7 @@ using Xunit; using Xunit.Abstractions; +using Microsoft.Build.UnitTests.Shared; #nullable disable @@ -3174,7 +3175,7 @@ public void CopyToFileWithSameCaseInsensitiveNameAsExistingDirectoryOnUnix() Directory.CreateDirectory(tempDir); // Create a subdirectory structure to match the real scenario - string outputDir = Path.Combine(tempDir, "bin", "Debug", "net10.0"); + string outputDir = Path.Combine(tempDir, "bin", "Debug", RunnerUtilities.LatestDotNetCoreForMSBuild); Directory.CreateDirectory(outputDir); // Create a directory named "cs" (lowercase) in the output directory @@ -3182,7 +3183,7 @@ public void CopyToFileWithSameCaseInsensitiveNameAsExistingDirectoryOnUnix() Directory.CreateDirectory(lowercaseDir); // Create a few source files to copy (representing multiple files being copied to same dest dir) - string sourceDir = Path.Combine(tempDir, "CS", "obj", "Debug", "net10.0"); + string sourceDir = Path.Combine(tempDir, "CS", "obj", "Debug", RunnerUtilities.LatestDotNetCoreForMSBuild); Directory.CreateDirectory(sourceDir); string sourceFile1 = Path.Combine(sourceDir, "apphost"); diff --git a/src/UnitTests.Shared/BootstrapLocationAttribute.cs b/src/UnitTests.Shared/BootstrapLocationAttribute.cs index 3854f1ecf13..bc0d0211dfb 100644 --- a/src/UnitTests.Shared/BootstrapLocationAttribute.cs +++ b/src/UnitTests.Shared/BootstrapLocationAttribute.cs @@ -6,7 +6,7 @@ namespace Microsoft.Build.UnitTests.Shared; [System.AttributeUsage(System.AttributeTargets.Assembly)] -internal sealed class BootstrapLocationAttribute(string bootstrapRoot, string bootstrapMsBuildBinaryLocation, string bootstrapSdkVersion) : System.Attribute +internal sealed class BootstrapLocationAttribute(string bootstrapRoot, string bootstrapMsBuildBinaryLocation, string bootstrapSdkVersion, string latestDotNetCoreForMSBuild) : System.Attribute { /// /// Path to the root of the bootstrap MSBuild (in artifacts folder). @@ -22,4 +22,9 @@ internal sealed class BootstrapLocationAttribute(string bootstrapRoot, string bo /// Returns the version of the SDK used by the bootstrap MSBuild. /// public string BootstrapSdkVersion { get; } = bootstrapSdkVersion; + + /// + /// The latest .NET target framework setup in MSBuild. + /// + public string LatestDotNetCoreForMSBuild { get; } = latestDotNetCoreForMSBuild; } diff --git a/src/UnitTests.Shared/Microsoft.Build.UnitTests.Shared.csproj b/src/UnitTests.Shared/Microsoft.Build.UnitTests.Shared.csproj index e3538055dba..73c968b3d22 100644 --- a/src/UnitTests.Shared/Microsoft.Build.UnitTests.Shared.csproj +++ b/src/UnitTests.Shared/Microsoft.Build.UnitTests.Shared.csproj @@ -44,6 +44,7 @@ <_Parameter1>$(ArtifactsBinDir)bootstrap <_Parameter2>$(TestBootstrapBinaryDestination) <_Parameter3>$(BootstrapSdkVersion) + <_Parameter4>$(LatestDotNetCoreForMSBuild) diff --git a/src/UnitTests.Shared/RunnerUtilities.cs b/src/UnitTests.Shared/RunnerUtilities.cs index 7cb15936a11..e3e43b8be32 100644 --- a/src/UnitTests.Shared/RunnerUtilities.cs +++ b/src/UnitTests.Shared/RunnerUtilities.cs @@ -27,6 +27,8 @@ public static class RunnerUtilities public static string BootstrapRootPath => BootstrapLocationAttribute.BootstrapRoot; + public static string LatestDotNetCoreForMSBuild => BootstrapLocationAttribute.LatestDotNetCoreForMSBuild; + internal static BootstrapLocationAttribute BootstrapLocationAttribute = Assembly.GetExecutingAssembly().GetCustomAttribute() ?? throw new InvalidOperationException("This test assembly does not have the BootstrapLocationAttribute");