From 6f6e4ced9f398ff37a44b91fdba62479cde29d06 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Thu, 9 Jun 2022 15:30:48 -0500 Subject: Implement ArpEntry flavored ExePackage. 6772 --- .../TestData/DependencyTests/BundleD/BundleD.wxs | 2 +- .../BrokenPerUserArpEntryExePackage.wixproj | 17 ++ .../BrokenPerUserArpEntryExePackage.wxs | 18 ++ .../PackageFail/PackageFail.wixproj | 12 ++ .../PerMachineArpEntryExePackage.wixproj | 19 ++ .../PerMachineArpEntryExePackage.wxs | 18 ++ .../PerMachineArpEntryExePackageFailure.wixproj | 18 ++ .../PerMachineArpEntryExePackageFailure.wxs | 19 ++ .../PerUserArpEntryExePackage.wixproj | 17 ++ .../PerUserArpEntryExePackage.wxs | 18 ++ src/test/burn/WixTestTools/ArpEntryInstaller.cs | 43 ++++ src/test/burn/WixTestTools/ArpEntryVerifier.cs | 24 +++ src/test/burn/WixTestTools/BundleRegistration.cs | 121 ++---------- src/test/burn/WixTestTools/BundleVerifier.cs | 23 +++ .../burn/WixTestTools/GenericArpRegistration.cs | 143 ++++++++++++++ .../burn/WixToolsetTest.BurnE2E/BurnE2ETests.cs | 17 ++ src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs | 4 +- .../burn/WixToolsetTest.BurnE2E/ExePackageTests.cs | 99 ++++++++++ src/test/burn/WixToolsetTest.BurnE2E/IWebServer.cs | 23 --- .../WixToolsetTest.BurnE2E/TestBAController.cs | 217 --------------------- .../WixToolsetTest.BurnE2E/Utilities/IWebServer.cs | 23 +++ .../Utilities/TestBAController.cs | 217 +++++++++++++++++++++ .../Utilities/TestExeTool.cs | 17 ++ 23 files changed, 782 insertions(+), 347 deletions(-) create mode 100644 src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wixproj create mode 100644 src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wxs create mode 100644 src/test/burn/TestData/ExePackageTests/PackageFail/PackageFail.wixproj create mode 100644 src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wixproj create mode 100644 src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wxs create mode 100644 src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wixproj create mode 100644 src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wxs create mode 100644 src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wixproj create mode 100644 src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wxs create mode 100644 src/test/burn/WixTestTools/ArpEntryInstaller.cs create mode 100644 src/test/burn/WixTestTools/ArpEntryVerifier.cs create mode 100644 src/test/burn/WixTestTools/GenericArpRegistration.cs create mode 100644 src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs delete mode 100644 src/test/burn/WixToolsetTest.BurnE2E/IWebServer.cs delete mode 100644 src/test/burn/WixToolsetTest.BurnE2E/TestBAController.cs create mode 100644 src/test/burn/WixToolsetTest.BurnE2E/Utilities/IWebServer.cs create mode 100644 src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs create mode 100644 src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestExeTool.cs (limited to 'src/test') diff --git a/src/test/burn/TestData/DependencyTests/BundleD/BundleD.wxs b/src/test/burn/TestData/DependencyTests/BundleD/BundleD.wxs index f371f674..22152da2 100644 --- a/src/test/burn/TestData/DependencyTests/BundleD/BundleD.wxs +++ b/src/test/burn/TestData/DependencyTests/BundleD/BundleD.wxs @@ -4,7 +4,7 @@ - + diff --git a/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wixproj b/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wixproj new file mode 100644 index 00000000..bcb447b0 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wixproj @@ -0,0 +1,17 @@ + + + + Bundle + {A843CC02-6814-48F5-997D-052073BAE744} + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wxs b/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wxs new file mode 100644 index 00000000..709a7c3c --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/BrokenPerUserArpEntryExePackage/BrokenPerUserArpEntryExePackage.wxs @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/src/test/burn/TestData/ExePackageTests/PackageFail/PackageFail.wixproj b/src/test/burn/TestData/ExePackageTests/PackageFail/PackageFail.wixproj new file mode 100644 index 00000000..19c5463d --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PackageFail/PackageFail.wixproj @@ -0,0 +1,12 @@ + + + + {6C5A2C71-2009-4B52-BC20-C1C6A5C87EA6} + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wixproj b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wixproj new file mode 100644 index 00000000..ed46e6a5 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wixproj @@ -0,0 +1,19 @@ + + + + Bundle + x64 + TestBA_x64 + {5923A558-091E-4015-A9CC-BA92E7A2405A} + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wxs b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wxs new file mode 100644 index 00000000..a966283f --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackage/PerMachineArpEntryExePackage.wxs @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wixproj b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wixproj new file mode 100644 index 00000000..e4219565 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wixproj @@ -0,0 +1,18 @@ + + + + Bundle + {6436F747-08F7-416F-BE92-DB48F282AFC1} + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wxs b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wxs new file mode 100644 index 00000000..945146f0 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageFailure/PerMachineArpEntryExePackageFailure.wxs @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wixproj b/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wixproj new file mode 100644 index 00000000..06395843 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wixproj @@ -0,0 +1,17 @@ + + + + Bundle + {E4683E88-AF03-40D0-B308-5C084B0E1FA0} + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wxs b/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wxs new file mode 100644 index 00000000..e2792693 --- /dev/null +++ b/src/test/burn/TestData/ExePackageTests/PerUserArpEntryExePackage/PerUserArpEntryExePackage.wxs @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/src/test/burn/WixTestTools/ArpEntryInstaller.cs b/src/test/burn/WixTestTools/ArpEntryInstaller.cs new file mode 100644 index 00000000..96d9fab9 --- /dev/null +++ b/src/test/burn/WixTestTools/ArpEntryInstaller.cs @@ -0,0 +1,43 @@ +// 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 WixTestTools +{ + using System; + using Xunit; + + public partial class ArpEntryInstaller : IDisposable + { + public ArpEntryInstaller(WixTestContext testContext, string id, bool perMachine = true, bool x64 = false) + { + this.ArpId = id; + this.PerMachine = perMachine; + this.X64 = x64; + this.TestContext = testContext; + } + + public string ArpId { get; } + + public bool PerMachine { get; } + + public bool X64 { get; } + + private WixTestContext TestContext { get; } + + public void Unregister(bool assertIfMissing = true) + { + if (this.TryGetRegistration(out var registration)) + { + registration.Delete(); + } + else + { + Assert.True(false, "Tried to unregister when not registered."); + } + } + + public void Dispose() + { + this.Unregister(false); + } + } +} diff --git a/src/test/burn/WixTestTools/ArpEntryVerifier.cs b/src/test/burn/WixTestTools/ArpEntryVerifier.cs new file mode 100644 index 00000000..b3c70337 --- /dev/null +++ b/src/test/burn/WixTestTools/ArpEntryVerifier.cs @@ -0,0 +1,24 @@ +// 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 WixTestTools +{ + using Xunit; + + public partial class ArpEntryInstaller + { + public bool TryGetRegistration(out GenericArpRegistration registration) + { + bool success = !this.PerMachine ? GenericArpRegistration.TryGetPerUserRegistrationById(this.ArpId, out registration) + : GenericArpRegistration.TryGetPerMachineRegistrationById(this.ArpId, this.X64, out registration); + + return success; + } + + public void VerifyRegistered(bool registered) + { + bool success = this.TryGetRegistration(out _); + + Assert.Equal(registered, success); + } + } +} diff --git a/src/test/burn/WixTestTools/BundleRegistration.cs b/src/test/burn/WixTestTools/BundleRegistration.cs index 3541e7ea..524d4616 100644 --- a/src/test/burn/WixTestTools/BundleRegistration.cs +++ b/src/test/burn/WixTestTools/BundleRegistration.cs @@ -5,108 +5,51 @@ namespace WixTestTools using System; using Microsoft.Win32; - public class BundleRegistration + public class BundleRegistration : GenericArpRegistration { - public const string BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - public const string BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY_WOW6432NODE = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; - public const string BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH = "BundleCachePath"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_ADDON_CODE = "BundleAddonCode"; + public const string BURN_REGISTRATION_REGISTRY_BUNDLE_CACHE_PATH = "BundleCachePath"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_DETECT_CODE = "BundleDetectCode"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_PATCH_CODE = "BundlePatchCode"; + public const string BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = "BundleProviderKey"; + public const string BURN_REGISTRATION_REGISTRY_BUNDLE_RESUME_COMMAND_LINE = "BundleResumeCommandLine"; + public const string BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = "BundleTag"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE = "BundleUpgradeCode"; - public const string BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME = "DisplayName"; public const string BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION = "BundleVersion"; public const string BURN_REGISTRATION_REGISTRY_ENGINE_VERSION = "EngineVersion"; - public const string BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY = "BundleProviderKey"; - public const string BURN_REGISTRATION_REGISTRY_BUNDLE_TAG = "BundleTag"; - public const string REGISTRY_REBOOT_PENDING_FORMAT = "{0}.RebootRequired"; - public const string REGISTRY_BUNDLE_INSTALLED = "Installed"; - public const string REGISTRY_BUNDLE_DISPLAY_ICON = "DisplayIcon"; - public const string REGISTRY_BUNDLE_DISPLAY_VERSION = "DisplayVersion"; - public const string REGISTRY_BUNDLE_ESTIMATED_SIZE = "EstimatedSize"; - public const string REGISTRY_BUNDLE_PUBLISHER = "Publisher"; - public const string REGISTRY_BUNDLE_HELP_LINK = "HelpLink"; - public const string REGISTRY_BUNDLE_HELP_TELEPHONE = "HelpTelephone"; - public const string REGISTRY_BUNDLE_URL_INFO_ABOUT = "URLInfoAbout"; - public const string REGISTRY_BUNDLE_URL_UPDATE_INFO = "URLUpdateInfo"; - public const string REGISTRY_BUNDLE_PARENT_DISPLAY_NAME = "ParentDisplayName"; - public const string REGISTRY_BUNDLE_PARENT_KEY_NAME = "ParentKeyName"; - public const string REGISTRY_BUNDLE_COMMENTS = "Comments"; - public const string REGISTRY_BUNDLE_CONTACT = "Contact"; - public const string REGISTRY_BUNDLE_NO_MODIFY = "NoModify"; - public const string REGISTRY_BUNDLE_MODIFY_PATH = "ModifyPath"; - public const string REGISTRY_BUNDLE_NO_ELEVATE_ON_MODIFY = "NoElevateOnModify"; - public const string REGISTRY_BUNDLE_NO_REMOVE = "NoRemove"; - public const string REGISTRY_BUNDLE_SYSTEM_COMPONENT = "SystemComponent"; - public const string REGISTRY_BUNDLE_QUIET_UNINSTALL_STRING = "QuietUninstallString"; - public const string REGISTRY_BUNDLE_UNINSTALL_STRING = "UninstallString"; - public const string REGISTRY_BUNDLE_RESUME_COMMAND_LINE = "BundleResumeCommandLine"; - public const string REGISTRY_BUNDLE_VERSION_MAJOR = "VersionMajor"; - public const string REGISTRY_BUNDLE_VERSION_MINOR = "VersionMinor"; public string[] AddonCodes { get; set; } - public string CachePath { get; set; } + public string BundleVersion { get; set; } - public string DisplayName { get; set; } + public string CachePath { get; set; } public string[] DetectCodes { get; set; } public string EngineVersion { get; set; } - public int? EstimatedSize { get; set; } - - public int? Installed { get; set; } - - public string ModifyPath { get; set; } - public string[] PatchCodes { get; set; } public string ProviderKey { get; set; } - public string Publisher { get; set; } - - public int? SystemComponent { get; set; } - - public string QuietUninstallString { get; set; } - - public string QuietUninstallCommand { get; set; } - - public string QuietUninstallCommandArguments { get; set; } - public string Tag { get; set; } - public string UninstallCommand { get; set; } - - public string UninstallCommandArguments { get; set; } - - public string UninstallString { get; set; } - public string[] UpgradeCodes { get; set; } - public string UrlInfoAbout { get; set; } - - public string UrlUpdateInfo { get; set; } - - public string Version { get; set; } + public static bool TryGetPerMachineBundleRegistrationById(string id, bool x64, out BundleRegistration registration) + { + return TryGetRegistrationById(id, x64, false, out registration); + } - public static bool TryGetPerMachineBundleRegistrationById(string bundleId, bool x64, out BundleRegistration registration) + public static bool TryGetPerUserBundleRegistrationById(string id, out BundleRegistration registration) { - var baseKeyPath = x64 ? BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY : BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY_WOW6432NODE; - var registrationKeyPath = $"{baseKeyPath}\\{bundleId}"; - using var registrationKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); - var success = registrationKey != null; - registration = success ? GetBundleRegistration(registrationKey) : null; - return success; + return TryGetRegistrationById(id, true, true, out registration); } - public static bool TryGetPerUserBundleRegistrationById(string bundleId, out BundleRegistration registration) + private static bool TryGetRegistrationById(string id, bool x64, bool perUser, out BundleRegistration registration) { - var registrationKeyPath = $"{BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY}\\{bundleId}"; - using var registrationKey = Registry.CurrentUser.OpenSubKey(registrationKeyPath); - var success = registrationKey != null; - registration = success ? GetBundleRegistration(registrationKey) : null; - return success; + registration = GetGenericArpRegistration(id, x64, perUser, key => GetBundleRegistration(key)); + return registration != null; } private static BundleRegistration GetBundleRegistration(RegistryKey idKey) @@ -120,38 +63,8 @@ namespace WixTestTools registration.ProviderKey = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_PROVIDER_KEY) as string; registration.Tag = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_TAG) as string; registration.UpgradeCodes = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE) as string[]; - registration.Version = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION) as string; - registration.DisplayName = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME) as string; + registration.BundleVersion = idKey.GetValue(BURN_REGISTRATION_REGISTRY_BUNDLE_VERSION) as string; registration.EngineVersion = idKey.GetValue(BURN_REGISTRATION_REGISTRY_ENGINE_VERSION) as string; - registration.EstimatedSize = idKey.GetValue(REGISTRY_BUNDLE_ESTIMATED_SIZE) as int?; - registration.Installed = idKey.GetValue(REGISTRY_BUNDLE_INSTALLED) as int?; - registration.ModifyPath = idKey.GetValue(REGISTRY_BUNDLE_MODIFY_PATH) as string; - registration.Publisher = idKey.GetValue(REGISTRY_BUNDLE_PUBLISHER) as string; - registration.SystemComponent = idKey.GetValue(REGISTRY_BUNDLE_SYSTEM_COMPONENT) as int?; - registration.UrlInfoAbout = idKey.GetValue(REGISTRY_BUNDLE_URL_INFO_ABOUT) as string; - registration.UrlUpdateInfo = idKey.GetValue(REGISTRY_BUNDLE_URL_UPDATE_INFO) as string; - - registration.QuietUninstallString = idKey.GetValue(REGISTRY_BUNDLE_QUIET_UNINSTALL_STRING) as string; - if (!String.IsNullOrEmpty(registration.QuietUninstallString)) - { - var closeQuote = registration.QuietUninstallString.IndexOf("\"", 1); - if (closeQuote > 0) - { - registration.QuietUninstallCommand = registration.QuietUninstallString.Substring(1, closeQuote - 1).Trim(); - registration.QuietUninstallCommandArguments = registration.QuietUninstallString.Substring(closeQuote + 1).Trim(); - } - } - - registration.UninstallString = idKey.GetValue(REGISTRY_BUNDLE_UNINSTALL_STRING) as string; - if (!String.IsNullOrEmpty(registration.UninstallString)) - { - var closeQuote = registration.UninstallString.IndexOf("\"", 1); - if (closeQuote > 0) - { - registration.UninstallCommand = registration.UninstallString.Substring(1, closeQuote - 1).Trim(); - registration.UninstallCommandArguments = registration.UninstallString.Substring(closeQuote + 1).Trim(); - } - } return registration; } diff --git a/src/test/burn/WixTestTools/BundleVerifier.cs b/src/test/burn/WixTestTools/BundleVerifier.cs index 103171cd..ff45a291 100644 --- a/src/test/burn/WixTestTools/BundleVerifier.cs +++ b/src/test/burn/WixTestTools/BundleVerifier.cs @@ -80,6 +80,29 @@ namespace WixTestTools File.Delete(expectedCachePath); } + public bool TryGetArpEntryExePackageConfiguration(string packageId, out string arpId, out string arpVersion, out bool arpWin64, out bool perMachine) + { + using var wixOutput = WixOutput.Read(this.BundlePdb); + var intermediate = Intermediate.Load(wixOutput); + var section = intermediate.Sections.Single(); + var packageSymbol = section.Symbols.OfType().SingleOrDefault(p => p.Id.Id == packageId); + var exePackageSymbol = section.Symbols.OfType().SingleOrDefault(p => p.Id.Id == packageId); + if (packageSymbol == null || exePackageSymbol == null || exePackageSymbol.DetectionType != WixBundleExePackageDetectionType.Arp) + { + arpId = null; + arpVersion = null; + arpWin64 = false; + perMachine = false; + return false; + } + + arpId = exePackageSymbol.ArpId; + arpVersion = exePackageSymbol.ArpDisplayVersion; + arpWin64 = exePackageSymbol.ArpWin64; + perMachine = packageSymbol.PerMachine == true; + return true; + } + public bool TryGetRegistration(out BundleRegistration registration) { var bundleSymbol = this.GetBundleSymbol(); diff --git a/src/test/burn/WixTestTools/GenericArpRegistration.cs b/src/test/burn/WixTestTools/GenericArpRegistration.cs new file mode 100644 index 00000000..d87c4feb --- /dev/null +++ b/src/test/burn/WixTestTools/GenericArpRegistration.cs @@ -0,0 +1,143 @@ +// 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 WixTestTools +{ + using System; + using Microsoft.Win32; + + public class GenericArpRegistration + { + public const string UNINSTALL_KEY = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + public const string UNINSTALL_KEY_WOW6432NODE = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + + public const string REGISTRY_ARP_INSTALLED = "Installed"; + public const string REGISTRY_ARP_DISPLAY_ICON = "DisplayIcon"; + public const string REGISTRY_ARP_DISPLAY_NAME = "DisplayName"; + public const string REGISTRY_ARP_DISPLAY_VERSION = "DisplayVersion"; + public const string REGISTRY_ARP_ESTIMATED_SIZE = "EstimatedSize"; + public const string REGISTRY_ARP_PUBLISHER = "Publisher"; + public const string REGISTRY_ARP_HELP_LINK = "HelpLink"; + public const string REGISTRY_ARP_HELP_TELEPHONE = "HelpTelephone"; + public const string REGISTRY_ARP_URL_INFO_ABOUT = "URLInfoAbout"; + public const string REGISTRY_ARP_URL_UPDATE_INFO = "URLUpdateInfo"; + public const string REGISTRY_ARP_COMMENTS = "Comments"; + public const string REGISTRY_ARP_CONTACT = "Contact"; + public const string REGISTRY_ARP_NO_MODIFY = "NoModify"; + public const string REGISTRY_ARP_MODIFY_PATH = "ModifyPath"; + public const string REGISTRY_ARP_NO_ELEVATE_ON_MODIFY = "NoElevateOnModify"; + public const string REGISTRY_ARP_NO_REMOVE = "NoRemove"; + public const string REGISTRY_ARP_SYSTEM_COMPONENT = "SystemComponent"; + public const string REGISTRY_ARP_QUIET_UNINSTALL_STRING = "QuietUninstallString"; + public const string REGISTRY_ARP_UNINSTALL_STRING = "UninstallString"; + public const string REGISTRY_ARP_VERSION_MAJOR = "VersionMajor"; + public const string REGISTRY_ARP_VERSION_MINOR = "VersionMinor"; + + public RegistryKey BaseKey { get; set; } + + public string KeyPath { get; set; } + + public string DisplayName { get; set; } + + public string DisplayVersion { get; set; } + + public int? EstimatedSize { get; set; } + + public int? Installed { get; set; } + + public string ModifyPath { get; set; } + + public string Publisher { get; set; } + + public int? SystemComponent { get; set; } + + public string QuietUninstallString { get; set; } + + public string QuietUninstallCommand { get; set; } + + public string QuietUninstallCommandArguments { get; set; } + + public string UninstallCommand { get; set; } + + public string UninstallCommandArguments { get; set; } + + public string UninstallString { get; set; } + + public string UrlInfoAbout { get; set; } + + public string UrlUpdateInfo { get; set; } + + public static bool TryGetPerMachineRegistrationById(string id, bool x64, out GenericArpRegistration registration) + { + return TryGetRegistrationById(id, x64, false, out registration); + } + + public static bool TryGetPerUserRegistrationById(string id, out GenericArpRegistration registration) + { + return TryGetRegistrationById(id, true, true, out registration); + } + + private static bool TryGetRegistrationById(string id, bool x64, bool perUser, out GenericArpRegistration registration) + { + registration = GetGenericArpRegistration(id, x64, perUser, key => new GenericArpRegistration()); + return registration != null; + } + + protected static T GetGenericArpRegistration(string id, bool x64, bool perUser, Func fnCreate) + where T : GenericArpRegistration + { + var baseKey = perUser ? Registry.CurrentUser : Registry.LocalMachine; + var baseKeyPath = x64 ? UNINSTALL_KEY : UNINSTALL_KEY_WOW6432NODE; + var registrationKeyPath = $"{baseKeyPath}\\{id}"; + using var idKey = baseKey.OpenSubKey(registrationKeyPath); + + if (idKey == null) + { + return null; + } + + var registration = fnCreate(idKey); + + registration.BaseKey = baseKey; + registration.KeyPath = registrationKeyPath; + + registration.DisplayName = idKey.GetValue(REGISTRY_ARP_DISPLAY_NAME) as string; + registration.DisplayVersion = idKey.GetValue(REGISTRY_ARP_DISPLAY_VERSION) as string; + registration.EstimatedSize = idKey.GetValue(REGISTRY_ARP_ESTIMATED_SIZE) as int?; + registration.Installed = idKey.GetValue(REGISTRY_ARP_INSTALLED) as int?; + registration.ModifyPath = idKey.GetValue(REGISTRY_ARP_MODIFY_PATH) as string; + registration.Publisher = idKey.GetValue(REGISTRY_ARP_PUBLISHER) as string; + registration.SystemComponent = idKey.GetValue(REGISTRY_ARP_SYSTEM_COMPONENT) as int?; + registration.UrlInfoAbout = idKey.GetValue(REGISTRY_ARP_URL_INFO_ABOUT) as string; + registration.UrlUpdateInfo = idKey.GetValue(REGISTRY_ARP_URL_UPDATE_INFO) as string; + + registration.QuietUninstallString = idKey.GetValue(REGISTRY_ARP_QUIET_UNINSTALL_STRING) as string; + if (!String.IsNullOrEmpty(registration.QuietUninstallString)) + { + var closeQuote = registration.QuietUninstallString.IndexOf("\"", 1); + if (closeQuote > 0) + { + registration.QuietUninstallCommand = registration.QuietUninstallString.Substring(1, closeQuote - 1).Trim(); + registration.QuietUninstallCommandArguments = registration.QuietUninstallString.Substring(closeQuote + 1).Trim(); + } + } + + registration.UninstallString = idKey.GetValue(REGISTRY_ARP_UNINSTALL_STRING) as string; + if (!String.IsNullOrEmpty(registration.UninstallString)) + { + var closeQuote = registration.UninstallString.IndexOf("\"", 1); + if (closeQuote > 0) + { + registration.UninstallCommand = registration.UninstallString.Substring(1, closeQuote - 1).Trim(); + registration.UninstallCommandArguments = registration.UninstallString.Substring(closeQuote + 1).Trim(); + } + } + + return registration; + } + + public void Delete() + { + this.BaseKey.DeleteSubKeyTree(this.KeyPath); + } + } +} diff --git a/src/test/burn/WixToolsetTest.BurnE2E/BurnE2ETests.cs b/src/test/burn/WixToolsetTest.BurnE2E/BurnE2ETests.cs index 6664b849..5caedacb 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/BurnE2ETests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/BurnE2ETests.cs @@ -31,6 +31,23 @@ namespace WixToolsetTest.BurnE2E this.Installers.Push(installer); } + protected ArpEntryInstaller CreateArpEntryInstaller(string id, bool perMachine = true, bool x64 = false) + { + var installer = new ArpEntryInstaller(this.TestContext, id, perMachine, x64); + this.Installers.Push(installer); + return installer; + } + + protected ArpEntryInstaller CreateArpEntryInstaller(BundleInstaller bundleInstaller, string packageId) + { + if (!bundleInstaller.TryGetArpEntryExePackageConfiguration(packageId, out var arpId, out _, out var arpWin64, out var perMachine)) + { + return null; + } + + return this.CreateArpEntryInstaller(arpId, perMachine, arpWin64); + } + protected BundleInstaller CreateBundleInstaller(string name) { var installer = new BundleInstaller(this.TestContext, name); diff --git a/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs index f5a1cda8..e5e3259f 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/CacheTests.cs @@ -33,12 +33,12 @@ namespace WixToolsetTest.BurnE2E if (!File.Exists(targetFilePath)) { - var testTool = new TestTool(Path.Combine(TestData.Get(), "win-x86", "TestExe.exe")) + var testExeTool = new TestExeTool { Arguments = "/lf \"" + targetFilePath + $"|{FiveGB}\"", ExpectedExitCode = 0, }; - testTool.Run(true); + testExeTool.Run(true); } } diff --git a/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs new file mode 100644 index 00000000..dc6515b5 --- /dev/null +++ b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs @@ -0,0 +1,99 @@ +// 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 WixTestTools; + using Xunit; + using Xunit.Abstractions; + + public class ExePackageTests : BurnE2ETests + { + public ExePackageTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } + + [RuntimeFact] + public void CanInstallAndUninstallPerMachineArpEntryExePackage() + { + const string arpId = "{4D9EC36A-1E63-4244-875C-3ECB0A2CAE30}"; + var perMachineArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackage"); + var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageBundle, "TestExe"); + + arpEntryExePackage.VerifyRegistered(false); + + var installLogPath = perMachineArpEntryExePackageBundle.Install(); + perMachineArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); + arpEntryExePackage.VerifyRegistered(true); + + LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); + + var uninstallLogPath = perMachineArpEntryExePackageBundle.Uninstall(); + perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); + arpEntryExePackage.VerifyRegistered(false); + + LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); + } + + [RuntimeFact] + public void CanUninstallPerMachineArpEntryExePackageOnRollback() + { + const string arpId = "{80E90929-EEA5-48A7-A680-A0237A1CAD84}"; + var perMachineArpEntryExePackageFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageFailure"); + var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageFailureBundle, "TestExe"); + + arpEntryExePackage.VerifyRegistered(false); + + var installLogPath = perMachineArpEntryExePackageFailureBundle.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE); + perMachineArpEntryExePackageFailureBundle.VerifyUnregisteredAndRemovedFromPackageCache(); + arpEntryExePackage.VerifyRegistered(false); + + LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); + LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); + } + + [RuntimeFact] + public void CanInstallAndUninstallPerUserArpEntryExePackage() + { + const string arpId = "{9B5300C7-9B34-4670-9614-185B02AB87EF}"; + var perUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerUserArpEntryExePackage"); + var arpEntryExePackage = this.CreateArpEntryInstaller(perUserArpEntryExePackageBundle, "TestExe"); + + arpEntryExePackage.VerifyRegistered(false); + + var installLogPath = perUserArpEntryExePackageBundle.Install(); + perUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); + arpEntryExePackage.VerifyRegistered(true); + + LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); + + var uninstallLogPath = perUserArpEntryExePackageBundle.Uninstall(); + perUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); + arpEntryExePackage.VerifyRegistered(false); + + LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); + } + + [RuntimeFact] + public void FailsUninstallWhenPerUserArpEntryExePackageMissingQuietUninstallString() + { + const string arpId = "{DE9F8594-5856-4454-AB10-3C01ED246D7D}"; + var brokenPerUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"BrokenPerUserArpEntryExePackage"); + var arpEntryExePackage = this.CreateArpEntryInstaller(brokenPerUserArpEntryExePackageBundle, "TestExe"); + + arpEntryExePackage.VerifyRegistered(false); + brokenPerUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); + + var installLogPath = brokenPerUserArpEntryExePackageBundle.Install(); + brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); + arpEntryExePackage.VerifyRegistered(true); + + LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\""); + + brokenPerUserArpEntryExePackageBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INVALID_PARAMETER); + brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); + + arpEntryExePackage.Unregister(); + + brokenPerUserArpEntryExePackageBundle.Uninstall(); + brokenPerUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); + } + } +} diff --git a/src/test/burn/WixToolsetTest.BurnE2E/IWebServer.cs b/src/test/burn/WixToolsetTest.BurnE2E/IWebServer.cs deleted file mode 100644 index a4d46d48..00000000 --- a/src/test/burn/WixToolsetTest.BurnE2E/IWebServer.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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.Collections.Generic; - - public interface IWebServer : IDisposable - { - bool DisableHeadResponses { get; set; } - bool DisableRangeRequests { get; set; } - - /// - /// Registers a collection of relative URLs (the key) with its absolute path to the file (the value). - /// - void AddFiles(Dictionary physicalPathsByRelativeUrl); - - /// - /// Starts the web server on a new thread. - /// - void Start(); - } -} \ No newline at end of file diff --git a/src/test/burn/WixToolsetTest.BurnE2E/TestBAController.cs b/src/test/burn/WixToolsetTest.BurnE2E/TestBAController.cs deleted file mode 100644 index 8e6611a2..00000000 --- a/src/test/burn/WixToolsetTest.BurnE2E/TestBAController.cs +++ /dev/null @@ -1,217 +0,0 @@ -// 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 Microsoft.Win32; - using WixTestTools; - using WixToolset.Mba.Core; - - public class TestBAController : IDisposable - { - public TestBAController(WixTestContext testContext, bool x64 = false) - { - this.TestGroupName = testContext.TestGroupName; - this.BaseRegKeyPath = x64 ? @"Software\WiX\Tests" : @"Software\WOW6432Node\WiX\Tests"; - this.TestBaseRegKeyPath = String.Format(@"{0}\TestBAControl\{1}", this.BaseRegKeyPath, this.TestGroupName); - } - - private string BaseRegKeyPath { get; } - - private string TestBaseRegKeyPath { get; } - - public string TestGroupName { get; } - - /// - /// Sets a test value in the registry to communicate with the TestBA. - /// - /// Name of the value to set. - /// Value to set. If this is null, the value is removed. - public void SetBurnTestValue(string name, string value) - { - using (var testKey = Registry.LocalMachine.CreateSubKey(this.TestBaseRegKeyPath)) - { - if (String.IsNullOrEmpty(value)) - { - testKey.DeleteValue(name, false); - } - else - { - testKey.SetValue(name, value); - } - } - } - - public void SetExplicitlyElevateAndPlanFromOnElevateBegin(string value = "true") - { - this.SetBurnTestValue("ExplicitlyElevateAndPlanFromOnElevateBegin", value); - } - - public void SetForceKeepRegistration(string value = "true") - { - this.SetBurnTestValue("ForceKeepRegistration", value); - } - - public void SetImmediatelyQuit(string value = "true") - { - this.SetBurnTestValue("ImmediatelyQuit", value); - } - - public void SetQuitAfterDetect(string value = "true") - { - this.SetBurnTestValue("QuitAfterDetect", value); - } - - /// - /// Slows the cache progress of a package. - /// - /// Package identity. - /// Sets or removes the delay on a package being cached. - public void SetPackageSlowCache(string packageId, int? delay) - { - this.SetPackageState(packageId, "SlowCache", delay.HasValue ? delay.ToString() : null); - } - - /// - /// Cancels the cache of a package at a particular progress point. - /// - /// Package identity. - /// Sets or removes the cancel progress on a package being cached. - public void SetPackageCancelCacheAtProgress(string packageId, int? cancelPoint) - { - this.SetPackageState(packageId, "CancelCacheAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); - } - - /// - /// Slows the execute progress of a package. - /// - /// Package identity. - /// Sets or removes the delay on a package being executed. - public void SetPackageSlowExecute(string packageId, int? delay) - { - this.SetPackageState(packageId, "SlowExecute", delay.HasValue ? delay.ToString() : null); - } - - /// - /// Cancels the execute of a package at a particular progress point. - /// - /// Package identity. - /// Sets or removes the cancel progress on a package being executed. - public void SetPackageCancelExecuteAtProgress(string packageId, int? cancelPoint) - { - this.SetPackageState(packageId, "CancelExecuteAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); - } - - /// - /// Cancels the execute of a package at the next progess after the specified MSI action start. - /// - /// Package identity. - /// Sets or removes the cancel progress on a package being executed. - public void SetPackageCancelExecuteAtActionStart(string packageId, string actionName) - { - this.SetPackageState(packageId, "CancelExecuteAtActionStart", actionName); - } - - /// - /// Cancels the execute of a package at a particular OnProgress point. - /// - /// Package identity. - /// Sets or removes the cancel OnProgress point on a package being executed. - public void SetPackageCancelOnProgressAtProgress(string packageId, int? cancelPoint) - { - this.SetPackageState(packageId, "CancelOnProgressAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); - } - - /// - /// Retries the files in use one or more times before canceling. - /// - /// Package identity. - /// Sets or removes the retry count on a package's file in use message. - public void SetPackageRetryExecuteFilesInUse(string packageId, int? retryCount) - { - this.SetPackageState(packageId, "RetryExecuteFilesInUse", retryCount.HasValue ? retryCount.ToString() : null); - } - - /// - /// Sets the requested state for a package that the TestBA will return to the engine during plan. - /// - /// Package identity. - /// State to request. - public void SetPackageRequestedState(string packageId, RequestState state) - { - this.SetPackageState(packageId, "Requested", state.ToString()); - } - - /// - /// Sets the requested state for a package that the TestBA will return to the engine during plan. - /// - /// Package identity. - /// State to request. - public void SetPackageFeatureState(string packageId, string featureId, FeatureState state) - { - this.SetPackageState(packageId, String.Concat(featureId, "Requested"), state.ToString()); - } - - /// - /// Requests the BA to log the test registry value for the specified package. - /// - /// - /// - public void SetPackageRecordTestRegistryValue(string packageId, string value = "true") - { - this.SetPackageState(packageId, "RecordTestRegistryValue", value); - } - - public void SetPackageProcessCancelAction(string packageId, BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION action) - { - this.SetPackageState(packageId, "ProcessCancelAction", action.ToString()); - } - - /// - /// Sets the number of times to re-run the Detect phase. - /// - /// Number of times to run Detect (after the first, normal, Detect). - public void SetRedetectCount(int redetectCount) - { - this.SetPackageState(null, "RedetectCount", redetectCount.ToString()); - } - - /// - /// Resets the state for a package that the TestBA will return to the engine during plan. - /// - /// Package identity. - public void ResetPackageStates(string packageId) - { - var key = String.Format(@"{0}\{1}", this.TestBaseRegKeyPath, packageId ?? String.Empty); - Registry.LocalMachine.DeleteSubKey(key); - } - - public void SetVerifyArguments(string verifyArguments) - { - this.SetBurnTestValue("VerifyArguments", verifyArguments); - - } - - private void SetPackageState(string packageId, string name, string value) - { - var key = String.Format(@"{0}\{1}", this.TestBaseRegKeyPath, packageId ?? String.Empty); - using (var packageKey = Registry.LocalMachine.CreateSubKey(key)) - { - if (String.IsNullOrEmpty(value)) - { - packageKey.DeleteValue(name, false); - } - else - { - packageKey.SetValue(name, value); - } - } - } - - public void Dispose() - { - Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\{this.TestGroupName}", false); - Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\TestBAControl", false); - } - } -} diff --git a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/IWebServer.cs b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/IWebServer.cs new file mode 100644 index 00000000..a4d46d48 --- /dev/null +++ b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/IWebServer.cs @@ -0,0 +1,23 @@ +// 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.Collections.Generic; + + public interface IWebServer : IDisposable + { + bool DisableHeadResponses { get; set; } + bool DisableRangeRequests { get; set; } + + /// + /// Registers a collection of relative URLs (the key) with its absolute path to the file (the value). + /// + void AddFiles(Dictionary physicalPathsByRelativeUrl); + + /// + /// Starts the web server on a new thread. + /// + void Start(); + } +} \ No newline at end of file diff --git a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs new file mode 100644 index 00000000..8e6611a2 --- /dev/null +++ b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs @@ -0,0 +1,217 @@ +// 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 Microsoft.Win32; + using WixTestTools; + using WixToolset.Mba.Core; + + public class TestBAController : IDisposable + { + public TestBAController(WixTestContext testContext, bool x64 = false) + { + this.TestGroupName = testContext.TestGroupName; + this.BaseRegKeyPath = x64 ? @"Software\WiX\Tests" : @"Software\WOW6432Node\WiX\Tests"; + this.TestBaseRegKeyPath = String.Format(@"{0}\TestBAControl\{1}", this.BaseRegKeyPath, this.TestGroupName); + } + + private string BaseRegKeyPath { get; } + + private string TestBaseRegKeyPath { get; } + + public string TestGroupName { get; } + + /// + /// Sets a test value in the registry to communicate with the TestBA. + /// + /// Name of the value to set. + /// Value to set. If this is null, the value is removed. + public void SetBurnTestValue(string name, string value) + { + using (var testKey = Registry.LocalMachine.CreateSubKey(this.TestBaseRegKeyPath)) + { + if (String.IsNullOrEmpty(value)) + { + testKey.DeleteValue(name, false); + } + else + { + testKey.SetValue(name, value); + } + } + } + + public void SetExplicitlyElevateAndPlanFromOnElevateBegin(string value = "true") + { + this.SetBurnTestValue("ExplicitlyElevateAndPlanFromOnElevateBegin", value); + } + + public void SetForceKeepRegistration(string value = "true") + { + this.SetBurnTestValue("ForceKeepRegistration", value); + } + + public void SetImmediatelyQuit(string value = "true") + { + this.SetBurnTestValue("ImmediatelyQuit", value); + } + + public void SetQuitAfterDetect(string value = "true") + { + this.SetBurnTestValue("QuitAfterDetect", value); + } + + /// + /// Slows the cache progress of a package. + /// + /// Package identity. + /// Sets or removes the delay on a package being cached. + public void SetPackageSlowCache(string packageId, int? delay) + { + this.SetPackageState(packageId, "SlowCache", delay.HasValue ? delay.ToString() : null); + } + + /// + /// Cancels the cache of a package at a particular progress point. + /// + /// Package identity. + /// Sets or removes the cancel progress on a package being cached. + public void SetPackageCancelCacheAtProgress(string packageId, int? cancelPoint) + { + this.SetPackageState(packageId, "CancelCacheAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); + } + + /// + /// Slows the execute progress of a package. + /// + /// Package identity. + /// Sets or removes the delay on a package being executed. + public void SetPackageSlowExecute(string packageId, int? delay) + { + this.SetPackageState(packageId, "SlowExecute", delay.HasValue ? delay.ToString() : null); + } + + /// + /// Cancels the execute of a package at a particular progress point. + /// + /// Package identity. + /// Sets or removes the cancel progress on a package being executed. + public void SetPackageCancelExecuteAtProgress(string packageId, int? cancelPoint) + { + this.SetPackageState(packageId, "CancelExecuteAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); + } + + /// + /// Cancels the execute of a package at the next progess after the specified MSI action start. + /// + /// Package identity. + /// Sets or removes the cancel progress on a package being executed. + public void SetPackageCancelExecuteAtActionStart(string packageId, string actionName) + { + this.SetPackageState(packageId, "CancelExecuteAtActionStart", actionName); + } + + /// + /// Cancels the execute of a package at a particular OnProgress point. + /// + /// Package identity. + /// Sets or removes the cancel OnProgress point on a package being executed. + public void SetPackageCancelOnProgressAtProgress(string packageId, int? cancelPoint) + { + this.SetPackageState(packageId, "CancelOnProgressAtProgress", cancelPoint.HasValue ? cancelPoint.ToString() : null); + } + + /// + /// Retries the files in use one or more times before canceling. + /// + /// Package identity. + /// Sets or removes the retry count on a package's file in use message. + public void SetPackageRetryExecuteFilesInUse(string packageId, int? retryCount) + { + this.SetPackageState(packageId, "RetryExecuteFilesInUse", retryCount.HasValue ? retryCount.ToString() : null); + } + + /// + /// Sets the requested state for a package that the TestBA will return to the engine during plan. + /// + /// Package identity. + /// State to request. + public void SetPackageRequestedState(string packageId, RequestState state) + { + this.SetPackageState(packageId, "Requested", state.ToString()); + } + + /// + /// Sets the requested state for a package that the TestBA will return to the engine during plan. + /// + /// Package identity. + /// State to request. + public void SetPackageFeatureState(string packageId, string featureId, FeatureState state) + { + this.SetPackageState(packageId, String.Concat(featureId, "Requested"), state.ToString()); + } + + /// + /// Requests the BA to log the test registry value for the specified package. + /// + /// + /// + public void SetPackageRecordTestRegistryValue(string packageId, string value = "true") + { + this.SetPackageState(packageId, "RecordTestRegistryValue", value); + } + + public void SetPackageProcessCancelAction(string packageId, BOOTSTRAPPER_EXECUTEPROCESSCANCEL_ACTION action) + { + this.SetPackageState(packageId, "ProcessCancelAction", action.ToString()); + } + + /// + /// Sets the number of times to re-run the Detect phase. + /// + /// Number of times to run Detect (after the first, normal, Detect). + public void SetRedetectCount(int redetectCount) + { + this.SetPackageState(null, "RedetectCount", redetectCount.ToString()); + } + + /// + /// Resets the state for a package that the TestBA will return to the engine during plan. + /// + /// Package identity. + public void ResetPackageStates(string packageId) + { + var key = String.Format(@"{0}\{1}", this.TestBaseRegKeyPath, packageId ?? String.Empty); + Registry.LocalMachine.DeleteSubKey(key); + } + + public void SetVerifyArguments(string verifyArguments) + { + this.SetBurnTestValue("VerifyArguments", verifyArguments); + + } + + private void SetPackageState(string packageId, string name, string value) + { + var key = String.Format(@"{0}\{1}", this.TestBaseRegKeyPath, packageId ?? String.Empty); + using (var packageKey = Registry.LocalMachine.CreateSubKey(key)) + { + if (String.IsNullOrEmpty(value)) + { + packageKey.DeleteValue(name, false); + } + else + { + packageKey.SetValue(name, value); + } + } + } + + public void Dispose() + { + Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\{this.TestGroupName}", false); + Registry.LocalMachine.DeleteSubKeyTree($@"{this.BaseRegKeyPath}\TestBAControl", false); + } + } +} diff --git a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestExeTool.cs b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestExeTool.cs new file mode 100644 index 00000000..a02299d7 --- /dev/null +++ b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestExeTool.cs @@ -0,0 +1,17 @@ +// 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 WixTestTools +{ + using System.IO; + using WixBuildTools.TestSupport; + + public class TestExeTool : TestTool + { + private static readonly string TestExePath32 = Path.Combine(TestData.Get(), "win-x86", "TestExe.exe"); + + public TestExeTool() + : base(TestExePath32) + { + } + } +} -- cgit v1.2.3-55-g6feb