Add support for testing with MSBuild
Rob Mensching committed
Jul 30, 2018 at 01:49 UTC
a7f145fa0669ab988e69e031f346360072306a94
5 files changed
+175
-1
src/WixBuildTools.TestSupport/FakeBuildEngine.cs
new
+33
@@ -0,0 +1,33 @@
1
+// 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.
2
+
3
+namespace WixBuildTools.TestSupport
4
+{
5
+ using System.Collections;
6
+ using System.Text;
7
+ using Microsoft.Build.Framework;
8
+
9
+ public class FakeBuildEngine : IBuildEngine
10
+ {
11
+ private readonly StringBuilder output = new StringBuilder();
12
+
13
+ public int ColumnNumberOfTaskNode => 0;
14
+
15
+ public bool ContinueOnError => false;
16
+
17
+ public int LineNumberOfTaskNode => 0;
18
+
19
+ public string ProjectFileOfTaskNode => "fake_wix.targets";
20
+
21
+ public string Output => this.output.ToString();
22
+
23
+ public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs) => throw new System.NotImplementedException();
24
+
25
+ public void LogCustomEvent(CustomBuildEventArgs e) => this.output.AppendLine(e.Message);
26
+
27
+ public void LogErrorEvent(BuildErrorEventArgs e) => this.output.AppendLine(e.Message);
28
+
29
+ public void LogMessageEvent(BuildMessageEventArgs e) => this.output.AppendLine(e.Message);
30
+
31
+ public void LogWarningEvent(BuildWarningEventArgs e) => this.output.AppendLine(e.Message);
32
+ }
33
+}
src/WixBuildTools.TestSupport/MsbuildRunner.cs
new
+117
@@ -0,0 +1,117 @@
1
+// 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.
2
+
3
+namespace WixBuildTools.TestSupport
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Diagnostics;
8
+ using System.IO;
9
+ using System.Text;
10
+
11
+ public class MsbuildRunner
12
+ {
13
+ private static readonly string VswhereRelativePath = @"Microsoft Visual Studio\Installer\vswhere.exe";
14
+ private static readonly string[] VswhereFindArguments = new[] { "-property", "installationPath", "-latest" };
15
+ private static readonly string Msbuild15RelativePath = @"MSBuild\15.0\bin\MSBuild.exe";
16
+
17
+ public MsbuildRunner()
18
+ {
19
+ var vswherePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), VswhereRelativePath);
20
+ if (!File.Exists(vswherePath))
21
+ {
22
+ throw new InvalidOperationException($"Failed to find vswhere at: {vswherePath}");
23
+ }
24
+
25
+ var result = RunProcessCaptureOutput(vswherePath, VswhereFindArguments);
26
+ if (result.ExitCode != 0)
27
+ {
28
+ throw new InvalidOperationException($"Failed to execute vswhere.exe, exit code: {result.ExitCode}");
29
+ }
30
+
31
+ this.Msbuild15Path = Path.Combine(result.Output[0], Msbuild15RelativePath);
32
+ if (!File.Exists(this.Msbuild15Path))
33
+ {
34
+ throw new InvalidOperationException($"Failed to find MSBuild v15 at: {this.Msbuild15Path}");
35
+ }
36
+ }
37
+
38
+ private string Msbuild15Path { get; }
39
+
40
+ public MsbuildRunnerResult Execute(string projectPath, string[] arguments = null)
41
+ {
42
+ var total = new List<string>
43
+ {
44
+ projectPath
45
+ };
46
+
47
+ if (arguments != null)
48
+ {
49
+ total.AddRange(arguments);
50
+ }
51
+
52
+ var workingFolder = Path.GetDirectoryName(projectPath);
53
+ return RunProcessCaptureOutput(this.Msbuild15Path, total.ToArray(), workingFolder);
54
+ }
55
+
56
+ private static MsbuildRunnerResult RunProcessCaptureOutput(string executablePath, string[] arguments = null, string workingFolder = null)
57
+ {
58
+ var startInfo = new ProcessStartInfo(executablePath)
59
+ {
60
+ Arguments = CombineArguments(arguments),
61
+ CreateNoWindow = true,
62
+ RedirectStandardError = true,
63
+ RedirectStandardOutput = true,
64
+ UseShellExecute = false,
65
+ WorkingDirectory = workingFolder,
66
+ };
67
+
68
+ var exitCode = 0;
69
+ var output = new List<string>();
70
+
71
+ using (var process = Process.Start(startInfo))
72
+ {
73
+ process.OutputDataReceived += (s, e) => { if (e.Data != null) output.Add(e.Data); };
74
+ process.ErrorDataReceived += (s, e) => { if (e.Data != null) output.Add(e.Data); };
75
+
76
+ process.BeginErrorReadLine();
77
+ process.BeginOutputReadLine();
78
+
79
+ process.WaitForExit();
80
+ exitCode = process.ExitCode;
81
+ }
82
+
83
+ return new MsbuildRunnerResult { ExitCode = exitCode, Output = output.ToArray() };
84
+ }
85
+
86
+ private static string CombineArguments(string[] arguments)
87
+ {
88
+ if (arguments == null)
89
+ {
90
+ return null;
91
+ }
92
+
93
+ var sb = new StringBuilder();
94
+
95
+ foreach (var arg in arguments)
96
+ {
97
+ if (sb.Length > 0)
98
+ {
99
+ sb.Append(' ');
100
+ }
101
+
102
+ if (arg.IndexOf(' ') > -1)
103
+ {
104
+ sb.Append("\"");
105
+ sb.Append(arg);
106
+ sb.Append("\"");
107
+ }
108
+ else
109
+ {
110
+ sb.Append(arg);
111
+ }
112
+ }
113
+
114
+ return sb.ToString();
115
+ }
116
+ }
117
+}
src/WixBuildTools.TestSupport/MsbuildRunnerResult.cs
new
+19
@@ -0,0 +1,19 @@
1
+// 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.
2
+
3
+namespace WixBuildTools.TestSupport
4
+{
5
+ using System;
6
+ using Xunit;
7
+
8
+ public class MsbuildRunnerResult
9
+ {
10
+ public int ExitCode { get; set; }
11
+
12
+ public string[] Output { get; set; }
13
+
14
+ public void AssertSuccess()
15
+ {
16
+ Assert.True(0 == this.ExitCode, $"MSBuild failed unexpectedly. Output:\r\n{String.Join("\r\n", this.Output)}");
17
+ }
18
+ }
19
+}
src/WixBuildTools.TestSupport/TestData.cs
+1
-1
@@ -1,4 +1,4 @@
1
-// 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.
1
+// 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.
2
3
namespace WixBuildTools.TestSupport
4
{
src/WixBuildTools.TestSupport/WixBuildTools.TestSupport.csproj
+5
@@ -9,6 +9,7 @@
9
</PropertyGroup>
10
11
<ItemGroup>
12
+ <PackageReference Include="Microsoft.Build.Tasks.Core" Version="14.3" />
13
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" Version="4.0.*" NoWarn="NU1701" />
14
</ItemGroup>
15
@@ -16,4 +17,8 @@
17
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63102-01" PrivateAssets="All"/>
18
<PackageReference Include="Nerdbank.GitVersioning" Version="2.1.65" PrivateAssets="all" />
19
</ItemGroup>
20
+
21
+ <ItemGroup>
22
+ <PackageReference Include="xunit" Version="2.4.0" />
23
+ </ItemGroup>
24
</Project>