File: CodeTaskFactoryEmbeddedFileInBinlogTestHelper.cs
Web Access
Project: ..\..\..\src\Tasks.UnitTests\Microsoft.Build.Tasks.UnitTests.csproj (Microsoft.Build.Tasks.UnitTests)
// 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.IO.Compression;
using Microsoft.Build.Logging;
using Microsoft.Build.UnitTests;
using Shouldly;
using Xunit;
 
namespace Microsoft.Build.Tasks.UnitTests
{
    internal enum FactoryType
    {
        CodeTaskFactory,
        RoslynCodeTaskFactory,
    }
 
    internal static class CodeTaskFactoryEmbeddedFileInBinlogTestHelper
    {
        internal static void BuildFromSourceAndCheckForEmbeddedFileInBinlog(
            FactoryType factoryType,
            string taskName,
            string sourceContent,
            bool buildShouldSucceed)
        {
            using var env = TestEnvironment.Create();
 
            TransientTestFolder folder = env.CreateFolder(createFolder: true);
 
            var sourceClass = env.CreateFile(folder, $"{taskName}.cs", sourceContent);
 
            string projectFileContents = $"""
                <Project>
 
                  <UsingTask
                    TaskName="{taskName}"
                    TaskFactory="{factoryType}"
                    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
                    <Task>
                      <Code Type="Class" Language="cs" Source="{sourceClass.Path}">
                      </Code>
                    </Task>
                  </UsingTask>
 
                    <Target Name="SayHello">
                        <{taskName} />
                    </Target>
 
                </Project>
                """;
 
            TransientTestFile binlog = env.ExpectFile(".binlog");
 
            var binaryLogger = new BinaryLogger()
            {
                Parameters = $"LogFile={binlog.Path}",
                CollectProjectImports = BinaryLogger.ProjectImportsCollectionMode.ZipFile,
            };
 
            Helpers.BuildProjectWithNewOMAndBinaryLogger(projectFileContents, binaryLogger, out bool result, out string projectDirectoryPath);
 
            Assert.Equal(buildShouldSucceed, result);
 
            string projectImportsZipPath = Path.ChangeExtension(binlog.Path, ".ProjectImports.zip");
            using var fileStream = new FileStream(projectImportsZipPath, FileMode.Open);
            using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
 
            // A path like "C:\path" in ZipArchive is saved as "C\path"
            // For unix-based systems path uses '/'
            projectDirectoryPath = NativeMethodsShared.IsWindows ? projectDirectoryPath.Replace(":\\", "\\") : projectDirectoryPath.Replace("/", "\\");
 
            // Can't just compare `Name` because `ZipArchive` does not handle unix directory separators well
            // thus producing garbled fully qualified paths in the actual .ProjectImports.zip entries
            zipArchive.Entries.ShouldContain(
                zE => zE.FullName.StartsWith(projectDirectoryPath) && zE.Name.EndsWith($"{taskName}-compilation-file.tmp"),
                $"Binlog's embedded files didn't have the expected '{projectDirectoryPath}/{{guid}}-{taskName}-compilation-file.tmp'.");
        }
 
        internal static void BuildAndCheckForEmbeddedFileInBinlog(
            FactoryType factoryType,
            string taskName,
            string taskXml,
            bool buildShouldSucceed)
        {
            string projectFileContents = $"""
                <Project>
 
                  <UsingTask
                    TaskName="{taskName}"
                    TaskFactory="{factoryType}"
                    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
                    {taskXml}
                  </UsingTask>
 
                    <Target Name="SayHello">
                        <{taskName} />
                    </Target>
 
                </Project>
                """;
 
            using var env = TestEnvironment.Create();
 
            TransientTestFile binlog = env.ExpectFile(".binlog");
 
            var binaryLogger = new BinaryLogger()
            {
                Parameters = $"LogFile={binlog.Path}",
                CollectProjectImports = BinaryLogger.ProjectImportsCollectionMode.ZipFile,
            };
 
            Helpers.BuildProjectWithNewOMAndBinaryLogger(projectFileContents, binaryLogger, out bool result, out string projectDirectory);
 
            Assert.Equal(buildShouldSucceed, result);
 
            string projectImportsZipPath = Path.ChangeExtension(binlog.Path, ".ProjectImports.zip");
            using var fileStream = new FileStream(projectImportsZipPath, FileMode.Open);
            using var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Read);
 
            // A path like "C:\path" in ZipArchive is saved as "C\path"
            // For unix-based systems path uses '/'
            projectDirectory = NativeMethodsShared.IsWindows ? projectDirectory.Replace(":\\", "\\") : projectDirectory.Replace("/", "\\");
 
            // Can't just compare `Name` because `ZipArchive` does not handle unix directory separators well
            // thus producing garbled fully qualified paths in the actual .ProjectImports.zip entries
            zipArchive.Entries.ShouldContain(
                zE => zE.FullName.StartsWith(projectDirectory) && zE.Name.EndsWith($"{taskName}-compilation-file.tmp"),
                $"Binlog's embedded files didn't have the expected '{projectDirectory}/{{guid}}-{taskName}-compilation-file.tmp'.");
        }
    }
}