| 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.Threading; |
| 6 | using WixTestTools; |
| 7 | using WixToolset.BootstrapperApplicationApi; |
| 8 | using Xunit; |
| 9 | using Xunit.Abstractions; |
| 10 | |
| 11 | public class FailureTests : BurnE2ETests |
| 12 | { |
| 13 | public FailureTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } |
| 14 | |
| 15 | [RuntimeFact] |
| 16 | public void CanCancelExePackageAndAbandonIt() |
| 17 | { |
| 18 | var bundleD = this.CreateBundleInstaller("BundleD"); |
| 19 | var testBAController = this.CreateTestBAController(); |
| 20 | |
| 21 | // Cancel package ExeA after it starts. |
| 22 | testBAController.SetPackageCancelExecuteAtProgress("ExeA", 1); |
| 23 | testBAController.SetPackageRecordTestRegistryValue("ExeA"); |
| 24 | |
| 25 | var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 26 | bundleD.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 27 | |
| 28 | Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Execute, ExeA, Version, ''")); |
| 29 | Assert.False(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Rollback, ExeA, Version")); |
| 30 | } |
| 31 | |
| 32 | [RuntimeFact] |
| 33 | public void CanCancelExePackageAndWaitUntilItCompletes() |
| 34 | { |
| 35 | var bundleD = this.CreateBundleInstaller("BundleD"); |
| 36 | var testBAController = this.CreateTestBAController(); |
| 37 | |
| 38 | // Cancel package ExeA after it starts. |
| 39 | testBAController.SetPackageCancelExecuteAtProgress("ExeA", 1); |
| 40 | testBAController.SetPackageProcessCancelAction("ExeA", BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION.Wait); |
| 41 | testBAController.SetPackageRecordTestRegistryValue("ExeA"); |
| 42 | |
| 43 | var logPath = bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 44 | bundleD.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 45 | |
| 46 | Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Execute, ExeA, Version, '1.0.0.0'")); |
| 47 | Assert.True(LogVerifier.MessageInLogFile(logPath, "TestRegistryValue: Rollback, ExeA, Version, ''")); |
| 48 | |
| 49 | // The package should have rolled back. |
| 50 | bundleD.VerifyExeTestRegistryRootDeleted("ExeA"); |
| 51 | } |
| 52 | |
| 53 | [RuntimeFact] |
| 54 | public void CanCancelMsiPackageVeryEarly() |
| 55 | { |
| 56 | var packageA = this.CreatePackageInstaller("PackageA"); |
| 57 | var packageB = this.CreatePackageInstaller("PackageB"); |
| 58 | var bundleA = this.CreateBundleInstaller("BundleA"); |
| 59 | var testBAController = this.CreateTestBAController(); |
| 60 | |
| 61 | // Cancel package B right away. |
| 62 | testBAController.SetPackageCancelExecuteAtProgress("PackageB", 1); |
| 63 | |
| 64 | bundleA.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 65 | bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 66 | |
| 67 | packageA.VerifyInstalled(false); |
| 68 | packageB.VerifyInstalled(false); |
| 69 | } |
| 70 | |
| 71 | [RuntimeFact] |
| 72 | public void CanCancelMsiPackageVeryLate() |
| 73 | { |
| 74 | var packageA = this.CreatePackageInstaller("PackageA"); |
| 75 | var packageB = this.CreatePackageInstaller("PackageB"); |
| 76 | var bundleA = this.CreateBundleInstaller("BundleA"); |
| 77 | var testBAController = this.CreateTestBAController(); |
| 78 | |
| 79 | // Cancel package B at the last moment possible. |
| 80 | testBAController.SetPackageCancelExecuteAtProgress("PackageB", 100); |
| 81 | |
| 82 | bundleA.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 83 | bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 84 | |
| 85 | packageA.VerifyInstalled(false); |
| 86 | packageB.VerifyInstalled(false); |
| 87 | } |
| 88 | |
| 89 | [RuntimeFact] |
| 90 | public void CanCancelMsiPackageInOnProgress() |
| 91 | { |
| 92 | var packageA = this.CreatePackageInstaller("PackageA"); |
| 93 | var packageB = this.CreatePackageInstaller("PackageB"); |
| 94 | var bundleA = this.CreateBundleInstaller("BundleA"); |
| 95 | var testBAController = this.CreateTestBAController(); |
| 96 | |
| 97 | // Cancel package B during its OnProgress message. |
| 98 | testBAController.SetPackageCancelOnProgressAtProgress("PackageB", 100); |
| 99 | |
| 100 | bundleA.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 101 | bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 102 | |
| 103 | packageA.VerifyInstalled(false); |
| 104 | packageB.VerifyInstalled(false); |
| 105 | } |
| 106 | |
| 107 | [RuntimeFact] |
| 108 | public void CanCancelExecuteWhileCaching() |
| 109 | { |
| 110 | var packageA = this.CreatePackageInstaller("PackageA"); |
| 111 | var packageB = this.CreatePackageInstaller("PackageB"); |
| 112 | var bundleB = this.CreateBundleInstaller("BundleB"); |
| 113 | var testBAController = this.CreateTestBAController(); |
| 114 | |
| 115 | // Slow the caching of package B to ensure that package A starts installing and cancels. |
| 116 | testBAController.SetPackageCancelExecuteAtProgress("PackageA", 50); |
| 117 | testBAController.SetPackageSlowCache("PackageB", 2000); |
| 118 | |
| 119 | bundleB.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); |
| 120 | bundleB.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 121 | |
| 122 | packageA.VerifyInstalled(false); |
| 123 | packageB.VerifyInstalled(false); |
| 124 | } |
| 125 | |
| 126 | /// <summary> |
| 127 | /// BundleC has non-vital PackageA and vital PackageB. |
| 128 | /// PackageA is not compressed in the bundle and has a Name different from the source file. The Name points to a file that does not exist. |
| 129 | /// BundleC should be able to install successfully by ignoring the missing PackageA and installing PackageB. |
| 130 | /// </summary> |
| 131 | [RuntimeFact] |
| 132 | public void CanInstallWhenMissingNonVitalPackage() |
| 133 | { |
| 134 | var packageA = this.CreatePackageInstaller("PackageA"); |
| 135 | var packageB = this.CreatePackageInstaller("PackageB"); |
| 136 | var bundleC = this.CreateBundleInstaller("BundleC"); |
| 137 | |
| 138 | var bundleCInstallLogFilePath = bundleC.Install(); |
| 139 | bundleC.VerifyRegisteredAndInPackageCache(); |
| 140 | Assert.True(LogVerifier.MessageInLogFileRegex(bundleCInstallLogFilePath, "Skipping apply of package: PackageA due to cache error: 0x80070002. Continuing...")); |
| 141 | |
| 142 | packageA.VerifyInstalled(false); |
| 143 | packageB.VerifyInstalled(true); |
| 144 | |
| 145 | bundleC.Uninstall(); |
| 146 | bundleC.VerifyUnregisteredAndRemovedFromPackageCache(); |
| 147 | |
| 148 | packageA.VerifyInstalled(false); |
| 149 | packageB.VerifyInstalled(false); |
| 150 | } |
| 151 | } |
| 152 | } |