diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-08-03 14:55:23 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-08-03 15:57:24 -0500 |
commit | 124fef398a26bc8e139e889a2345602d2478590c (patch) | |
tree | 002c77e0c1d72b0cc0e46bed3c6f02d4179625fe /src/test | |
parent | a896fec453056aa5e1ad803b04a672d2dceda981 (diff) | |
download | wix-124fef398a26bc8e139e889a2345602d2478590c.tar.gz wix-124fef398a26bc8e139e889a2345602d2478590c.tar.bz2 wix-124fef398a26bc8e139e889a2345602d2478590c.zip |
Add ability to skip a local path candidate if it failed verification.
Fixes 6818
Diffstat (limited to 'src/test')
5 files changed, 223 insertions, 1 deletions
diff --git a/src/test/burn/TestBA/TestBA.cs b/src/test/burn/TestBA/TestBA.cs index 7e3d2623..e73c907e 100644 --- a/src/test/burn/TestBA/TestBA.cs +++ b/src/test/burn/TestBA/TestBA.cs | |||
@@ -155,6 +155,9 @@ namespace WixToolset.Test.BA | |||
155 | this.quitAfterDetect = false; | 155 | this.quitAfterDetect = false; |
156 | } | 156 | } |
157 | 157 | ||
158 | this.ImportContainerSources(); | ||
159 | this.ImportPayloadSources(); | ||
160 | |||
158 | this.wait.WaitOne(); | 161 | this.wait.WaitOne(); |
159 | 162 | ||
160 | if (this.action == LaunchAction.Help) | 163 | if (this.action == LaunchAction.Help) |
@@ -657,6 +660,54 @@ namespace WixToolset.Test.BA | |||
657 | this.Engine.Log(LogLevel.Standard, String.Concat("TESTBA", relation, ": ", message)); | 660 | this.Engine.Log(LogLevel.Standard, String.Concat("TESTBA", relation, ": ", message)); |
658 | } | 661 | } |
659 | 662 | ||
663 | private void ImportContainerSources() | ||
664 | { | ||
665 | string testName = this.Engine.GetVariableString("TestGroupName"); | ||
666 | using (RegistryKey testKey = Registry.LocalMachine.OpenSubKey(String.Format(@"Software\WiX\Tests\TestBAControl\{0}\container", testName))) | ||
667 | { | ||
668 | if (testKey == null) | ||
669 | { | ||
670 | return; | ||
671 | } | ||
672 | |||
673 | foreach (var containerId in testKey.GetSubKeyNames()) | ||
674 | { | ||
675 | using (RegistryKey subkey = testKey.OpenSubKey(containerId)) | ||
676 | { | ||
677 | string initialSource = subkey == null ? null : subkey.GetValue("InitialLocalSource") as string; | ||
678 | if (initialSource != null) | ||
679 | { | ||
680 | this.Engine.SetLocalSource(containerId, null, initialSource); | ||
681 | } | ||
682 | } | ||
683 | } | ||
684 | } | ||
685 | } | ||
686 | |||
687 | private void ImportPayloadSources() | ||
688 | { | ||
689 | string testName = this.Engine.GetVariableString("TestGroupName"); | ||
690 | using (RegistryKey testKey = Registry.LocalMachine.OpenSubKey(String.Format(@"Software\WiX\Tests\TestBAControl\{0}\payload", testName))) | ||
691 | { | ||
692 | if (testKey == null) | ||
693 | { | ||
694 | return; | ||
695 | } | ||
696 | |||
697 | foreach (var payloadId in testKey.GetSubKeyNames()) | ||
698 | { | ||
699 | using (RegistryKey subkey = testKey.OpenSubKey(payloadId)) | ||
700 | { | ||
701 | string initialSource = subkey == null ? null : subkey.GetValue("InitialLocalSource") as string; | ||
702 | if (initialSource != null) | ||
703 | { | ||
704 | this.Engine.SetLocalSource(null, payloadId, initialSource); | ||
705 | } | ||
706 | } | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | |||
660 | private List<string> ReadVerifyArguments() | 711 | private List<string> ReadVerifyArguments() |
661 | { | 712 | { |
662 | string testName = this.Engine.GetVariableString("TestGroupName"); | 713 | string testName = this.Engine.GetVariableString("TestGroupName"); |
diff --git a/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wixproj b/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wixproj new file mode 100644 index 00000000..2ce22ea1 --- /dev/null +++ b/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wixproj | |||
@@ -0,0 +1,17 @@ | |||
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 | <Project Sdk="WixToolset.Sdk"> | ||
3 | <PropertyGroup> | ||
4 | <BA>hyperlinkLicense</BA> | ||
5 | <OutputType>Bundle</OutputType> | ||
6 | <UpgradeCode>{CBF22B7D-C6C0-408A-9F29-81FE8610559C}</UpgradeCode> | ||
7 | </PropertyGroup> | ||
8 | <ItemGroup> | ||
9 | <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" /> | ||
10 | </ItemGroup> | ||
11 | <ItemGroup> | ||
12 | <ProjectReference Include="..\PackageA\PackageA.wixproj" /> | ||
13 | </ItemGroup> | ||
14 | <ItemGroup> | ||
15 | <PackageReference Include="WixToolset.Bal.wixext" /> | ||
16 | </ItemGroup> | ||
17 | </Project> \ No newline at end of file | ||
diff --git a/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wxs b/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wxs new file mode 100644 index 00000000..fb6eadb9 --- /dev/null +++ b/src/test/burn/TestData/LayoutTests/BundleB/BundleB.wxs | |||
@@ -0,0 +1,10 @@ | |||
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 | |||
4 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
5 | <Fragment> | ||
6 | <PackageGroup Id="BundlePackages"> | ||
7 | <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" Compressed="no" DownloadUrl="$(var.WebServerBaseUrl)BundleB/{2}" /> | ||
8 | </PackageGroup> | ||
9 | </Fragment> | ||
10 | </Wix> | ||
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/LayoutTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/LayoutTests.cs index 47a42750..14c3cd5d 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/LayoutTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/LayoutTests.cs | |||
@@ -65,5 +65,98 @@ namespace WixToolsetTest.BurnE2E | |||
65 | Assert.True(File.Exists(Path.Combine(layoutDirectory, "packages.cab"))); | 65 | Assert.True(File.Exists(Path.Combine(layoutDirectory, "packages.cab"))); |
66 | Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.wxs"))); | 66 | Assert.True(File.Exists(Path.Combine(layoutDirectory, "BundleA.wxs"))); |
67 | } | 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 | } | ||
68 | } | 161 | } |
69 | } | 162 | } |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs index 3f9d76b8..115f3b54 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs | |||
@@ -183,6 +183,26 @@ namespace WixToolsetTest.BurnE2E | |||
183 | } | 183 | } |
184 | 184 | ||
185 | /// <summary> | 185 | /// <summary> |
186 | /// At startup, set the payload's source path to the given path. | ||
187 | /// </summary> | ||
188 | /// <param name="payloadId"></param> | ||
189 | /// <param name="sourcePath"></param> | ||
190 | public void SetPayloadInitialLocalSource(string payloadId, string sourcePath) | ||
191 | { | ||
192 | this.SetPayloadState(payloadId, "InitialLocalSource", sourcePath); | ||
193 | } | ||
194 | |||
195 | /// <summary> | ||
196 | /// At startup, set the container's source path to the given path. | ||
197 | /// </summary> | ||
198 | /// <param name="containerId"></param> | ||
199 | /// <param name="sourcePath"></param> | ||
200 | public void SetContainerInitialLocalSource(string containerId, string sourcePath) | ||
201 | { | ||
202 | this.SetContainerState(containerId, "InitialLocalSource", sourcePath); | ||
203 | } | ||
204 | |||
205 | /// <summary> | ||
186 | /// Sets the number of times to re-run the Detect phase. | 206 | /// Sets the number of times to re-run the Detect phase. |
187 | /// </summary> | 207 | /// </summary> |
188 | /// <param name="state">Number of times to run Detect (after the first, normal, Detect).</param> | 208 | /// <param name="state">Number of times to run Detect (after the first, normal, Detect).</param> |
@@ -204,7 +224,6 @@ namespace WixToolsetTest.BurnE2E | |||
204 | public void SetVerifyArguments(string verifyArguments) | 224 | public void SetVerifyArguments(string verifyArguments) |
205 | { | 225 | { |
206 | this.SetBurnTestValue("VerifyArguments", verifyArguments); | 226 | this.SetBurnTestValue("VerifyArguments", verifyArguments); |
207 | |||
208 | } | 227 | } |
209 | 228 | ||
210 | private void SetPackageState(string packageId, string name, string value) | 229 | private void SetPackageState(string packageId, string name, string value) |
@@ -223,6 +242,38 @@ namespace WixToolsetTest.BurnE2E | |||
223 | } | 242 | } |
224 | } | 243 | } |
225 | 244 | ||
245 | private void SetContainerState(string containerId, string name, string value) | ||
246 | { | ||
247 | var key = String.Format(@"{0}\container\{1}", this.TestBaseRegKeyPath, containerId); | ||
248 | using (var containerKey = Registry.LocalMachine.CreateSubKey(key)) | ||
249 | { | ||
250 | if (String.IsNullOrEmpty(value)) | ||
251 | { | ||
252 | containerKey.DeleteValue(name, false); | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | containerKey.SetValue(name, value); | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | |||
261 | private void SetPayloadState(string payloadId, string name, string value) | ||
262 | { | ||
263 | var key = String.Format(@"{0}\payload\{1}", this.TestBaseRegKeyPath, payloadId ?? String.Empty); | ||
264 | using (var payloadKey = Registry.LocalMachine.CreateSubKey(key)) | ||
265 | { | ||
266 | if (String.IsNullOrEmpty(value)) | ||
267 | { | ||
268 | payloadKey.DeleteValue(name, false); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | payloadKey.SetValue(name, value); | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
226 | public void Dispose() | 277 | public void Dispose() |
227 | { | 278 | { |
228 | Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\{this.TestGroupName}", false); | 279 | Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\{this.TestGroupName}", false); |