main
cs 162 lines 8.14 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.BurnE2E
4 {
5 using System.Collections.Generic;
6 using System.IO;
7 using WixInternal.TestSupport;
8 using WixTestTools;
9 using Xunit;
10 using Xunit.Abstractions;
11
12 public class LayoutTests : BurnE2ETests
13 {
14 public LayoutTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
15
16 [RuntimeFact]
17 public void CanLayoutBundleInPlaceWithMissingPayloads()
18 {
19 var bundleA = this.CreateBundleInstaller("BundleA");
20 var webServer = this.CreateWebServer();
21
22 webServer.AddFiles(new Dictionary<string, string>
23 {
24 { "/BundleA/LayoutOnlyPayload", Path.Combine(this.TestContext.TestDataFolder, "BundleA.wxs") },
25 { "/BundleA/packages.cab", Path.Combine(this.TestContext.TestDataFolder, "packages.cab") },
26 });
27 webServer.Start();
28
29 using var dfs = new DisposableFileSystem();
30 var layoutDirectory = dfs.GetFolder(true);
31
32 // Manually copy bundle to layout directory and then run from there so the non-compressed payloads have to be resolved.
33 var bundleAFileInfo = new FileInfo(bundleA.Bundle);
34 var bundleACopiedPath = Path.Combine(layoutDirectory, bundleAFileInfo.Name);
35 bundleAFileInfo.CopyTo(bundleACopiedPath);
36
37 bundleA.Layout(bundleACopiedPath, layoutDirectory);
38 bundleA.VerifyUnregisteredAndRemovedFromPackageCache();
39
40 Assert.True(File.Exists(bundleACopiedPath));
41 Assert.True(File.Exists(Path.Combine(layoutDirectory, "packages.cab")));
42 Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.wxs")));
43 }
44
45 [RuntimeFact]
46 public void CanLayoutBundleToNewDirectory()
47 {
48 var bundleA = this.CreateBundleInstaller("BundleA");
49 var webServer = this.CreateWebServer();
50
51 webServer.AddFiles(new Dictionary<string, string>
52 {
53 { "/BundleA/LayoutOnlyPayload", Path.Combine(this.TestContext.TestDataFolder, "BundleA.wxs") },
54 { "/BundleA/packages.cab", Path.Combine(this.TestContext.TestDataFolder, "packages.cab") },
55 });
56 webServer.Start();
57
58 using var dfs = new DisposableFileSystem();
59 var layoutDirectory = dfs.GetFolder();
60
61 bundleA.Layout(layoutDirectory);
62 bundleA.VerifyUnregisteredAndRemovedFromPackageCache();
63
64 Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.exe")));
65 Assert.True(File.Exists(Path.Combine(layoutDirectory, "packages.cab")));
66 Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.wxs")));
67 }
68
69 [RuntimeFact]
70 public void CanSkipOverCorruptLocalFileForDownloadableFile()
71 {
72 var bundleB = this.CreateBundleInstaller("BundleB");
73 var webServer = this.CreateWebServer();
74
75 webServer.AddFiles(new Dictionary<string, string>
76 {
77 { "/BundleB/PackageA.msi", Path.Combine(this.TestContext.TestDataFolder, "PackageA.msi") },
78 });
79 webServer.Start();
80
81 using var dfs = new DisposableFileSystem();
82 var baseDirectory = dfs.GetFolder(true);
83 var sourceDirectory = Path.Combine(baseDirectory, "source");
84 Directory.CreateDirectory(sourceDirectory);
85 var layoutDirectory = Path.Combine(baseDirectory, "layout");
86 Directory.CreateDirectory(layoutDirectory);
87
88 // Manually copy bundle to empty directory and then run from there so it can't find the uncorrupted file.
89 var bundleBFileInfo = new FileInfo(bundleB.Bundle);
90 var bundleBCopiedPath = Path.Combine(sourceDirectory, bundleBFileInfo.Name);
91 bundleBFileInfo.CopyTo(bundleBCopiedPath);
92
93 // Copy a corrupted version of PackageA.msi next to the bundle.
94 var packageAFileInfo = new FileInfo(Path.Combine(bundleBFileInfo.DirectoryName, "PackageA.msi"));
95 var packageACorruptedFileInfo = new FileInfo(Path.Combine(sourceDirectory, packageAFileInfo.Name));
96 packageAFileInfo.CopyTo(packageACorruptedFileInfo.FullName);
97 SubtlyCorruptFile(packageACorruptedFileInfo);
98
99 var layoutLogPath = bundleB.Layout(bundleBCopiedPath, layoutDirectory);
100 bundleB.VerifyUnregisteredAndRemovedFromPackageCache();
101
102 Assert.True(File.Exists(Path.Combine(layoutDirectory, bundleBFileInfo.Name)));
103 Assert.True(File.Exists(Path.Combine(layoutDirectory, packageAFileInfo.Name)));
104 Assert.True(LogVerifier.MessageInLogFile(layoutLogPath, "Verification failed on payload group item: PackageA"));
105 }
106
107 [RuntimeFact]
108 public void CanSkipOverCorruptLocalFileForOtherLocalFile()
109 {
110 var bundleA = this.CreateBundleInstaller("BundleA");
111 var testBAController = this.CreateTestBAController();
112
113 using var dfs = new DisposableFileSystem();
114 var baseDirectory = dfs.GetFolder(true);
115 var sourceDirectory = Path.Combine(baseDirectory, "source");
116 Directory.CreateDirectory(sourceDirectory);
117 var layoutDirectory = Path.Combine(baseDirectory, "layout");
118 Directory.CreateDirectory(layoutDirectory);
119
120 // Copy a corrupted version of packages.cab and BundleA.wxs.
121 var bundleAFileInfo = new FileInfo(bundleA.Bundle);
122 var packagesCabFileInfo = new FileInfo(Path.Combine(bundleAFileInfo.DirectoryName, "packages.cab"));
123 var packagesCabCorruptedFileInfo = new FileInfo(Path.Combine(sourceDirectory, packagesCabFileInfo.Name));
124 packagesCabFileInfo.CopyTo(packagesCabCorruptedFileInfo.FullName);
125 SubtlyCorruptFile(packagesCabCorruptedFileInfo);
126
127 var layoutOnlyPayloadFileInfo = new FileInfo(Path.Combine(bundleAFileInfo.DirectoryName, "BundleA.wxs"));
128 var layoutOnlyPayloadCorruptedFileInfo = new FileInfo(Path.Combine(sourceDirectory, layoutOnlyPayloadFileInfo.Name));
129 layoutOnlyPayloadFileInfo.CopyTo(layoutOnlyPayloadCorruptedFileInfo.FullName);
130 SubtlyCorruptFile(layoutOnlyPayloadCorruptedFileInfo);
131
132 // Set the source to absolute path so the engine tries the corrupted files first.
133 testBAController.SetContainerInitialLocalSource("PackagesContainer", packagesCabCorruptedFileInfo.FullName);
134 testBAController.SetPayloadInitialLocalSource("LayoutOnlyPayload", layoutOnlyPayloadCorruptedFileInfo.FullName);
135
136 var layoutLogPath = bundleA.Layout(layoutDirectory);
137 bundleA.VerifyUnregisteredAndRemovedFromPackageCache();
138
139 Assert.True(File.Exists(Path.Combine(layoutDirectory, bundleAFileInfo.Name)));
140 Assert.True(File.Exists(Path.Combine(layoutDirectory, packagesCabFileInfo.Name)));
141 Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.wxs")));
142 Assert.True(LogVerifier.MessageInLogFile(layoutLogPath, "Verification failed on container: PackagesContainer"));
143 Assert.True(LogVerifier.MessageInLogFile(layoutLogPath, "Verification failed on payload group item: LayoutOnlyPayload"));
144 }
145
146 private static void SubtlyCorruptFile(FileInfo fileInfo)
147 {
148 using (var v = fileInfo.Open(FileMode.Open, FileAccess.ReadWrite))
149 {
150 // Change one byte of information in the middle of the file to corrupt it.
151 // Hopefully this ensures that these tests will continue to work even if optimizations are added later,
152 // such as checking the file header, product code, or product version during acquisition.
153 var bytePosition = v.Length / 2;
154 v.Position = bytePosition;
155 var byteValue = v.ReadByte();
156 byteValue = byteValue == 0 ? 1 : 0;
157 v.Position = bytePosition;
158 v.WriteByte((byte)byteValue);
159 }
160 }
161 }
162 }