From c2ff0ccf46dd2bb07769d39e27a636e7b928a0ab Mon Sep 17 00:00:00 2001 From: Bevan Weiss <bevan.weiss@gmail.com> Date: Sat, 13 Jul 2024 15:54:41 +1000 Subject: [PATCH 1/2] Tidy up some display around Domain users. Displayed appearance should be {domain}\{user} (as per Windows displays), not {domain}/{user} Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com> --- src/test/burn/WixTestTools/UserVerifier.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/burn/WixTestTools/UserVerifier.cs b/src/test/burn/WixTestTools/UserVerifier.cs index d192a8b8f..3680d172d 100644 --- a/src/test/burn/WixTestTools/UserVerifier.cs +++ b/src/test/burn/WixTestTools/UserVerifier.cs @@ -171,12 +171,12 @@ public static void VerifyUserInformation(string domainName, string userName, boo Assert.False(null == user, String.Format("User '{0}' was not found under domain '{1}'.", userName, domainName)); - Assert.True(passwordNeverExpires == user.PasswordNeverExpires, String.Format("Password Never Expires for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, user.PasswordNeverExpires, passwordNeverExpires)); - Assert.True(disabled != user.Enabled, String.Format("Disappled for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, !user.Enabled, disabled)); + Assert.True(passwordNeverExpires == user.PasswordNeverExpires, String.Format("Password Never Expires for user '{0}\\{1}' is: '{2}', expected: '{3}'.", domainName, userName, user.PasswordNeverExpires, passwordNeverExpires)); + Assert.True(disabled != user.Enabled, String.Format("Account disabled for user '{0}\\{1}' is: '{2}', expected: '{3}'.", domainName, userName, !user.Enabled, disabled)); DateTime expirationDate = user.AccountExpirationDate.GetValueOrDefault(); bool accountExpired = expirationDate.ToLocalTime().CompareTo(DateTime.Now) <= 0; - Assert.True(passwordExpired == accountExpired, String.Format("Password Expired for user '{0}/{1}' is: '{2}', expected: '{3}'.", domainName, userName, accountExpired, passwordExpired)); + Assert.True(passwordExpired == accountExpired, String.Format("Password Expired for user '{0}\\{1}' is: '{2}', expected: '{3}'.", domainName, userName, accountExpired, passwordExpired)); } /// <summary> @@ -349,7 +349,7 @@ private static void IsUserMemberOf(string domainName, string userName, bool shou if (found != shouldBeMember) { missedAGroup = true; - message += String.Format("User '{0}/{1}' is {2} a member of local group '{3}'. \r\n", domainName, userName, found ? String.Empty : "NOT", groupName); + message += String.Format("User '{0}\\{1}' is {2} a member of local group '{3}'. \r\n", domainName, userName, found ? String.Empty : "NOT", groupName); } } catch (System.DirectoryServices.AccountManagement.PrincipalOperationException) From 54715f1cecf12276445ddc8bdb41ac631927456a Mon Sep 17 00:00:00 2001 From: Bevan Weiss <bevan.weiss@gmail.com> Date: Sat, 13 Jul 2024 15:52:51 +1000 Subject: [PATCH 2/2] Add conditional MsiE2E Tests for Domain functionality. This test currently fails under a Domain workstation. Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com> --- .../burn/WixTestTools/RuntimeFactAttribute.cs | 32 ++++++++++++++++++ .../ProductDomain/ProductDomain.wixproj | 13 ++++++++ .../ProductDomain/product.wxs | 33 +++++++++++++++++++ .../UtilExtensionUserTests.cs | 23 +++++++++++-- .../msi/WixToolsetTest.MsiE2E/runtests.cmd | 1 + 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/ProductDomain.wixproj create mode 100644 src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/product.wxs diff --git a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs index f73c87a29..02cec9e44 100644 --- a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs +++ b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs @@ -3,16 +3,21 @@ namespace WixTestTools { using System; + using System.DirectoryServices.ActiveDirectory; using System.Security.Principal; using WixInternal.TestSupport.XunitExtensions; public class RuntimeFactAttribute : SkippableFactAttribute { const string RequiredEnvironmentVariableName = "RuntimeTestsEnabled"; + const string RequiredDomainEnvironmentVariableName = "RuntimeDomainTestsEnabled"; public static bool RuntimeTestsEnabled { get; } public static bool RunningAsAdministrator { get; } + public static bool RuntimeDomainTestsEnabled { get; } + public static bool RunningInDomain { get; } + static RuntimeFactAttribute() { using var identity = WindowsIdentity.GetCurrent(); @@ -21,6 +26,33 @@ static RuntimeFactAttribute() var testsEnabledString = Environment.GetEnvironmentVariable(RequiredEnvironmentVariableName); RuntimeTestsEnabled = Boolean.TryParse(testsEnabledString, out var testsEnabled) && testsEnabled; + + RunningInDomain = false; + try + { + RunningInDomain = !String.IsNullOrEmpty(System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name); + } + catch (ActiveDirectoryObjectNotFoundException) { } + + var domainTestsEnabledString = Environment.GetEnvironmentVariable(RequiredDomainEnvironmentVariableName); + RuntimeDomainTestsEnabled = Boolean.TryParse(domainTestsEnabledString, out var domainTestsEnabled) && domainTestsEnabled; + } + + private bool _domainRequired; + public bool DomainRequired + { + get + { + return _domainRequired; + } + set + { + _domainRequired = value; + if (_domainRequired && String.IsNullOrEmpty(this.Skip) && (!RunningInDomain || !RuntimeDomainTestsEnabled)) + { + this.Skip = $"These tests require the test host to be running as a domain member ({(RunningInDomain ? "passed" : "failed")}). These tests affect both MACHINE AND DOMAIN state. To accept the consequences, set the {RequiredDomainEnvironmentVariableName} environment variable to true ({(RuntimeDomainTestsEnabled ? "passed" : "failed")})."; + } + } } public RuntimeFactAttribute() diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/ProductDomain.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/ProductDomain.wixproj new file mode 100644 index 000000000..1477407a6 --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/ProductDomain.wixproj @@ -0,0 +1,13 @@ +<!-- 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. --> +<Project Sdk="WixToolset.Sdk"> + <PropertyGroup> + <UpgradeCode>{08806ED8-3CE7-4BC3-A319-3ACCE3AAE7DC}</UpgradeCode> + <ProductComponentsRef>true</ProductComponentsRef> + </PropertyGroup> + <ItemGroup> + <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="WixToolset.Util.wixext" /> + </ItemGroup> +</Project> diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/product.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/product.wxs new file mode 100644 index 000000000..93df23518 --- /dev/null +++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductDomain/product.wxs @@ -0,0 +1,33 @@ +<!-- 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. --> + + +<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> + <Fragment> + <ComponentGroup Id="ProductComponents"> + <ComponentRef Id="Component1" /> + </ComponentGroup> + + <Property Id="TEMPDOMAIN" Secure="yes" /> + <Property Id="TEMPUSERNAME" Secure="yes" /> + </Fragment> + + <Fragment> + <util:Group Id="ADMIN" Name="Administrators" /> + <util:Group Id="DOMAIN_GUESTS" Name="Domain Guests" Domain="TESTDOMAIN" /> + + <Component Id="Component1" Guid="09624A9A-4BBC-4126-BBF9-0713C5217DB1" Directory="INSTALLFOLDER"> + <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> + + <util:User Id="TEST_USER1" Name="testName1" Domain="TESTDOMAIN" Comment="testComment1" + Password="test123!@#" + PasswordNeverExpires="no" + PasswordExpired="yes" + Disabled="yes" + CreateUser="yes" + RemoveOnUninstall="yes"> + <util:GroupRef Id="ADMIN" /> + <util:GroupRef Id="DOMAIN_GUESTS" /> + </util:User> + </Component> + </Fragment> +</Wix> diff --git a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs index 08b7cee18..41ea2f4c8 100644 --- a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs +++ b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs @@ -79,7 +79,7 @@ public void CanRollbackUsers() // Verify that command-line parameters are not blocked by repair switches. // Original code signalled repair mode by using "-f ", which silently // terminated the command-line parsing, ignoring any parameters that followed. - [RuntimeFact()] + [RuntimeFact] public void CanRepairUsersWithCommandLineParameters() { var arguments = new string[] @@ -103,7 +103,7 @@ public void CanRepairUsersWithCommandLineParameters() // Verify that the users specified in the authoring are created as expected on repair. - [RuntimeFact()] + [RuntimeFact] public void CanRepairUsers() { UserVerifier.CreateLocalUser("testName3", "test123!@#"); @@ -279,5 +279,24 @@ public void CanDeleteCommentOfExistingUser() // clean up UserVerifier.DeleteLocalUser("testName1"); } + + // Verify that the users specified in the authoring are created as expected. + [RuntimeFact(DomainRequired = true)] + public void CanInstallAndUninstallDomainUsers() + { + var productDomain = this.CreatePackageInstaller("ProductDomain"); + + productDomain.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); + + // Validate New User Information. + UserVerifier.VerifyUserInformation("TESTDOMAIN", "testName1", true, false, true); + UserVerifier.VerifyUserIsMemberOf("TESTDOMAIN", "testName1", "Administrators", "TESTDOMAIN\\Domain Guests"); + UserVerifier.VerifyUserComment("TESTDOMAIN", "testName1", "testComment1"); + + productDomain.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); + + // Verify Users marked as RemoveOnUninstall were removed. + Assert.False(UserVerifier.UserExists("TESTDOMAIN", "testName1"), String.Format("User '{0}\\{1}' was not removed on Uninstall", "TESTDOMAIN", "testName1")); + } } } diff --git a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd index a2e67c891..ed1d50b68 100644 --- a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd +++ b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd @@ -1,2 +1,3 @@ SET RuntimeTestsEnabled=true +SET RuntimeDomainTestsEnabled=true dotnet test WixToolsetTest.MsiE2E.dll -v normal --logger trx