main
cs 411 lines 22.5 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.Collections.Generic;
6 using System.IO;
7 using System.Linq;
8 using System.Xml;
9 using WixInternal.TestSupport;
10 using WixToolset.Core.Burn.Bundles;
11 using WixInternal.Core.TestPackage;
12 using WixToolset.Data;
13 using WixToolset.Data.WindowsInstaller;
14 using WixToolset.Data.WindowsInstaller.Rows;
15 using Xunit;
16
17 public class ContainerFixture
18 {
19 [Fact]
20 public void CanBuildWithCustomAttachedContainer()
21 {
22 var folder = TestData.Get(@"TestData");
23
24 using (var fs = new DisposableFileSystem())
25 {
26 var baseFolder = fs.GetFolder();
27 var intermediateFolder = Path.Combine(baseFolder, "obj");
28 var binFolder = Path.Combine(baseFolder, "bin");
29 var bundlePath = Path.Combine(binFolder, "test.exe");
30 var baFolderPath = Path.Combine(baseFolder, "ba");
31 var extractFolderPath = Path.Combine(baseFolder, "extract");
32
33 this.BuildMsis(folder, intermediateFolder, binFolder, buildToSubfolder: true);
34
35 var result = WixRunner.Execute(new[]
36 {
37 "build",
38 Path.Combine(folder, "Container", "HarvestIntoAttachedContainer.wxs"),
39 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
40 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
41 "-bindpath", binFolder,
42 "-intermediateFolder", intermediateFolder,
43 "-o", bundlePath
44 });
45
46 result.AssertSuccess();
47
48 Assert.True(File.Exists(bundlePath));
49
50 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
51 extractResult.AssertSuccess();
52
53 var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
54 var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload", ignoreAttributes);
55 WixAssert.CompareLineByLine(new[]
56 {
57 @"<Payload Id='FirstX64' FilePath='FirstX64\FirstX64.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX64/FirstX64/FirstX64.msi' Packaging='embedded' SourcePath='a0' Container='BundlePackages' />",
58 @"<Payload Id='FirstX86.msi' FilePath='FirstX86\FirstX86.msi' FileSize='*' Hash='*' DownloadUrl='http://example.com//FirstX86.msi/FirstX86/FirstX86.msi' Packaging='embedded' SourcePath='a1' Container='BundlePackages' />",
59 @"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='FirstX86\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX86.msi/fk1m38Cf9RZ2Bx_ipinRY6BftelU/FirstX86/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a2' Container='BundlePackages' />",
60 @"<Payload Id='ff2L_N_DLQ.nSUi.l8LxG14gd2V4' FilePath='FirstX64\PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' DownloadUrl='http://example.com/FirstX64/ff2L_N_DLQ.nSUi.l8LxG14gd2V4/FirstX64/PFiles/MsiPackage/test.txt' Packaging='embedded' SourcePath='a3' Container='BundlePackages' />",
61 }, payloads);
62 }
63 }
64
65 [Fact]
66 public void HarvestedPayloadsArePutInCorrectContainer()
67 {
68 var folder = TestData.Get(@"TestData");
69
70 using (var fs = new DisposableFileSystem())
71 {
72 var baseFolder = fs.GetFolder();
73 var intermediateFolder = Path.Combine(baseFolder, "obj");
74 var binFolder = Path.Combine(baseFolder, "bin");
75 var bundlePath = Path.Combine(binFolder, "test.exe");
76 var baFolderPath = Path.Combine(baseFolder, "ba");
77 var extractFolderPath = Path.Combine(baseFolder, "extract");
78
79 this.BuildMsis(folder, intermediateFolder, binFolder);
80
81 var result = WixRunner.Execute(new[]
82 {
83 "build",
84 Path.Combine(folder, "Container", "HarvestIntoDetachedContainer.wxs"),
85 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
86 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
87 "-bindpath", binFolder,
88 "-intermediateFolder", intermediateFolder,
89 "-o", bundlePath
90 });
91
92 result.AssertSuccess();
93
94 Assert.True(File.Exists(bundlePath));
95
96 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
97 extractResult.AssertSuccess();
98
99 var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
100 var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload", ignoreAttributes);
101 WixAssert.CompareLineByLine(new[]
102 {
103 @"<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />",
104 @"<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a1' Container='FirstX64' />",
105 @"<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />",
106 @"<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\MsiPackage\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a3' Container='FirstX64' />",
107 }, payloads);
108 }
109 }
110
111 [Fact]
112 public void HarvestedPayloadsArePutInCorrectPackage()
113 {
114 var folder = TestData.Get(@"TestData");
115
116 using (var fs = new DisposableFileSystem())
117 {
118 var baseFolder = fs.GetFolder();
119 var intermediateFolder = Path.Combine(baseFolder, "obj");
120 var binFolder = Path.Combine(baseFolder, "bin");
121 var bundlePath = Path.Combine(binFolder, "test.exe");
122 var baFolderPath = Path.Combine(baseFolder, "ba");
123 var extractFolderPath = Path.Combine(baseFolder, "extract");
124
125 var pdbPaths = this.BuildMsis(folder, intermediateFolder, binFolder);
126
127 var result = WixRunner.Execute(new[]
128 {
129 "build",
130 Path.Combine(folder, "Container", "HarvestIntoDetachedContainer.wxs"),
131 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
132 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
133 "-bindpath", binFolder,
134 "-intermediateFolder", intermediateFolder,
135 "-o", bundlePath
136 });
137
138 result.AssertSuccess();
139
140 Assert.True(File.Exists(bundlePath));
141
142 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
143 extractResult.AssertSuccess();
144
145 var ignoreAttributes = new Dictionary<string, List<string>>
146 {
147 { "MsiPackage", new List<string> { "CacheId", "InstallSize", "Size", "ProductCode" } },
148 };
149 var msiPackages = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Chain/burn:MsiPackage", ignoreAttributes);
150 WixAssert.CompareLineByLine(new[]
151 {
152 "<MsiPackage Id='FirstX86.msi' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryForward='WixDefaultBoundary' LogPathVariable='WixBundleLog_FirstX86.msi' RollbackLogPathVariable='WixBundleRollbackLog_FirstX86.msi' ProductCode='*' Language='1033' Version='1.0.0.0' UpgradeCode='{12E4699F-E774-4D05-8A01-5BDD41BBA127}'>" +
153 "<MsiProperty Id='MSIFASTINSTALL' Value='1' />" +
154 "<MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />" +
155 $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[0])}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
156 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
157 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
158 "<PayloadRef Id='FirstX86.msi' />" +
159 "<PayloadRef Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' />" +
160 "</MsiPackage>",
161 "<MsiPackage Id='FirstX64.msi' Cache='keep' CacheId='*' InstallSize='*' Size='*' PerMachine='yes' Permanent='no' Vital='yes' RollbackBoundaryBackward='WixDefaultBoundary' LogPathVariable='WixBundleLog_FirstX64.msi' RollbackLogPathVariable='WixBundleRollbackLog_FirstX64.msi' ProductCode='*' Language='1033' Version='1.0.0.0' UpgradeCode='{12E4699F-E774-4D05-8A01-5BDD41BBA127}'>" +
162 "<MsiProperty Id='ARPSYSTEMCOMPONENT' Value='1' />" +
163 "<MsiProperty Id='MSIFASTINSTALL' Value='7' />" +
164 $"<Provides Key='{GetProductCodeFromMsiPdb(pdbPaths[1])}_v1.0.0.0' Version='1.0.0.0' DisplayName='MsiPackage' />" +
165 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MaxVersion='1.0.0.0' MaxInclusive='no' OnlyDetect='no' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
166 "<RelatedPackage Id='{12E4699F-E774-4D05-8A01-5BDD41BBA127}' MinVersion='1.0.0.0' MinInclusive='no' OnlyDetect='yes' LangInclusive='yes'><Language Id='1033' /></RelatedPackage>" +
167 "<PayloadRef Id='FirstX64.msi' />" +
168 "<PayloadRef Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' />" +
169 "</MsiPackage>",
170 }, msiPackages);
171 }
172 }
173
174 [Fact]
175 public void LayoutPayloadIsPutInContainer()
176 {
177 var folder = TestData.Get(@"TestData");
178
179 using (var fs = new DisposableFileSystem())
180 {
181 var baseFolder = fs.GetFolder();
182 var intermediateFolder = Path.Combine(baseFolder, "obj");
183 var binFolder = Path.Combine(baseFolder, "bin");
184 var bundlePath = Path.Combine(binFolder, "test.exe");
185 var baFolderPath = Path.Combine(baseFolder, "ba");
186 var extractFolderPath = Path.Combine(baseFolder, "extract");
187
188 this.BuildMsis(folder, intermediateFolder, binFolder);
189
190 var result = WixRunner.Execute(false, new[]
191 {
192 "build",
193 Path.Combine(folder, "Container", "LayoutPayloadInContainer.wxs"),
194 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
195 "-bindpath", binFolder,
196 "-intermediateFolder", intermediateFolder,
197 "-o", bundlePath
198 });
199
200 WixAssert.CompareLineByLine(new[]
201 {
202 "The layout-only Payload 'SharedPayload' is being added to Container 'FirstX64'. It will not be extracted during layout.",
203 }, result.Messages.Select(m => m.ToString()).ToArray());
204 result.AssertSuccess();
205
206 Assert.True(File.Exists(bundlePath));
207
208 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
209 extractResult.AssertSuccess();
210
211 var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
212 var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']", ignoreAttributes);
213 WixAssert.CompareLineByLine(new[]
214 {
215 "<Payload Id='SharedPayload' FilePath='LayoutPayloadInContainer.wxs' FileSize='*' Hash='*' LayoutOnly='yes' Packaging='embedded' SourcePath='a1' Container='FirstX64' />",
216 }, payloads);
217 }
218 }
219
220 [Fact]
221 public void MultipleAttachedContainers()
222 {
223 var folder = TestData.Get(@"TestData");
224
225 using (var fs = new DisposableFileSystem())
226 {
227 var baseFolder = fs.GetFolder();
228 var intermediateFolder = Path.Combine(baseFolder, "obj");
229 var binFolder = Path.Combine(baseFolder, "bin");
230 var bundlePath = Path.Combine(binFolder, "test.exe");
231 var baFolderPath = Path.Combine(baseFolder, "ba");
232 var attachedFolderPath = Path.Combine(baseFolder, "attached");
233 var extractFolderPath = Path.Combine(baseFolder, "extract");
234
235 this.BuildMsis(folder, intermediateFolder, binFolder);
236
237 var result = WixRunner.Execute(new[]
238 {
239 "build",
240 Path.Combine(folder, "Container", "MultipleAttachedContainers.wxs"),
241 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
242 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
243 "-bindpath", binFolder,
244 "-intermediateFolder", intermediateFolder,
245 "-o", bundlePath
246 });
247
248 result.AssertSuccess();
249 Assert.True(File.Exists(bundlePath));
250
251 var extractResult = BundleExtractor.ExtractAllContainers(null, bundlePath, baFolderPath, attachedFolderPath, extractFolderPath);
252 extractResult.AssertSuccess();
253
254 Assert.True(File.Exists(Path.Combine(attachedFolderPath, "FirstX64", "FirstX64.msi")), "Expected extracted container to contain FirstX64.msi");
255 Assert.True(File.Exists(Path.Combine(attachedFolderPath, "WixAttachedContainer", "FirstX86.msi")), "Expected extracted container to contain FirstX86.msi");
256
257 var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
258 var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload", ignoreAttributes);
259 WixAssert.CompareLineByLine(new[]
260 {
261 "<Payload Id='FirstX86.msi' FilePath='FirstX86.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a0' Container='WixAttachedContainer' />",
262 "<Payload Id='FirstX64.msi' FilePath='FirstX64.msi' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a1' Container='FirstX64' />",
263 "<Payload Id='fk1m38Cf9RZ2Bx_ipinRY6BftelU' FilePath='PFiles\\MsiPackage\\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='WixAttachedContainer' />",
264 "<Payload Id='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' FilePath='PFiles\\MsiPackage\\test.txt' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a3' Container='FirstX64' />",
265 }, payloads);
266 }
267 }
268
269 [Fact]
270 public void PayloadIsNotPutInMultipleContainers()
271 {
272 var folder = TestData.Get(@"TestData");
273
274 using (var fs = new DisposableFileSystem())
275 {
276 var baseFolder = fs.GetFolder();
277 var intermediateFolder = Path.Combine(baseFolder, "obj");
278 var binFolder = Path.Combine(baseFolder, "bin");
279 var bundlePath = Path.Combine(binFolder, "test.exe");
280 var baFolderPath = Path.Combine(baseFolder, "ba");
281 var extractFolderPath = Path.Combine(baseFolder, "extract");
282
283 this.BuildMsis(folder, intermediateFolder, binFolder);
284
285 var result = WixRunner.Execute(false, new[]
286 {
287 "build",
288 Path.Combine(folder, "Container", "PayloadInMultipleContainers.wxs"),
289 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
290 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
291 "-bindpath", binFolder,
292 "-intermediateFolder", intermediateFolder,
293 "-o", bundlePath
294 });
295
296 WixAssert.CompareLineByLine(new[]
297 {
298 "The Payload 'SharedPayload' can't be added to Container 'FirstX64' because it was already added to Container 'FirstX86'.",
299 }, result.Messages.Select(m => m.ToString()).ToArray());
300 result.AssertSuccess();
301
302 Assert.True(File.Exists(bundlePath));
303
304 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
305 extractResult.AssertSuccess();
306
307 var ignoreAttributes = new Dictionary<string, List<string>> { { "Payload", new List<string> { "FileSize", "Hash" } } };
308 var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload[@Id='SharedPayload']", ignoreAttributes);
309 WixAssert.CompareLineByLine(new[]
310 {
311 "<Payload Id='SharedPayload' FilePath='PayloadInMultipleContainers.wxs' FileSize='*' Hash='*' Packaging='embedded' SourcePath='a2' Container='FirstX86' />",
312 }, payloads);
313 }
314 }
315
316 [Fact]
317 public void PopulatesBAManifestWithLayoutOnlyPayloads()
318 {
319 var folder = TestData.Get(@"TestData");
320
321 using (var fs = new DisposableFileSystem())
322 {
323 var baseFolder = fs.GetFolder();
324 var intermediateFolder = Path.Combine(baseFolder, "obj");
325 var binFolder = Path.Combine(baseFolder, "bin");
326 var bundlePath = Path.Combine(binFolder, "test.exe");
327 var baFolderPath = Path.Combine(baseFolder, "ba");
328 var extractFolderPath = Path.Combine(baseFolder, "extract");
329
330 this.BuildMsis(folder, intermediateFolder, binFolder);
331
332 var result = WixRunner.Execute(false, new[]
333 {
334 "build",
335 Path.Combine(folder, "Container", "LayoutPayloadInContainer.wxs"),
336 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
337 "-bindpath", binFolder,
338 "-intermediateFolder", intermediateFolder,
339 "-o", bundlePath
340 });
341
342 WixAssert.CompareLineByLine(new[]
343 {
344 "The layout-only Payload 'SharedPayload' is being added to Container 'FirstX64'. It will not be extracted during layout.",
345 }, result.Messages.Select(m => m.ToString()).ToArray());
346 result.AssertSuccess();
347
348 Assert.True(File.Exists(bundlePath));
349
350 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
351 extractResult.AssertSuccess();
352
353 var ignoreAttributesByElementName = new Dictionary<string, List<string>>
354 {
355 { "WixPayloadProperties", new List<string> { "Size" } },
356 };
357 var payloads = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixPayloadProperties", ignoreAttributesByElementName);
358 WixAssert.CompareLineByLine(new[]
359 {
360 "<WixPayloadProperties Package='FirstX64.msi' Payload='FirstX64.msi' Container='FirstX64' Name='FirstX64.msi' Size='*' />",
361 "<WixPayloadProperties Package='FirstX64.msi' Payload='SharedPayload' Container='FirstX64' Name='LayoutPayloadInContainer.wxs' Size='*' />",
362 "<WixPayloadProperties Package='FirstX64.msi' Payload='fC0n41rZK8oW3JK8LzHu6AT3CjdQ' Container='FirstX64' Name='PFiles\\MsiPackage\\test.txt' Size='*' />",
363 "<WixPayloadProperties Payload='SharedPayload' Container='FirstX64' Name='LayoutPayloadInContainer.wxs' Size='*' />",
364 }, payloads);
365 }
366 }
367
368 private string[] BuildMsis(string folder, string intermediateFolder, string binFolder, bool buildToSubfolder = false)
369 {
370 var x86OutputPath = Path.Combine(binFolder, buildToSubfolder ? "FirstX86" : ".", "FirstX86.msi");
371 var result = WixRunner.Execute(new[]
372 {
373 "build",
374 Path.Combine(folder, "MsiTransaction", "FirstX86.wxs"),
375 Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"),
376 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
377 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
378 "-intermediateFolder", intermediateFolder,
379 "-o", x86OutputPath,
380 });
381
382 result.AssertSuccess();
383
384 var x64OutputPath = Path.Combine(binFolder, buildToSubfolder ? "FirstX64" : ".", "FirstX64.msi");
385 result = WixRunner.Execute(new[]
386 {
387 "build",
388 Path.Combine(folder, "MsiTransaction", "FirstX64.wxs"),
389 Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"),
390 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
391 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
392 "-intermediateFolder", intermediateFolder,
393 "-o", x64OutputPath,
394 });
395
396 result.AssertSuccess();
397
398 return new[]
399 {
400 Path.ChangeExtension(x86OutputPath, ".wixpdb"),
401 Path.ChangeExtension(x64OutputPath, ".wixpdb"),
402 };
403 }
404
405 private static string GetProductCodeFromMsiPdb(string pdbPath)
406 {
407 var wiData = WindowsInstallerData.Load(pdbPath, suppressVersionCheck: false);
408 return wiData.Tables["Property"].Rows.Cast<PropertyRow>().Single(r => r.Property == "ProductCode").Value;
409 }
410 }
411 }