From ce73352b1fa1d4f9cded10a0ee410f2e786bd326 Mon Sep 17 00:00:00 2001 From: Bevan Weiss Date: Mon, 15 Jul 2024 20:06:54 +1000 Subject: [PATCH] Add basic test for Msmq install/uninstall. Fix up lack of WIX CUSTOM_ACTION_DECORATION wrappers Add new RuntimeTest skipper for Server Features / Optional Features. Signed-off-by: Bevan Weiss --- src/ext/Msmq/ca/mqsched.cpp | 8 +-- src/ext/Msmq/ca/precomp.h | 2 + .../Directory.Packages.props.pp | 2 + .../RuntimePrereqFeatureFactAttribute.cs | 56 +++++++++++++++++++ .../burn/WixTestTools/WixTestTools.csproj | 1 + .../MsmqInstall/MsmqInstall.wixproj | 13 +++++ .../MsmqInstall/product.wxs | 17 ++++++ .../MsmqExtensionTests.cs | 27 +++++++++ 8 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 src/test/burn/WixTestTools/RuntimePrereqFeatureFactAttribute.cs create mode 100644 src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/MsmqInstall.wixproj create mode 100644 src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/product.wxs create mode 100644 src/test/msi/WixToolsetTest.MsiE2E/MsmqExtensionTests.cs diff --git a/src/ext/Msmq/ca/mqsched.cpp b/src/ext/Msmq/ca/mqsched.cpp index 4c9949014..ab5a5ee7b 100644 --- a/src/ext/Msmq/ca/mqsched.cpp +++ b/src/ext/Msmq/ca/mqsched.cpp @@ -68,7 +68,7 @@ extern "C" UINT __stdcall MessageQueuingInstall(MSIHANDLE hInstall) hr = MqiMessageQueueInstall(&lstMessageQueues, TRUE, &pwzRollbackActionData); ExitOnFailure(hr, "Failed to add message queues to rollback action data"); - hr = WcaDoDeferredAction(L"MessageQueuingRollbackInstall", pwzRollbackActionData, 0); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"MessageQueuingRollbackInstall"), pwzRollbackActionData, 0); ExitOnFailure(hr, "Failed to schedule MessageQueuingRollbackInstall"); // schedule execute action @@ -80,7 +80,7 @@ extern "C" UINT __stdcall MessageQueuingInstall(MSIHANDLE hInstall) ExitOnFailure(hr, "Failed to add message queue permissions to execute action data"); iCost += lstMessageQueues.iInstallCount * COST_MESSAGE_QUEUE_PERMISSION_ADD; - hr = WcaDoDeferredAction(L"MessageQueuingExecuteInstall", pwzExecuteActionData, iCost); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"MessageQueuingExecuteInstall"), pwzExecuteActionData, iCost); ExitOnFailure(hr, "Failed to schedule MessageQueuingExecuteInstall"); } @@ -163,7 +163,7 @@ extern "C" UINT __stdcall MessageQueuingUninstall(MSIHANDLE hInstall) hr = MqiMessageQueuePermissionUninstall(&lstMessageQueuePermissions, &pwzRollbackActionData); ExitOnFailure(hr, "Failed to add message queue permissions to rollback action data"); - hr = WcaDoDeferredAction(L"MessageQueuingRollbackUninstall", pwzRollbackActionData, 0); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"MessageQueuingRollbackUninstall"), pwzRollbackActionData, 0); ExitOnFailure(hr, "Failed to schedule MessageQueuingRollbackUninstall"); // schedule execute action @@ -174,7 +174,7 @@ extern "C" UINT __stdcall MessageQueuingUninstall(MSIHANDLE hInstall) ExitOnFailure(hr, "Failed to add message queues to execute action data"); iCost += lstMessageQueues.iUninstallCount * COST_MESSAGE_QUEUE_DELETE; - hr = WcaDoDeferredAction(L"MessageQueuingExecuteUninstall", pwzExecuteActionData, iCost); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"MessageQueuingExecuteUninstall"), pwzExecuteActionData, iCost); ExitOnFailure(hr, "Failed to schedule MessageQueuingExecuteUninstall"); } diff --git a/src/ext/Msmq/ca/precomp.h b/src/ext/Msmq/ca/precomp.h index 6fbd418c3..7e8f92f6b 100644 --- a/src/ext/Msmq/ca/precomp.h +++ b/src/ext/Msmq/ca/precomp.h @@ -20,3 +20,5 @@ #include "mqqueuesched.h" #include "mqutilexec.h" #include "mqqueueexec.h" + +#include "..\..\caDecor.h" diff --git a/src/internal/SetBuildNumber/Directory.Packages.props.pp b/src/internal/SetBuildNumber/Directory.Packages.props.pp index 24095f362..721771d0c 100644 --- a/src/internal/SetBuildNumber/Directory.Packages.props.pp +++ b/src/internal/SetBuildNumber/Directory.Packages.props.pp @@ -38,6 +38,7 @@ + @@ -45,6 +46,7 @@ + diff --git a/src/test/burn/WixTestTools/RuntimePrereqFeatureFactAttribute.cs b/src/test/burn/WixTestTools/RuntimePrereqFeatureFactAttribute.cs new file mode 100644 index 000000000..aa02d5f3d --- /dev/null +++ b/src/test/burn/WixTestTools/RuntimePrereqFeatureFactAttribute.cs @@ -0,0 +1,56 @@ +// 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 System.Globalization; + using System.Linq; + using System.Management; + using System.Collections.Generic; + using System.Security.Principal; + using WixInternal.TestSupport.XunitExtensions; + + public class RuntimePrereqFeatureFactAttribute : RuntimeFactAttribute + { + public static HashSet OptionalFeatures = new(StringComparer.OrdinalIgnoreCase); + public static HashSet ServerFeatures = new(StringComparer.OrdinalIgnoreCase); + static RuntimePrereqFeatureFactAttribute() + { + AddFeaturesToSet(ServerFeatures, "Win32_ServerFeature"); + AddFeaturesToSet(OptionalFeatures, "Win32_OptionalFeature"); + } + + private static void AddFeaturesToSet(HashSet featureSet, string featureSetName) + { + try + { + var objMC = new ManagementClass(featureSetName); + var objMOC = objMC?.GetInstances(); + if (objMOC is not null) + { + foreach (var objMO in objMOC) + { + string featureName = (string)objMO.Properties["Name"].Value; + if ((uint)objMO.Properties["InstallState"].Value == 1) + { + featureSet.Add(featureName); + } + } + } + } + catch + { + } + } + + public RuntimePrereqFeatureFactAttribute(params string[] prerequisiteFeatures) : base() + { + var missingRequirements = prerequisiteFeatures.Select(x => x).Where(x => !ServerFeatures.Contains(x) && !OptionalFeatures.Contains(x)); + + if (missingRequirements.Any()) + { + this.Skip = "This test is missing the following Feature pre-requisites: " + String.Join(", ", missingRequirements); + } + } + } +} diff --git a/src/test/burn/WixTestTools/WixTestTools.csproj b/src/test/burn/WixTestTools/WixTestTools.csproj index 19c09294e..7a7029490 100644 --- a/src/test/burn/WixTestTools/WixTestTools.csproj +++ b/src/test/burn/WixTestTools/WixTestTools.csproj @@ -23,6 +23,7 @@ + diff --git a/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/MsmqInstall.wixproj b/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/MsmqInstall.wixproj new file mode 100644 index 000000000..41e399443 --- /dev/null +++ b/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/MsmqInstall.wixproj @@ -0,0 +1,13 @@ + + + + {A75B81F4-3335-4B4D-B766-303E136ED374} + true + + + + + + + + diff --git a/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/product.wxs b/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/product.wxs new file mode 100644 index 000000000..241b6aed9 --- /dev/null +++ b/src/test/msi/TestData/MsmqExtensionTests/MsmqInstall/product.wxs @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/test/msi/WixToolsetTest.MsiE2E/MsmqExtensionTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/MsmqExtensionTests.cs new file mode 100644 index 000000000..41eb8201d --- /dev/null +++ b/src/test/msi/WixToolsetTest.MsiE2E/MsmqExtensionTests.cs @@ -0,0 +1,27 @@ +// 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.MsiE2E +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using WixTestTools; + using Xunit.Abstractions; + + public class MsmqExtensionTests : MsiE2ETests + { + public MsmqExtensionTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) + { + } + + [RuntimePrereqFeatureFact("MSMQ-Container", "MSMQ-Server")] + public void CanInstallAndUninstallMsmq() + { + var product = this.CreatePackageInstaller("MsmqInstall"); + product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); + product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); + } + } +}