diff --git a/src/WixBuildTools.TestSupport/FakeBuildEngine.cs b/src/WixBuildTools.TestSupport/FakeBuildEngine.cs new file mode 100644 index 0000000..2054597 --- /dev/null +++ b/src/WixBuildTools.TestSupport/FakeBuildEngine.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixBuildTools.TestSupport +{ + using System.Collections; + using System.Text; + using Microsoft.Build.Framework; + + public class FakeBuildEngine : IBuildEngine + { + private readonly StringBuilder output = new StringBuilder(); + + public int ColumnNumberOfTaskNode => 0; + + public bool ContinueOnError => false; + + public int LineNumberOfTaskNode => 0; + + public string ProjectFileOfTaskNode => "fake_wix.targets"; + + public string Output => this.output.ToString(); + + public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => throw new System.NotImplementedException(); + + public void LogCustomEvent(CustomBuildEventArgs e) => this.output.AppendLine(e.Message); + + public void LogErrorEvent(BuildErrorEventArgs e) => this.output.AppendLine(e.Message); + + public void LogMessageEvent(BuildMessageEventArgs e) => this.output.AppendLine(e.Message); + + public void LogWarningEvent(BuildWarningEventArgs e) => this.output.AppendLine(e.Message); + } +} diff --git a/src/WixBuildTools.TestSupport/MsbuildRunner.cs b/src/WixBuildTools.TestSupport/MsbuildRunner.cs new file mode 100644 index 0000000..dbfc02f --- /dev/null +++ b/src/WixBuildTools.TestSupport/MsbuildRunner.cs @@ -0,0 +1,117 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixBuildTools.TestSupport +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.IO; + using System.Text; + + public class MsbuildRunner + { + private static readonly string VswhereRelativePath = @"Microsoft Visual Studio\Installer\vswhere.exe"; + private static readonly string[] VswhereFindArguments = new[] { "-property", "installationPath", "-latest" }; + private static readonly string Msbuild15RelativePath = @"MSBuild\15.0\bin\MSBuild.exe"; + + public MsbuildRunner() + { + var vswherePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), VswhereRelativePath); + if (!File.Exists(vswherePath)) + { + throw new InvalidOperationException($"Failed to find vswhere at: {vswherePath}"); + } + + var result = RunProcessCaptureOutput(vswherePath, VswhereFindArguments); + if (result.ExitCode != 0) + { + throw new InvalidOperationException($"Failed to execute vswhere.exe, exit code: {result.ExitCode}"); + } + + this.Msbuild15Path = Path.Combine(result.Output[0], Msbuild15RelativePath); + if (!File.Exists(this.Msbuild15Path)) + { + throw new InvalidOperationException($"Failed to find MSBuild v15 at: {this.Msbuild15Path}"); + } + } + + private string Msbuild15Path { get; } + + public MsbuildRunnerResult Execute(string projectPath, string[] arguments = null) + { + var total = new List + { + projectPath + }; + + if (arguments != null) + { + total.AddRange(arguments); + } + + var workingFolder = Path.GetDirectoryName(projectPath); + return RunProcessCaptureOutput(this.Msbuild15Path, total.ToArray(), workingFolder); + } + + private static MsbuildRunnerResult RunProcessCaptureOutput(string executablePath, string[] arguments = null, string workingFolder = null) + { + var startInfo = new ProcessStartInfo(executablePath) + { + Arguments = CombineArguments(arguments), + CreateNoWindow = true, + RedirectStandardError = true, + RedirectStandardOutput = true, + UseShellExecute = false, + WorkingDirectory = workingFolder, + }; + + var exitCode = 0; + var output = new List(); + + using (var process = Process.Start(startInfo)) + { + process.OutputDataReceived += (s, e) => { if (e.Data != null) output.Add(e.Data); }; + process.ErrorDataReceived += (s, e) => { if (e.Data != null) output.Add(e.Data); }; + + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); + + process.WaitForExit(); + exitCode = process.ExitCode; + } + + return new MsbuildRunnerResult { ExitCode = exitCode, Output = output.ToArray() }; + } + + private static string CombineArguments(string[] arguments) + { + if (arguments == null) + { + return null; + } + + var sb = new StringBuilder(); + + foreach (var arg in arguments) + { + if (sb.Length > 0) + { + sb.Append(' '); + } + + if (arg.IndexOf(' ') > -1) + { + sb.Append("\""); + sb.Append(arg); + sb.Append("\""); + } + else + { + sb.Append(arg); + } + } + + return sb.ToString(); + } + } +} diff --git a/src/WixBuildTools.TestSupport/MsbuildRunnerResult.cs b/src/WixBuildTools.TestSupport/MsbuildRunnerResult.cs new file mode 100644 index 0000000..5610987 --- /dev/null +++ b/src/WixBuildTools.TestSupport/MsbuildRunnerResult.cs @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixBuildTools.TestSupport +{ + using System; + using Xunit; + + public class MsbuildRunnerResult + { + public int ExitCode { get; set; } + + public string[] Output { get; set; } + + public void AssertSuccess() + { + Assert.True(0 == this.ExitCode, $"MSBuild failed unexpectedly. Output:\r\n{String.Join("\r\n", this.Output)}"); + } + } +} diff --git a/src/WixBuildTools.TestSupport/TestData.cs b/src/WixBuildTools.TestSupport/TestData.cs index fde9db5..8587330 100644 --- a/src/WixBuildTools.TestSupport/TestData.cs +++ b/src/WixBuildTools.TestSupport/TestData.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixBuildTools.TestSupport { diff --git a/src/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj b/src/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj index 96baec4..baedb0c 100644 --- a/src/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj +++ b/src/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj @@ -9,6 +9,7 @@ + @@ -16,4 +17,8 @@ + + + +