main
cs 249 lines 12.1 KB
Raw
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 WixTestTools
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Text;
9
10 public partial class BundleInstaller : IDisposable
11 {
12 public BundleInstaller(WixTestContext testContext, string name)
13 {
14 this.Bundle = Path.Combine(testContext.TestDataFolder, $"{name}.exe");
15 this.BundlePdb = Path.Combine(testContext.TestDataFolder, $"{name}.wixpdb");
16 this.TestContext = testContext;
17 this.TestGroupName = testContext.TestGroupName;
18 this.TestName = testContext.TestName;
19 }
20
21 public string Bundle { get; }
22
23 private WixTestContext TestContext { get; }
24
25 public string TestGroupName { get; }
26
27 public string TestName { get; }
28
29 public int? AlternateExitCode { get; set; }
30
31 public string LogDirectory { get; set; }
32
33 public int? LastExitCode { get; set; }
34
35 /// <summary>
36 /// Runs the bundle asking for help.
37 /// </summary>
38 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
39 /// <param name="arguments">Optional arguments to pass to the tool.</param>
40 /// <returns>Path to the generated log file.</returns>
41 public string Help(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
42 {
43 var newArgumentList = new List<string>();
44 newArgumentList.Add("-help");
45 newArgumentList.AddRange(arguments);
46 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray());
47 }
48
49 /// <summary>
50 /// Installs the bundle with optional arguments.
51 /// </summary>
52 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
53 /// <param name="arguments">Optional arguments to pass to the tool.</param>
54 /// <returns>Path to the generated log file.</returns>
55 public string Install(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
56 {
57 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Install, arguments);
58 }
59
60 /// <summary>
61 /// Installs the bundle with optional arguments.
62 /// </summary>
63 /// <param name="bundlePath">This should be the bundle in the package cache.</param>
64 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
65 /// <param name="arguments">Optional arguments to pass to the tool.</param>
66 /// <returns>Path to the generated log file.</returns>
67 public string Install(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
68 {
69 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Install, arguments, bundlePath: bundlePath);
70 }
71
72 /// <summary>
73 /// Calls Layout for the bundle with optional arguments.
74 /// </summary>
75 /// <param name="layoutDirectory">The destination directory.</param>
76 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
77 /// <param name="arguments">Optional arguments to pass to the tool.</param>
78 /// <returns>Path to the generated log file.</returns>
79 public string Layout(string layoutDirectory, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
80 {
81 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.AdministrativeInstall, arguments, layoutDirectory: layoutDirectory);
82 }
83
84 /// <summary>
85 /// Calls Layout for the bundle with optional arguments.
86 /// </summary>
87 /// <param name="bundlePath">Path to the bundle to run.</param>
88 /// <param name="layoutDirectory">The destination directory.</param>
89 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
90 /// <param name="arguments">Optional arguments to pass to the tool.</param>
91 /// <returns>Path to the generated log file.</returns>
92 public string Layout(string bundlePath, string layoutDirectory, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
93 {
94 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.AdministrativeInstall, arguments, bundlePath: bundlePath, layoutDirectory: layoutDirectory);
95 }
96
97 /// <summary>
98 /// Modify the bundle with optional arguments.
99 /// </summary>
100 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
101 /// <param name="arguments">Optional arguments to pass to the tool.</param>
102 /// <returns>Path to the generated log file.</returns>
103 public string Modify(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
104 {
105 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Modify, arguments);
106 }
107
108 /// <summary>
109 /// Modify the bundle with optional arguments.
110 /// </summary>
111 /// <param name="bundlePath">This should be the bundle in the package cache.</param>
112 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
113 /// <param name="arguments">Optional arguments to pass to the tool.</param>
114 /// <returns>Path to the generated log file.</returns>
115 public string Modify(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
116 {
117 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Modify, arguments, bundlePath: bundlePath);
118 }
119
120 /// <summary>
121 /// Repairs the bundle with optional arguments.
122 /// </summary>
123 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
124 /// <param name="arguments">Optional arguments to pass to the tool.</param>
125 /// <returns>Path to the generated log file.</returns>
126 public string Repair(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
127 {
128 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Repair, arguments);
129 }
130
131 /// <summary>
132 /// Uninstalls the bundle with optional arguments.
133 /// </summary>
134 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
135 /// <param name="arguments">Optional arguments to pass to the tool.</param>
136 /// <returns>Path to the generated log file.</returns>
137 public string Uninstall(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
138 {
139 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Uninstall, arguments);
140 }
141
142 /// <summary>
143 /// Uninstalls the bundle at the given path with optional arguments.
144 /// </summary>
145 /// <param name="bundlePath">This should be the bundle in the package cache.</param>
146 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
147 /// <param name="arguments">Optional arguments to pass to the tool.</param>
148 /// <returns>Path to the generated log file.</returns>
149 public string Uninstall(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
150 {
151 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Uninstall, arguments, bundlePath: bundlePath);
152 }
153
154 /// <summary>
155 /// Uninstalls the bundle unsafely with optional arguments.
156 /// </summary>
157 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
158 /// <param name="arguments">Optional arguments to pass to the tool.</param>
159 /// <returns>Path to the generated log file.</returns>
160 public string UnsafeUninstall(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
161 {
162 var newArgumentList = new List<string>();
163 newArgumentList.Add("-unsafeuninstall");
164 newArgumentList.AddRange(arguments);
165 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray());
166 }
167
168 /// <summary>
169 /// Uninstalls the bundle unsafely at the given path with optional arguments.
170 /// </summary>
171 /// <param name="bundlePath">This should be the bundle in the package cache.</param>
172 /// <param name="expectedExitCode">Expected exit code, defaults to success.</param>
173 /// <param name="arguments">Optional arguments to pass to the tool.</param>
174 /// <returns>Path to the generated log file.</returns>
175 public string UnsafeUninstall(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments)
176 {
177 var newArgumentList = new List<string>();
178 newArgumentList.Add("-unsafeuninstall");
179 newArgumentList.AddRange(arguments);
180 return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray(), bundlePath: bundlePath);
181 }
182
183 /// <summary>
184 /// Executes the bundle with optional arguments.
185 /// </summary>
186 /// <param name="expectedExitCode">Expected exit code.</param>
187 /// <param name="mode">Install mode.</param>
188 /// <param name="arguments">Optional arguments to pass to the tool.</param>
189 /// <returns>Path to the generated log file.</returns>
190 private string RunBundleWithArguments(int expectedExitCode, MSIExec.MSIExecMode mode, string[] arguments, bool assertOnError = true, string bundlePath = null, string layoutDirectory = null)
191 {
192 TestTool bundle = new TestTool(bundlePath ?? this.Bundle);
193 var sb = new StringBuilder();
194
195 // Be sure to run silent.
196 sb.Append(" -quiet");
197
198 // Generate the log file name.
199 string logFile = Path.Combine(this.LogDirectory ?? Path.GetTempPath(), String.Format("{0}_{1}_{2:yyyyMMddhhmmss}_{4}_{3}.log", this.TestGroupName, this.TestName, DateTime.UtcNow, Path.GetFileNameWithoutExtension(this.Bundle), mode));
200 sb.AppendFormat(" -log \"{0}\"", logFile);
201
202 // Set operation.
203 switch (mode)
204 {
205 case MSIExec.MSIExecMode.AdministrativeInstall:
206 sb.Append($" -layout \"{layoutDirectory}\"");
207 break;
208
209 case MSIExec.MSIExecMode.Modify:
210 sb.Append(" -modify");
211 break;
212
213 case MSIExec.MSIExecMode.Repair:
214 sb.Append(" -repair");
215 break;
216
217 case MSIExec.MSIExecMode.Cleanup:
218 case MSIExec.MSIExecMode.Uninstall:
219 sb.Append(" -uninstall");
220 break;
221 }
222
223 // Add additional arguments.
224 if (null != arguments)
225 {
226 sb.Append(" ");
227 sb.Append(String.Join(" ", arguments));
228 }
229
230 // Set the arguments.
231 bundle.Arguments = sb.ToString();
232
233 // Run the tool and assert the expected code.
234 bundle.ExpectedExitCode = expectedExitCode;
235 bundle.AlternateExitCode = this.AlternateExitCode;
236 var result = bundle.Run(assertOnError);
237 this.LastExitCode = result.ExitCode;
238
239 // Return the log file name.
240 return logFile;
241 }
242
243 public void Dispose()
244 {
245 string[] args = { "-burn.ignoredependencies=ALL" };
246 this.RunBundleWithArguments((int)MSIExec.MSIExecReturnCode.SUCCESS, MSIExec.MSIExecMode.Cleanup, args, assertOnError: false);
247 }
248 }
249 }