Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 38 additions & 15 deletions test/Microsoft.NET.Build.Tests/RoslynBuildTaskTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Basic.CompilerLog.Util;
using Microsoft.Build.Logging.StructuredLogger;
using Microsoft.CodeAnalysis;
Expand All @@ -11,6 +12,9 @@ namespace Microsoft.NET.Build.Tests;

public sealed class RoslynBuildTaskTests(ITestOutputHelper log) : SdkTest(log)
{
private const string CoreTargetFrameworkName = ".NETCoreApp";
private const string FxTargetFrameworkName = ".NETFramework";

private static string CompilerFileNameWithoutExtension(Language language) => language switch
{
Language.CSharp => "csc",
Expand All @@ -27,7 +31,7 @@ public void FullMSBuild_SdkStyle(bool useSharedCompilation, Language language)
{
var testAsset = CreateProject(useSharedCompilation, language);
var buildCommand = BuildAndRunUsingMSBuild(testAsset);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), CoreTargetFrameworkName, useSharedCompilation);
}

[FullMSBuildOnlyTheory, CombinatorialData]
Expand All @@ -38,7 +42,7 @@ public void FullMSBuild_SdkStyle_OptOut(bool useSharedCompilation, Language lang
doc.Root!.Element("PropertyGroup")!.Add(new XElement("RoslynCompilerType", "Framework"));
});
var buildCommand = BuildAndRunUsingMSBuild(testAsset);
VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation);
VerifyCompiler(buildCommand, FxCompilerFileName(language), FxTargetFrameworkName, useSharedCompilation);
}

[FullMSBuildOnlyTheory, CombinatorialData]
Expand All @@ -50,23 +54,27 @@ public void FullMSBuild_NonSdkStyle(bool useSharedCompilation, Language language
project.TargetFrameworkVersion = "v4.7.2";
});
var buildCommand = BuildAndRunUsingMSBuild(testAsset);
VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation);
VerifyCompiler(buildCommand, FxCompilerFileName(language), FxTargetFrameworkName, useSharedCompilation);
}

[FullMSBuildOnlyTheory, CombinatorialData]
public void FullMSBuild_SdkStyle_ToolsetPackage(bool useSharedCompilation, Language language)
public void FullMSBuild_SdkStyle_ToolsetPackage(bool useSharedCompilation, Language language, bool useFrameworkCompiler)
{
var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage);
var buildCommand = BuildAndRunUsingMSBuild(testAsset);
VerifyCompiler(buildCommand, FxCompilerFileName(language), useSharedCompilation, toolsetPackage: true);
ReadOnlySpan<string> args = useFrameworkCompiler ? ["-p:RoslynCompilerType=Framework"] : [];
var buildCommand = BuildAndRunUsingMSBuild(testAsset, args);
VerifyCompiler(buildCommand,
useFrameworkCompiler ? FxCompilerFileName(language) : CoreCompilerFileName(language),
useFrameworkCompiler ? FxTargetFrameworkName : CoreTargetFrameworkName,
useSharedCompilation, toolsetPackage: true);
}

[Theory, CombinatorialData]
public void DotNet(bool useSharedCompilation, Language language)
{
var testAsset = CreateProject(useSharedCompilation, language);
var buildCommand = BuildAndRunUsingDotNet(testAsset);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), CoreTargetFrameworkName, useSharedCompilation);
}

// https://github.com/dotnet/sdk/issues/49665
Expand All @@ -75,7 +83,7 @@ public void DotNet_ToolsetPackage(bool useSharedCompilation, Language language)
{
var testAsset = CreateProject(useSharedCompilation, language, AddCompilersToolsetPackage);
var buildCommand = BuildAndRunUsingDotNet(testAsset);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), useSharedCompilation, toolsetPackage: true);
VerifyCompiler(buildCommand, CoreCompilerFileName(language), CoreTargetFrameworkName, useSharedCompilation, toolsetPackage: true);
}

private TestAsset CreateProject(bool useSharedCompilation, Language language, Action<TestProject>? configure = null, [CallerMemberName] string callingMethod = "")
Expand Down Expand Up @@ -129,21 +137,21 @@ private static void AddCompilersToolsetPackage(TestProject project)
project.PackageReferences.Add(new TestPackageReference("Microsoft.Net.Compilers.Toolset", roslynVersion));
}

private TestCommand BuildAndRunUsingMSBuild(TestAsset testAsset)
private TestCommand BuildAndRunUsingMSBuild(TestAsset testAsset, params ReadOnlySpan<string> args)
{
var buildCommand = new MSBuildCommand(testAsset, "Build");
buildCommand.WithWorkingDirectory(testAsset.Path)
.Execute("-bl").Should().Pass();
.Execute(["-bl", .. args]).Should().Pass();

Run(buildCommand.GetOutputDirectory().File(testAsset.TestProject!.GetOutputFileName()));

return buildCommand;
}

private TestCommand BuildAndRunUsingDotNet(TestAsset testAsset)
private TestCommand BuildAndRunUsingDotNet(TestAsset testAsset, params ReadOnlySpan<string> args)
{
var buildCommand = new DotnetBuildCommand(testAsset);
buildCommand.Execute("-bl").Should().Pass();
buildCommand.Execute(["-bl", .. args]).Should().Pass();

Run(buildCommand.GetOutputDirectory().File(testAsset.TestProject!.GetOutputFileName()));

Expand All @@ -157,7 +165,7 @@ private void Run(FileInfo outputFile)
.And.HaveStdOut("42");
}

private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, bool usedCompilerServer, bool toolsetPackage = false)
private static void VerifyCompiler(TestCommand buildCommand, string compilerFileName, string targetFrameworkName, bool usedCompilerServer, bool toolsetPackage = false)
{
var binaryLogPath = Path.Join(buildCommand.WorkingDirectory, "msbuild.binlog");
using (var reader = BinaryLogReader.Create(binaryLogPath))
Expand All @@ -174,16 +182,31 @@ private static void VerifyCompiler(TestCommand buildCommand, string compilerFile
{
call.CompilerFilePath.Should().NotContain(toolsetPackageName);
}

GetTargetFramework(call.CompilerFilePath).Should().StartWith($"{targetFrameworkName},");
}

// Verify compiler server message.
var compilerServerMesssages = BinaryLog.ReadBuild(binaryLogPath).FindChildrenRecursive<Message>(
var compilerServerMessages = BinaryLog.ReadBuild(binaryLogPath).FindChildrenRecursive<Message>(
static message => message.Text.StartsWith("CompilerServer:", StringComparison.Ordinal));
compilerServerMesssages.Should().ContainSingle().Which.Text.Should().StartWith(usedCompilerServer
compilerServerMessages.Should().ContainSingle().Which.Text.Should().StartWith(usedCompilerServer
? "CompilerServer: server - server processed compilation - "
: "CompilerServer: tool - using command line tool by design");
}

private static string? GetTargetFramework(string dllPath)
{
var tpa = ((string?)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"))?.Split(Path.PathSeparator) ?? [];
var resolver = new PathAssemblyResolver([.. tpa, dllPath]);
using var mlc = new MetadataLoadContext(resolver);
var asm = mlc.LoadFromAssemblyPath(dllPath);
var attrFullName = typeof(TargetFrameworkAttribute).FullName;
return asm.GetCustomAttributesData()
.Where(a => a.AttributeType.FullName == attrFullName)
.Select(a => a.ConstructorArguments[0].Value)
.FirstOrDefault() as string;
}

public enum Language
{
CSharp,
Expand Down
Loading