From 36b1a2ce73b394ca3ed7490a1392320e2f401cbd Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 1 Jan 2021 14:02:51 -0600 Subject: Create failing test for issue 6309. --- .../RollbackBoundary/BundleA/BundleA.wixproj | 15 ++++++ src/TestData/RollbackBoundary/BundleA/BundleA.wxi | 21 ++++++++ src/TestData/RollbackBoundary/BundleA/BundleA.wxs | 16 +++++++ .../RollbackBoundary/PackageA/PackageA.wixproj | 9 ++++ .../RollbackBoundary/PackageB/PackageB.wixproj | 9 ++++ .../RollbackBoundary/PackageC/PackageC.wixproj | 9 ++++ .../RollbackBoundary/PackageF/PackageF.wixproj | 12 +++++ src/WixToolsetTest.BurnE2E/BundleInstaller.cs | 56 +++++++++++++++++----- .../RollbackBoundaryTests.cs | 52 ++++++++++++++++++++ 9 files changed, 186 insertions(+), 13 deletions(-) create mode 100644 src/TestData/RollbackBoundary/BundleA/BundleA.wixproj create mode 100644 src/TestData/RollbackBoundary/BundleA/BundleA.wxi create mode 100644 src/TestData/RollbackBoundary/BundleA/BundleA.wxs create mode 100644 src/TestData/RollbackBoundary/PackageA/PackageA.wixproj create mode 100644 src/TestData/RollbackBoundary/PackageB/PackageB.wixproj create mode 100644 src/TestData/RollbackBoundary/PackageC/PackageC.wixproj create mode 100644 src/TestData/RollbackBoundary/PackageF/PackageF.wixproj create mode 100644 src/WixToolsetTest.BurnE2E/RollbackBoundaryTests.cs (limited to 'src') diff --git a/src/TestData/RollbackBoundary/BundleA/BundleA.wixproj b/src/TestData/RollbackBoundary/BundleA/BundleA.wixproj new file mode 100644 index 00000000..96f7aa31 --- /dev/null +++ b/src/TestData/RollbackBoundary/BundleA/BundleA.wixproj @@ -0,0 +1,15 @@ + + + + Bundle + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/RollbackBoundary/BundleA/BundleA.wxi b/src/TestData/RollbackBoundary/BundleA/BundleA.wxi new file mode 100644 index 00000000..145073b5 --- /dev/null +++ b/src/TestData/RollbackBoundary/BundleA/BundleA.wxi @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/RollbackBoundary/BundleA/BundleA.wxs b/src/TestData/RollbackBoundary/BundleA/BundleA.wxs new file mode 100644 index 00000000..251b1863 --- /dev/null +++ b/src/TestData/RollbackBoundary/BundleA/BundleA.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/TestData/RollbackBoundary/PackageA/PackageA.wixproj b/src/TestData/RollbackBoundary/PackageA/PackageA.wixproj new file mode 100644 index 00000000..25d9e279 --- /dev/null +++ b/src/TestData/RollbackBoundary/PackageA/PackageA.wixproj @@ -0,0 +1,9 @@ + + + + {14A06CEA-CC9E-478F-AD20-5C9624827090} + + + + + \ No newline at end of file diff --git a/src/TestData/RollbackBoundary/PackageB/PackageB.wixproj b/src/TestData/RollbackBoundary/PackageB/PackageB.wixproj new file mode 100644 index 00000000..2dc4f3a6 --- /dev/null +++ b/src/TestData/RollbackBoundary/PackageB/PackageB.wixproj @@ -0,0 +1,9 @@ + + + + {C0B6E75E-4378-4589-B3C5-A23FFA39F59B} + + + + + \ No newline at end of file diff --git a/src/TestData/RollbackBoundary/PackageC/PackageC.wixproj b/src/TestData/RollbackBoundary/PackageC/PackageC.wixproj new file mode 100644 index 00000000..a4b5134b --- /dev/null +++ b/src/TestData/RollbackBoundary/PackageC/PackageC.wixproj @@ -0,0 +1,9 @@ + + + + {1C977E8F-4E79-4E3B-A5B1-C4B0BE774041} + + + + + \ No newline at end of file diff --git a/src/TestData/RollbackBoundary/PackageF/PackageF.wixproj b/src/TestData/RollbackBoundary/PackageF/PackageF.wixproj new file mode 100644 index 00000000..d51fab1f --- /dev/null +++ b/src/TestData/RollbackBoundary/PackageF/PackageF.wixproj @@ -0,0 +1,12 @@ + + + + {E348D377-E5E7-44B0-897E-5DC8D401BF80} + + + + + + + + \ No newline at end of file diff --git a/src/WixToolsetTest.BurnE2E/BundleInstaller.cs b/src/WixToolsetTest.BurnE2E/BundleInstaller.cs index c85646bb..5ce993f3 100644 --- a/src/WixToolsetTest.BurnE2E/BundleInstaller.cs +++ b/src/WixToolsetTest.BurnE2E/BundleInstaller.cs @@ -15,6 +15,8 @@ namespace WixToolsetTest.BurnE2E { public const string BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH = "BundleCachePath"; + public const string FULL_BURN_POLICY_REGISTRY_PATH = "SOFTWARE\\WOW6432Node\\Policies\\WiX\\Burn"; + public const string PACKAGE_CACHE_FOLDER_NAME = "Package Cache"; public BundleInstaller(WixTestContext testContext, string name) { @@ -28,6 +30,8 @@ namespace WixToolsetTest.BurnE2E public string BundlePdb { get; } + private WixBundleSymbol BundleSymbol { get; set; } + public string TestGroupName { get; } public string TestName { get; } @@ -142,37 +146,63 @@ namespace WixToolsetTest.BurnE2E return logFile; } + private WixBundleSymbol GetBundleSymbol() + { + if (this.BundleSymbol == null) + { + using var wixOutput = WixOutput.Read(this.BundlePdb); + var intermediate = Intermediate.Load(wixOutput); + var section = intermediate.Sections.Single(); + this.BundleSymbol = section.Symbols.OfType().Single(); + } + + return this.BundleSymbol; + } + + public string GetExpectedCachedBundlePath() + { + var bundleSymbol = this.GetBundleSymbol(); + + using var policyKey = Registry.LocalMachine.OpenSubKey(FULL_BURN_POLICY_REGISTRY_PATH); + var redirectedCachePath = policyKey?.GetValue("PackageCache") as string; + var cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME); + return Path.Combine(cachePath, bundleSymbol.BundleId, Path.GetFileName(this.Bundle)); + } + public string VerifyRegisteredAndInPackageCache() { - using var wixOutput = WixOutput.Read(this.BundlePdb); - var intermediate = Intermediate.Load(wixOutput); - var section = intermediate.Sections.Single(); - var bundleSymbol = section.Symbols.OfType().Single(); + var bundleSymbol = this.GetBundleSymbol(); var bundleId = bundleSymbol.BundleId; var registrationKeyPath = $"{BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY}\\{bundleId}"; - using var testKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); - Assert.NotNull(testKey); + using var registrationKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); + Assert.NotNull(registrationKey); - var cachePathValue = testKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH); + var cachePathValue = registrationKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH); Assert.NotNull(cachePathValue); var cachePath = Assert.IsType(cachePathValue); Assert.True(File.Exists(cachePath)); + var expectedCachePath = this.GetExpectedCachedBundlePath(); + Assert.Equal(expectedCachePath, cachePath, StringComparer.OrdinalIgnoreCase); + return cachePath; } + public void VerifyUnregisteredAndRemovedFromPackageCache() + { + var cachedBundlePath = this.GetExpectedCachedBundlePath(); + this.VerifyUnregisteredAndRemovedFromPackageCache(cachedBundlePath); + } + public void VerifyUnregisteredAndRemovedFromPackageCache(string cachedBundlePath) { - using var wixOutput = WixOutput.Read(this.BundlePdb); - var intermediate = Intermediate.Load(wixOutput); - var section = intermediate.Sections.Single(); - var bundleSymbol = section.Symbols.OfType().Single(); + var bundleSymbol = this.GetBundleSymbol(); var bundleId = bundleSymbol.BundleId; var registrationKeyPath = $"{BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY}\\{bundleId}"; - using var testKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); - Assert.Null(testKey); + using var registrationKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); + Assert.Null(registrationKey); Assert.False(File.Exists(cachedBundlePath)); } diff --git a/src/WixToolsetTest.BurnE2E/RollbackBoundaryTests.cs b/src/WixToolsetTest.BurnE2E/RollbackBoundaryTests.cs new file mode 100644 index 00000000..1ae81b49 --- /dev/null +++ b/src/WixToolsetTest.BurnE2E/RollbackBoundaryTests.cs @@ -0,0 +1,52 @@ +// 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. + +namespace WixToolsetTest.BurnE2E +{ + using System; + using System.IO; + using Xunit; + using Xunit.Abstractions; + + public class RollbackBoundaryTests : BurnE2ETests + { + public RollbackBoundaryTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper, "RollbackBoundary") { } + + /// + /// Installs 1 bundle: + /// chain - non-vital rollback boundary, package F, package A, vital rollback boundary, package B + /// package F fails + /// package A and B are permanent + /// Execution is supposed to be: + /// package F (fails) + /// rollback to non-vital rollback boundary which ignores the error and skips over package A + /// install package B + /// unregister since no non-permanent packages should be installed or cached. + /// + [Fact] + public void NonVitalRollbackBoundarySkipsToNextRollbackBoundary() + { + var packageA = this.CreatePackageInstaller("PackageA"); + var packageB = this.CreatePackageInstaller("PackageB"); + this.CreatePackageInstaller("PackageC"); + this.CreatePackageInstaller("PackageF"); + + var bundleA = this.CreateBundleInstaller("BundleA"); + + var packageASourceCodeInstalled = packageA.GetInstalledFilePath("Package.wxs"); + var packageBSourceCodeInstalled = packageB.GetInstalledFilePath("Package.wxs"); + + // Source file should *not* be installed + Assert.False(File.Exists(packageASourceCodeInstalled), $"Package A payload should not be there on test start: {packageASourceCodeInstalled}"); + Assert.False(File.Exists(packageBSourceCodeInstalled), $"Package B payload should not be there on test start: {packageBSourceCodeInstalled}"); + + bundleA.Install(); + + // No non-permanent packages should have ended up installed or cached so it should have unregistered. + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + // Only PackageB source file should be installed + Assert.True(File.Exists(packageBSourceCodeInstalled), String.Concat("Should have found Package B payload installed at: ", packageBSourceCodeInstalled)); + Assert.False(File.Exists(packageASourceCodeInstalled), String.Concat("Should not have found Package A payload installed at: ", packageASourceCodeInstalled)); + } + } +} -- cgit v1.2.3-55-g6feb