main
cs 464 lines 19.9 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 WixToolsetTest.CoreIntegration
4 {
5 using System;
6 using System.IO;
7 using System.Linq;
8 using WixInternal.TestSupport;
9 using WixInternal.Core.TestPackage;
10 using WixToolset.Data;
11 using WixToolset.Data.Symbols;
12 using WixToolset.Data.WindowsInstaller;
13 using Xunit;
14
15 // When these tests are run repeatedly, they will expose an issue
16 // in the Windows Installer where ICE validations will occasionally
17 // fail to send all error/warning messages. The inconsistency
18 // obviously wreaks havoc on the tests.
19 //
20 // These tests are still interesting (and complex) enough to keep
21 // around for manual testing. Uncomment or define the following
22 // line to do so.
23 #if DISABLE_VALIDATION_TESTS_DUE_TO_WINDOWS_INSTALLER_INCONSISTENCIES
24 public class ValidationFixture
25 {
26 [Fact]
27 public void CanBuildAndValidateSimpleModule()
28 {
29 var folder = TestData.Get(@"TestData\SimpleModule");
30
31 using (var fs = new DisposableFileSystem())
32 {
33 var intermediateFolder = fs.GetFolder();
34
35 var result = WixRunner.Execute(new[]
36 {
37 "build",
38 "-arch", "arm64",
39 Path.Combine(folder, "Module.wxs"),
40 "-loc", Path.Combine(folder, "Module.en-us.wxl"),
41 "-bindpath", Path.Combine(folder, "data"),
42 "-intermediateFolder", intermediateFolder,
43 "-o", Path.Combine(intermediateFolder, @"bin\test.msm")
44 });
45
46 result.AssertSuccess();
47
48 var msmPath = Path.Combine(intermediateFolder, @"bin\test.msm");
49 Assert.True(File.Exists(msmPath));
50 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
51
52 var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
53 var section = intermediate.Sections.Single();
54
55 var dirSymbols = section.Symbols.OfType<DirectorySymbol>().OrderBy(d => d.Id.Id).ToList();
56 WixAssert.CompareLineByLine(new[]
57 {
58 "MergeRedirectFolder\tTARGETDIR\t.",
59 "NotTheMergeRedirectFolder\tTARGETDIR\t.",
60 "TARGETDIR\t\tSourceDir"
61 }, dirSymbols.Select(d => String.Join("\t", d.Id.Id, d.ParentDirectoryRef, d.Name)).ToArray());
62
63 var fileSymbols = section.Symbols.OfType<FileSymbol>().OrderBy(d => d.Id.Id).ToList();
64 WixAssert.CompareLineByLine(new[]
65 {
66 $"File1\t{Path.Combine(folder, @"data\test.txt")}\ttest.txt",
67 $"File2\t{Path.Combine(folder, @"data\test.txt")}\ttest.txt",
68 }, fileSymbols.Select(fileSymbol => String.Join("\t", fileSymbol.Id.Id, fileSymbol[FileSymbolFields.Source].AsPath().Path, fileSymbol[FileSymbolFields.Source].PreviousValue.AsPath().Path)).ToArray());
69
70 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
71 var fileRows = data.Tables["File"].Rows;
72 WixAssert.CompareLineByLine(new[]
73 {
74 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
75 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
76 }, fileRows.Select(r => r.FieldAsString(0)).ToArray());
77
78 var cabPath = Path.Combine(intermediateFolder, "msm-test.cab");
79 Query.ExtractStream(msmPath, "MergeModule.CABinet", cabPath);
80 var files = Query.GetCabinetFiles(cabPath);
81 WixAssert.CompareLineByLine(new[]
82 {
83 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
84 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
85 }, files.Select(f => Path.Combine(f.Path, f.Name)).ToArray());
86
87 var rows = Query.QueryDatabase(msmPath, new[] { "_SummaryInformation" });
88 WixAssert.CompareLineByLine(new[]
89 {
90 "_SummaryInformation:Title\tMerge Module",
91 "_SummaryInformation:Subject\tMergeModule1",
92 "_SummaryInformation:Author\tExample Company",
93 "_SummaryInformation:Keywords\tMergeModule, MSI, database",
94 "_SummaryInformation:Comments\tThis merge module contains the logic and data required to install MergeModule1.",
95 "_SummaryInformation:Template\tArm64;1033",
96 "_SummaryInformation:CodePage\t1252",
97 "_SummaryInformation:PageCount\t500",
98 "_SummaryInformation:WordCount\t0",
99 "_SummaryInformation:CharacterCount\t0",
100 "_SummaryInformation:Security\t2",
101 }, rows);
102
103 var validationResult = WixRunner.Execute(new[]
104 {
105 "msi", "validate",
106 "-intermediateFolder", intermediateFolder,
107 msmPath
108 });
109 validationResult.AssertSuccess();
110 }
111 }
112
113 [Fact]
114 public void CanBuildAndValidateSimpleModuleWithProperty()
115 {
116 var folder = TestData.Get(@"TestData\SimpleModuleWithProperty");
117
118 using (var fs = new DisposableFileSystem())
119 {
120 var intermediateFolder = fs.GetFolder();
121
122 var result = WixRunner.Execute(new[]
123 {
124 "build",
125 "-arch", "arm64",
126 Path.Combine(folder, "Module.wxs"),
127 "-loc", Path.Combine(folder, "Module.en-us.wxl"),
128 "-bindpath", Path.Combine(folder, "data"),
129 "-intermediateFolder", intermediateFolder,
130 "-o", Path.Combine(intermediateFolder, @"bin\test.msm")
131 });
132
133 result.AssertSuccess();
134
135 var msmPath = Path.Combine(intermediateFolder, @"bin\test.msm");
136 Assert.True(File.Exists(msmPath));
137 Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb")));
138
139 var validationResult = WixRunner.Execute(new[]
140 {
141 "msi", "validate",
142 "-intermediateFolder", intermediateFolder,
143 msmPath
144 });
145 validationResult.AssertSuccess();
146 }
147 }
148
149 [Fact]
150 public void CanMergeModuleAndValidate()
151 {
152 var msmFolder = TestData.Get(@"TestData\SimpleModule");
153 var folder = TestData.Get(@"TestData\SimpleMerge");
154
155 using (var fs = new DisposableFileSystem())
156 {
157 var intermediateFolder = fs.GetFolder();
158 var msiPath = Path.Combine(intermediateFolder, @"bin\test.msi");
159 var cabPath = Path.Combine(intermediateFolder, @"bin\cab1.cab");
160
161 var msmResult = WixRunner.Execute(new[]
162 {
163 "build",
164 Path.Combine(msmFolder, "Module.wxs"),
165 "-loc", Path.Combine(msmFolder, "Module.en-us.wxl"),
166 "-bindpath", Path.Combine(msmFolder, "data"),
167 "-intermediateFolder", intermediateFolder,
168 "-o", Path.Combine(intermediateFolder, "bin", "test", "test.msm")
169 });
170
171 msmResult.AssertSuccess();
172
173 var result = WixRunner.Execute(new[]
174 {
175 "build",
176 Path.Combine(folder, "Package.wxs"),
177 "-loc", Path.Combine(folder, "Package.en-us.wxl"),
178 "-bindpath", Path.Combine(intermediateFolder, "bin", "test"),
179 "-intermediateFolder", intermediateFolder,
180 "-o", msiPath
181 });
182
183 result.AssertSuccess();
184
185 var validationResult = WixRunner.Execute(new[]
186 {
187 "msi", "validate",
188 "-intermediateFolder", intermediateFolder,
189 msiPath
190 });
191 validationResult.AssertSuccess();
192
193 var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
194 var section = intermediate.Sections.Single();
195 Assert.Empty(section.Symbols.OfType<FileSymbol>());
196
197 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
198 Assert.Empty(data.Tables["File"].Rows);
199
200 var results = Query.QueryDatabase(msiPath, new[] { "File" });
201 WixAssert.CompareLineByLine(new[]
202 {
203 "File:File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile1.txt\t17\t\t\t512\t1",
204 "File:File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile2.txt\t17\t\t\t512\t2",
205 }, results);
206
207 var files = Query.GetCabinetFiles(cabPath);
208 WixAssert.CompareLineByLine(new[]
209 {
210 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
211 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE"
212 }, files.Select(f => f.Name).ToArray());
213 }
214 }
215
216 [Fact]
217 public void CanValidateMsiWithIceIssues()
218 {
219 var folder = TestData.Get(@"TestData");
220
221 var testLogsFolder = TestData.GetUnitTestLogsFolder();
222 File.Delete(Path.Combine(testLogsFolder, "build.txt"));
223 File.Delete(Path.Combine(testLogsFolder, "validate.txt"));
224
225 using (var fs = new DisposableFileSystem())
226 {
227 var baseFolder = fs.GetFolder();
228 var intermediateFolder = Path.Combine(baseFolder, "obj");
229 var msiPath = Path.Combine(baseFolder, @"bin", "CanValidateMsiWithIceIssues.msi");
230
231 var result = WixRunner.Execute(new[]
232 {
233 "build",
234 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
235 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
236 "-intermediateFolder", intermediateFolder,
237 "-o", msiPath,
238 });
239
240 File.WriteAllLines(Path.Combine(testLogsFolder, "build.txt"), result.Messages.Select(m => m.ToString()));
241
242 result.AssertSuccess();
243
244 var validationResult = WixRunner.Execute(new[]
245 {
246 "msi", "validate",
247 "-intermediateFolder", intermediateFolder,
248 msiPath
249 });
250
251 File.WriteAllLines(Path.Combine(testLogsFolder, "validate.txt"), validationResult.Messages.Select(m => m.ToString()));
252
253 Assert.Equal(1076, validationResult.ExitCode);
254
255 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
256 WixAssert.CompareLineByLine(new[]
257 {
258 @"ICE12: CustomAction: CausesICE12Error is of type: 35. Therefore it must come after CostFinalize @ 1000 in Seq Table: InstallExecuteSequence. CA Seq#: 49",
259 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
260 }, messages);
261 }
262 }
263
264 [Fact]
265 public void CanValidateMsiSuppressIceError()
266 {
267 var folder = TestData.Get(@"TestData");
268
269 var testLogsFolder = TestData.GetUnitTestLogsFolder();
270 File.Delete(Path.Combine(testLogsFolder, "build.txt"));
271 File.Delete(Path.Combine(testLogsFolder, "validate.txt"));
272
273 using (var fs = new DisposableFileSystem())
274 {
275 var baseFolder = fs.GetFolder();
276 var intermediateFolder = Path.Combine(baseFolder, "obj");
277 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
278
279 var result = WixRunner.Execute(new[]
280 {
281 "build",
282 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
283 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
284 "-intermediateFolder", intermediateFolder,
285 "-o", msiPath,
286 });
287
288 File.WriteAllLines(Path.Combine(testLogsFolder, "build.txt"), result.Messages.Select(m => m.ToString()));
289
290 result.AssertSuccess();
291
292 var validationResult = WixRunner.Execute(warningsAsErrors: false, new[]
293 {
294 "msi", "validate",
295 "-intermediateFolder", intermediateFolder,
296 "-sice", "ICE12",
297 msiPath
298 });
299
300 File.WriteAllLines(Path.Combine(testLogsFolder, "validate.txt"), validationResult.Messages.Select(m => m.ToString()));
301
302 validationResult.AssertSuccess();
303
304 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
305 WixAssert.CompareLineByLine(new[]
306 {
307 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
308 }, messages);
309 }
310 }
311
312 [Fact]
313 public void CanValidateMsiWithWarningsAsErrors()
314 {
315 var folder = TestData.Get(@"TestData");
316
317 using (var fs = new DisposableFileSystem())
318 {
319 var baseFolder = fs.GetFolder();
320 var intermediateFolder = Path.Combine(baseFolder, "obj");
321 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
322
323 var result = WixRunner.Execute(new[]
324 {
325 "build",
326 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
327 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
328 "-intermediateFolder", intermediateFolder,
329 "-o", msiPath,
330 });
331
332 result.AssertSuccess();
333
334 var validationResult = WixRunner.Execute(warningsAsErrors: true, new[]
335 {
336 "msi", "validate",
337 "-intermediateFolder", intermediateFolder,
338 "-sice", "ICE12",
339 msiPath
340 });
341
342 Assert.Equal(1076, validationResult.ExitCode);
343
344 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
345 WixAssert.CompareLineByLine(new[]
346 {
347 @"ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only."
348 }, messages);
349 }
350 }
351
352 [Fact]
353 public void CanValidateArm64Msi()
354 {
355 var folder = TestData.Get(@"TestData");
356
357 using (var fs = new DisposableFileSystem())
358 {
359 var baseFolder = fs.GetFolder();
360 var intermediateFolder = Path.Combine(baseFolder, "obj");
361 var msiPath = Path.Combine(baseFolder, @"bin", "test.msi");
362
363 var result = WixRunner.Execute(new[]
364 {
365 "build",
366 "-arch", "arm64",
367 Path.Combine(folder, "Validation", "PackageWithIceIssues.wxs"),
368 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
369 "-intermediateFolder", intermediateFolder,
370 "-o", msiPath,
371 });
372
373 result.AssertSuccess();
374
375 var validationResult = WixRunner.Execute(warningsAsErrors: true, new[]
376 {
377 "msi", "validate",
378 "-intermediateFolder", intermediateFolder,
379 msiPath
380 });
381
382 var messages = validationResult.Messages.Select(m => m.ToString()).ToArray();
383 WixAssert.CompareLineByLine(new[]
384 {
385 "ICE12: CustomAction: CausesICE12Error is of type: 35. Therefore it must come after CostFinalize @ 1000 in Seq Table: InstallExecuteSequence. CA Seq#: 49",
386 "ICE46: Property 'Myproperty' referenced in column 'LaunchCondition'.'Condition' of row 'Myproperty' differs from a defined property by case only.",
387 }, messages);
388
389 Assert.Equal(1076, validationResult.ExitCode);
390 }
391 }
392
393 [Fact]
394 public void CanMergeArm64ModuleAndValidate()
395 {
396 var msmFolder = TestData.Get(@"TestData\SimpleModule");
397 var folder = TestData.Get(@"TestData\SimpleMerge");
398
399 using (var fs = new DisposableFileSystem())
400 {
401 var intermediateFolder = fs.GetFolder();
402 var msiPath = Path.Combine(intermediateFolder, @"bin\test.msi");
403 var cabPath = Path.Combine(intermediateFolder, @"bin\cab1.cab");
404
405 var msmResult = WixRunner.Execute(new[]
406 {
407 "build",
408 "-arch", "arm64",
409 Path.Combine(msmFolder, "Module.wxs"),
410 "-loc", Path.Combine(msmFolder, "Module.en-us.wxl"),
411 "-bindpath", Path.Combine(msmFolder, "data"),
412 "-intermediateFolder", intermediateFolder,
413 "-o", Path.Combine(intermediateFolder, "bin", "test", "test.msm")
414 });
415
416 msmResult.AssertSuccess();
417
418 var result = WixRunner.Execute(new[]
419 {
420 "build",
421 "-arch", "arm64",
422 Path.Combine(folder, "Package.wxs"),
423 "-loc", Path.Combine(folder, "Package.en-us.wxl"),
424 "-bindpath", Path.Combine(intermediateFolder, "bin", "test"),
425 "-intermediateFolder", intermediateFolder,
426 "-o", msiPath
427 });
428
429 result.AssertSuccess();
430
431 var validationResult = WixRunner.Execute(new[]
432 {
433 "msi", "validate",
434 "-sice", "ICE80", // Prevent whinging about 32-bit directories.
435 "-intermediateFolder", intermediateFolder,
436 msiPath
437 });
438 validationResult.AssertSuccess();
439
440 var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
441 var section = intermediate.Sections.Single();
442 Assert.Empty(section.Symbols.OfType<FileSymbol>());
443
444 var data = WindowsInstallerData.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb"));
445 Assert.Empty(data.Tables["File"].Rows);
446
447 var results = Query.QueryDatabase(msiPath, new[] { "File" });
448 WixAssert.CompareLineByLine(new[]
449 {
450 "File:File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent1.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile1.txt\t17\t\t\t512\t1",
451 "File:File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tModuleComponent2.243FB739_4D05_472F_9CFB_EF6B1017B6DE\tfile2.txt\t17\t\t\t512\t2",
452 }, results);
453
454 var files = Query.GetCabinetFiles(cabPath);
455 WixAssert.CompareLineByLine(new[]
456 {
457 "File1.243FB739_4D05_472F_9CFB_EF6B1017B6DE",
458 "File2.243FB739_4D05_472F_9CFB_EF6B1017B6DE"
459 }, files.Select(f => f.Name).ToArray());
460 }
461 }
462 }
463 #endif
464 }