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); |
