summaryrefslogtreecommitdiff
path: root/src/test/msi
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-04-28 21:02:23 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-04-29 00:23:14 -0500
commit5b04bce6567855325810bc4e6bcd2f6e05b329c7 (patch)
treea36e140d36c83a2ef7e81a88d941dd792bef3f55 /src/test/msi
parent681da11cfc9a266304b47b88843cb8a365015c63 (diff)
downloadwix-5b04bce6567855325810bc4e6bcd2f6e05b329c7.tar.gz
wix-5b04bce6567855325810bc4e6bcd2f6e05b329c7.tar.bz2
wix-5b04bce6567855325810bc4e6bcd2f6e05b329c7.zip
Port UtilExtension.UserTests from wix3.
Diffstat (limited to 'src/test/msi')
-rw-r--r--src/test/msi/Directory.Build.props11
-rw-r--r--src/test/msi/Directory.Build.targets6
-rw-r--r--src/test/msi/Directory.wixproj.props11
-rw-r--r--src/test/msi/Directory.wixproj.targets13
-rw-r--r--src/test/msi/MsiE2ETests.sln51
-rw-r--r--src/test/msi/README.md29
-rw-r--r--src/test/msi/TestData/Templates/CustomActionFail.exebin0 -> 4608 bytes
-rw-r--r--src/test/msi/TestData/Templates/Product.wxs47
-rw-r--r--src/test/msi/TestData/TestData.proj16
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj13
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs35
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj13
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs39
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs24
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj13
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs22
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj13
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj13
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs20
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs28
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs44
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs162
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj31
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd2
-rw-r--r--src/test/msi/test_msi.cmd23
25 files changed, 679 insertions, 0 deletions
diff --git a/src/test/msi/Directory.Build.props b/src/test/msi/Directory.Build.props
new file mode 100644
index 00000000..9e2a776f
--- /dev/null
+++ b/src/test/msi/Directory.Build.props
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3<Project>
4 <PropertyGroup>
5 <SegmentName>IntegrationMsi</SegmentName>
6 <SignOutput>false</SignOutput>
7 </PropertyGroup>
8
9 <Import Project="..\..\Directory.Build.props" />
10 <Import Project="Directory$(MSBuildProjectExtension).props" Condition=" Exists('Directory$(MSBuildProjectExtension).props') " />
11</Project>
diff --git a/src/test/msi/Directory.Build.targets b/src/test/msi/Directory.Build.targets
new file mode 100644
index 00000000..4e97b6ca
--- /dev/null
+++ b/src/test/msi/Directory.Build.targets
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3<Project>
4 <Import Project="..\..\Directory.Build.targets" />
5 <Import Project="Directory$(MSBuildProjectExtension).targets" Condition=" Exists('Directory$(MSBuildProjectExtension).targets') " />
6</Project>
diff --git a/src/test/msi/Directory.wixproj.props b/src/test/msi/Directory.wixproj.props
new file mode 100644
index 00000000..f824ff2a
--- /dev/null
+++ b/src/test/msi/Directory.wixproj.props
@@ -0,0 +1,11 @@
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<Project>
3 <PropertyGroup>
4 <TestGroupName Condition=" '$(TestGroupName)'=='' ">$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))))</TestGroupName>
5 <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(TestGroupName)\$(ProjectName)\</BaseIntermediateOutputPath>
6 <OutputPath>$(OutputPath)netcoreapp3.1\TestData\$(TestGroupName)\</OutputPath>
7 <DefaultCompressionLevel>None</DefaultCompressionLevel>
8 <CompilerAdditionalOptions>-wx</CompilerAdditionalOptions>
9 <SuppressValidation>true</SuppressValidation>
10 </PropertyGroup>
11</Project>
diff --git a/src/test/msi/Directory.wixproj.targets b/src/test/msi/Directory.wixproj.targets
new file mode 100644
index 00000000..7dddb141
--- /dev/null
+++ b/src/test/msi/Directory.wixproj.targets
@@ -0,0 +1,13 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3<Project>
4 <PropertyGroup>
5 <PackageName Condition=" '$(PackageName)' == '' ">$(MSBuildProjectName)</PackageName>
6 <DefineConstants>TestGroupName=$(TestGroupName);PackageName=$(PackageName);$(DefineConstants)</DefineConstants>
7 <DefineConstants Condition=" '$(CabPrefix)' != '' ">CabPrefix=$(CabPrefix);$(DefineConstants)</DefineConstants>
8 <DefineConstants Condition=" '$(ProductCode)' != '' ">ProductCode=$(ProductCode);$(DefineConstants)</DefineConstants>
9 <DefineConstants Condition=" '$(ProductComponentsRef)' == 'true' ">ProductComponents=1;$(DefineConstants)</DefineConstants>
10 <DefineConstants Condition=" '$(UpgradeCode)' != '' ">UpgradeCode=$(UpgradeCode);$(DefineConstants)</DefineConstants>
11 <DefineConstants Condition=" '$(Version)' != '' ">Version=$(Version);$(DefineConstants)</DefineConstants>
12 </PropertyGroup>
13</Project>
diff --git a/src/test/msi/MsiE2ETests.sln b/src/test/msi/MsiE2ETests.sln
new file mode 100644
index 00000000..c8ba93ec
--- /dev/null
+++ b/src/test/msi/MsiE2ETests.sln
@@ -0,0 +1,51 @@
1
2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio Version 17
4VisualStudioVersion = 17.0.31919.166
5MinimumVisualStudioVersion = 10.0.40219.1
6Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixTestTools", "..\burn\WixTestTools\WixTestTools.csproj", "{3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}"
7EndProject
8Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.MsiE2E", "WixToolsetTest.MsiE2E\WixToolsetTest.MsiE2E.csproj", "{68E1A5F8-0F44-4B38-8876-C101A2A019F2}"
9EndProject
10Global
11 GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 Debug|Any CPU = Debug|Any CPU
13 Debug|x64 = Debug|x64
14 Debug|x86 = Debug|x86
15 Release|Any CPU = Release|Any CPU
16 Release|x64 = Release|x64
17 Release|x86 = Release|x86
18 EndGlobalSection
19 GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x64.ActiveCfg = Debug|Any CPU
23 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x64.Build.0 = Debug|Any CPU
24 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x86.ActiveCfg = Debug|Any CPU
25 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Debug|x86.Build.0 = Debug|Any CPU
26 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|Any CPU.Build.0 = Release|Any CPU
28 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x64.ActiveCfg = Release|Any CPU
29 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x64.Build.0 = Release|Any CPU
30 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x86.ActiveCfg = Release|Any CPU
31 {3D3B02F3-79B6-4BD5-AD49-2889DA3849A7}.Release|x86.Build.0 = Release|Any CPU
32 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x64.ActiveCfg = Debug|Any CPU
35 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x64.Build.0 = Debug|Any CPU
36 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x86.ActiveCfg = Debug|Any CPU
37 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Debug|x86.Build.0 = Debug|Any CPU
38 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|Any CPU.Build.0 = Release|Any CPU
40 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x64.ActiveCfg = Release|Any CPU
41 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x64.Build.0 = Release|Any CPU
42 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x86.ActiveCfg = Release|Any CPU
43 {68E1A5F8-0F44-4B38-8876-C101A2A019F2}.Release|x86.Build.0 = Release|Any CPU
44 EndGlobalSection
45 GlobalSection(SolutionProperties) = preSolution
46 HideSolutionNode = FALSE
47 EndGlobalSection
48 GlobalSection(ExtensibilityGlobals) = postSolution
49 SolutionGuid = {4C9978E3-8548-451E-8BF5-03AD1D0280C2}
50 EndGlobalSection
51EndGlobal
diff --git a/src/test/msi/README.md b/src/test/msi/README.md
new file mode 100644
index 00000000..2b4ff9a4
--- /dev/null
+++ b/src/test/msi/README.md
@@ -0,0 +1,29 @@
1# integration
2
3This layer is for building installers, and then executing xunit tests that run them and verify that they worked.
4
5## Running tests
6
7The main focus of these tests is to validate behavior in a real environment.
8Depending on who you talk to, these are integration or system-level or end-to-end (E2E) tests.
9They modify machine state so it's strongly recommended *not* to run these tests on your dev box.
10They should be run on a VM instead, where you can easily roll back.
11
121. Run build.cmd to build everything (the tests will not automatically run).
131. Copy the build\IntegrationMsi\Debug\netcoreapp3.1 folder to your VM.
141. Open an elevated command prompt and navigate to the netcoreapp3.1 folder.
151. Run the runtests.cmd file to run the tests.
16
17You can modify the runtests.cmd to run specific tests.
18For example, the following line runs only the specified test:
19
20> dotnet test --filter WixToolsetTest.BurnE2E.BasicFunctionalityTests.CanInstallAndUninstallSimpleBundle_x86_wixstdba WixToolsetTest.BurnE2E.dll
21
22The VM must have:
231. x64 .NET Core SDK of 3.1 or later (for the test runner)
24
25## Building with local changes
26
27The current build process will poison your NuGet package cache, so you may have to run the following command to clear it:
28
29> nuget locals all -clear \ No newline at end of file
diff --git a/src/test/msi/TestData/Templates/CustomActionFail.exe b/src/test/msi/TestData/Templates/CustomActionFail.exe
new file mode 100644
index 00000000..cceffe91
--- /dev/null
+++ b/src/test/msi/TestData/Templates/CustomActionFail.exe
Binary files differ
diff --git a/src/test/msi/TestData/Templates/Product.wxs b/src/test/msi/TestData/Templates/Product.wxs
new file mode 100644
index 00000000..c7604c1b
--- /dev/null
+++ b/src/test/msi/TestData/Templates/Product.wxs
@@ -0,0 +1,47 @@
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
4
5<?ifndef Version?>
6<?define Version = 1.0.0.0?>
7<?endif?>
8
9<?ifndef ProductCode?>
10<?define ProductCode = *?>
11<?endif?>
12
13<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
14 <Package Name="~$(var.TestGroupName) - $(var.PackageName)" Language="1033" Version="$(var.Version)" Manufacturer="WixToolset" UpgradeCode="$(var.UpgradeCode)" Compressed="yes" ProductCode="$(var.ProductCode)">
15 <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
16 <?ifndef CabPrefix?>
17 <MediaTemplate EmbedCab="yes" />
18 <?else?>
19 <MediaTemplate CabinetTemplate="{0}$(var.CabPrefix).cab" />
20 <?endif?>
21
22 <Feature Id="Complete" Level="1">
23 <ComponentRef Id="FileComponent" />
24 <?ifdef var.ProductComponents?>
25 <ComponentGroupRef Id="ProductComponents" />
26 <?endif?>
27 </Feature>
28 </Package>
29
30 <Fragment>
31 <StandardDirectory Id="ProgramFiles6432Folder">
32 <Directory Id="WixDir" Name="~Test WiX">
33 <Directory Id="TestDir" Name="$(var.TestGroupName)">
34 <Directory Id="INSTALLFOLDER" Name="$(var.PackageName)" />
35 </Directory>
36 </Directory>
37 </StandardDirectory>
38 </Fragment>
39
40 <Fragment>
41 <Component Id="FileComponent" Guid="12345678-9ABC-DEF0-1234-567890000000" Directory="INSTALLFOLDER">
42 <File Id="CAFile" Name="CustomActionFail.exe" Source="$(sys.SOURCEFILEDIR)\CustomActionFail.exe" />
43 </Component>
44
45 <CustomAction Id="CaFail" FileRef="CAFile" Execute="immediate" Return="check" ExeCommand="" />
46 </Fragment>
47</Wix>
diff --git a/src/test/msi/TestData/TestData.proj b/src/test/msi/TestData/TestData.proj
new file mode 100644
index 00000000..9e130987
--- /dev/null
+++ b/src/test/msi/TestData/TestData.proj
@@ -0,0 +1,16 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <ItemGroup>
6 <TestDataProject Include="**\*.wixproj" />
7 </ItemGroup>
8
9 <Target Name="Build">
10 <MSBuild Projects="%(TestDataProject.Identity)" />
11 </Target>
12
13 <Target Name="Restore">
14 <MSBuild Projects="%(TestDataProject.Identity)" Targets="Restore" />
15 </Target>
16</Project>
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj
new file mode 100644
index 00000000..fbc6f292
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/ProductA.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{1A1795A6-87C0-4A9A-ABD5-DF9BED697037}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Util.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs
new file mode 100644
index 00000000..a7bec54e
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductA/product.wxs
@@ -0,0 +1,35 @@
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
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="Component1" />
8 </ComponentGroup>
9
10 <Property Id="TEMPDOMAIN" Secure="yes" />
11 <Property Id="TEMPUSERNAME" Secure="yes" />
12 </Fragment>
13
14 <Fragment>
15 <util:Group Id="ADMIN" Name="Administrators" />
16 <util:Group Id="POWER_USER" Name="Power Users" />
17
18 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
19 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
20
21 <util:User Id="TEST_USER1" Name="testName1" Password="test123!@#" PasswordExpired="yes">
22 <util:GroupRef Id="ADMIN" />
23 <util:GroupRef Id="POWER_USER" />
24 </util:User>
25
26 <util:User Id="TEST_USER2" Name="testName2" Password="test123!@#" Disabled="yes" RemoveOnUninstall="no" PasswordNeverExpires="yes" UpdateIfExists="yes">
27 <util:GroupRef Id="POWER_USER" />
28 </util:User>
29
30 <util:User Id="TEST_USER3" Name="[TEMPUSERNAME]" Domain="[TEMPDOMAIN]" CreateUser="no">
31 <util:GroupRef Id="POWER_USER" />
32 </util:User>
33 </Component>
34 </Fragment>
35</Wix>
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj
new file mode 100644
index 00000000..e2fe3aa8
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/ProductFail.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{91D27DAC-04C1-4160-914E-343676D36CAA}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Util.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs
new file mode 100644
index 00000000..c5da862c
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFail/product_fail.wxs
@@ -0,0 +1,39 @@
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
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="Component1" />
8 </ComponentGroup>
9
10 <Property Id="TEMPDOMAIN" Secure="yes" />
11 <Property Id="TEMPUSERNAME" Secure="yes" />
12
13 <InstallExecuteSequence>
14 <Custom Action="CaFail" After="Wix4ConfigureUsers_X86" />
15 </InstallExecuteSequence>
16 </Fragment>
17
18 <Fragment>
19 <util:Group Id="ADMIN" Name="Administrators" />
20 <util:Group Id="POWER_USER" Name="Power Users" />
21
22 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
23 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
24
25 <util:User Id="TEST_USER1" Name="testName1" Password="test123!@#" PasswordExpired="yes">
26 <util:GroupRef Id="ADMIN" />
27 <util:GroupRef Id="POWER_USER" />
28 </util:User>
29
30 <util:User Id="TEST_USER2" Name="testName2" Password="test123!@#" Disabled="yes" RemoveOnUninstall="no" PasswordNeverExpires="yes" UpdateIfExists="yes">
31 <util:GroupRef Id="POWER_USER" />
32 </util:User>
33
34 <util:User Id="TEST_USER3" Name="[TEMPUSERNAME]" Domain="[TEMPDOMAIN]" CreateUser="no">
35 <util:GroupRef Id="POWER_USER" />
36 </util:User>
37 </Component>
38 </Fragment>
39</Wix>
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs
new file mode 100644
index 00000000..0da4f2b9
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/FailIfExists.wxs
@@ -0,0 +1,24 @@
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
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="Component1" />
8 </ComponentGroup>
9 </Fragment>
10
11 <Fragment>
12 <util:Group Id="ADMIN" Name="Administrators" />
13 <util:Group Id="POWER_USER" Name="Power Users" />
14
15 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
16 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
17
18 <util:User Id="TEST_USER4" Name="existinguser" Password="test123!@#" LogonAsService="yes" FailIfExists="yes" RemoveOnUninstall="yes">
19 <util:GroupRef Id="ADMIN" />
20 <util:GroupRef Id="POWER_USER" />
21 </util:User>
22 </Component>
23 </Fragment>
24</Wix>
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj
new file mode 100644
index 00000000..9e1a836f
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductFailIfExists/ProductFailIfExists.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{BC803822-929E-47DA-AB3A-3A62EEEA2BFB}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Util.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs
new file mode 100644
index 00000000..461648ee
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs
@@ -0,0 +1,22 @@
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
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="Component1" />
8 </ComponentGroup>
9 </Fragment>
10
11 <Fragment>
12 <util:Group Id="ShouldNotExist" Name="Should Not Exist" />
13
14 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
15 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
16
17 <util:User Id="CurrentUser" Name="[LogonUser]" Domain="[%USERDOMAIN]" RemoveOnUninstall="no" Vital="no">
18 <util:GroupRef Id="ShouldNotExist" />
19 </util:User>
20 </Component>
21 </Fragment>
22</Wix>
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj
new file mode 100644
index 00000000..8734224d
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/ProductNonVitalUserGroup.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{455C8D4F-6D59-405C-AD51-0ACC7FB91A26}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Util.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj
new file mode 100644
index 00000000..e4a01a3a
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/ProductRestrictedDomain.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{50CF526C-A862-4327-9EA3-C96AAB6FABCE}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Util.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs
new file mode 100644
index 00000000..f200a06a
--- /dev/null
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductRestrictedDomain/RestrictedDomain.wxs
@@ -0,0 +1,20 @@
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
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="Component1" />
8 </ComponentGroup>
9
10 <Property Id="TEMPDOMAIN" Secure="yes" />
11 </Fragment>
12
13 <Fragment>
14 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
15 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
16
17 <util:User Id="TEST_USER_test" Name="testName1" Domain="[TEMPDOMAIN]" Password="test123!@#" PasswordExpired="no" />
18 </Component>
19 </Fragment>
20</Wix>
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs
new file mode 100644
index 00000000..a7646568
--- /dev/null
+++ b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2EFixture.cs
@@ -0,0 +1,28 @@
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
3namespace WixToolsetTest.MsiE2E
4{
5 using System;
6 using System.Security.Principal;
7
8 public class MsiE2EFixture
9 {
10 const string RequiredEnvironmentVariableName = "RuntimeTestsEnabled";
11
12 public MsiE2EFixture()
13 {
14 using var identity = WindowsIdentity.GetCurrent();
15 var principal = new WindowsPrincipal(identity);
16 if (!principal.IsInRole(WindowsBuiltInRole.Administrator))
17 {
18 throw new InvalidOperationException("These tests must run elevated.");
19 }
20
21 var testsEnabledString = Environment.GetEnvironmentVariable(RequiredEnvironmentVariableName);
22 if (!bool.TryParse(testsEnabledString, out var testsEnabled) || !testsEnabled)
23 {
24 throw new InvalidOperationException($"These tests affect machine state. Set the {RequiredEnvironmentVariableName} environment variable to true to accept the consequences.");
25 }
26 }
27 }
28}
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs
new file mode 100644
index 00000000..22f2173b
--- /dev/null
+++ b/src/test/msi/WixToolsetTest.MsiE2E/MsiE2ETests.cs
@@ -0,0 +1,44 @@
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
3namespace WixToolsetTest.MsiE2E
4{
5 using System;
6 using System.Collections.Generic;
7 using WixTestTools;
8 using Xunit;
9 using Xunit.Abstractions;
10
11 [Collection("MsiE2E")]
12 public abstract class MsiE2ETests : WixTestBase, IDisposable
13 {
14 protected MsiE2ETests(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
15 {
16 }
17
18 private Stack<IDisposable> Installers { get; } = new Stack<IDisposable>();
19
20 protected PackageInstaller CreatePackageInstaller(string filename)
21 {
22 var installer = new PackageInstaller(this.TestContext, filename);
23 this.Installers.Push(installer);
24 return installer;
25 }
26
27 public void Dispose()
28 {
29 while (this.Installers.TryPop(out var installer))
30 {
31 try
32 {
33 installer.Dispose();
34 }
35 catch { }
36 }
37 }
38 }
39
40 [CollectionDefinition("MsiE2E", DisableParallelization = true)]
41 public class MsiE2ECollectionDefinition : ICollectionFixture<MsiE2EFixture>
42 {
43 }
44}
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs
new file mode 100644
index 00000000..21491858
--- /dev/null
+++ b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionUserTests.cs
@@ -0,0 +1,162 @@
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
3namespace WixToolsetTest.MsiE2E
4{
5 using System;
6 using WixTestTools;
7 using Xunit;
8 using Xunit.Abstractions;
9
10 public class UtilExtensionUserTests : MsiE2ETests
11 {
12 public UtilExtensionUserTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
13
14 const string TempDomain = "USERDOMAIN";
15 const string TempUsername = "USERNAME";
16
17 // Verify that the users specified in the authoring are created as expected.
18 [Fact]
19 public void CanInstallAndUninstallUsers()
20 {
21 var arguments = new string[]
22 {
23 $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}",
24 $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}",
25 };
26 var productA = this.CreatePackageInstaller("ProductA");
27
28 productA.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments);
29
30 // Validate New User Information.
31 UserVerifier.VerifyUserInformation(String.Empty, "testName1", true, false, false);
32 UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName1", "Administrators", "Power Users");
33
34 UserVerifier.VerifyUserInformation(String.Empty, "testName2", true, true, true);
35 UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName2", "Power Users");
36
37 UserVerifier.VerifyUserIsMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
38
39 productA.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments);
40
41 // Verify Users marked as RemoveOnUninstall were removed.
42 Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Uninstall", "testName1"));
43 Assert.True(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was removed on Uninstall", "testName2"));
44
45 // clean up
46 UserVerifier.DeleteLocalUser("testName2");
47
48 UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
49 }
50
51 // Verify the rollback action reverts all Users changes.
52 [Fact]
53 public void CanRollbackUsers()
54 {
55 var arguments = new string[]
56 {
57 $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}",
58 $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}",
59 };
60 var productFail = this.CreatePackageInstaller("ProductFail");
61
62 // make sure the user accounts are deleted before we start
63 UserVerifier.DeleteLocalUser("testName1");
64 UserVerifier.DeleteLocalUser("testName2");
65 UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
66
67 productFail.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, arguments);
68
69 // Verify Users marked as RemoveOnUninstall were removed.
70 Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Rollback", "testName1"));
71 Assert.False(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was not removed on Rollback", "testName2"));
72
73 UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
74 }
75
76 // Verify that the users specified in the authoring are created as expected on repair.
77 [Fact(Skip = "Test demonstrates failure")]
78 public void CanRepairUsers()
79 {
80 var arguments = new string[]
81 {
82 $"TEMPDOMAIN={Environment.GetEnvironmentVariable(TempDomain)}",
83 $"TEMPUSERNAME={Environment.GetEnvironmentVariable(TempUsername)}",
84 };
85 var productA = this.CreatePackageInstaller("ProductA");
86
87 productA.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments);
88
89 UserVerifier.DeleteLocalUser("testName1");
90 UserVerifier.SetUserInformation(String.Empty, "testName2", true, false, false);
91
92 productA.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments);
93
94 // Validate New User Information.
95 UserVerifier.VerifyUserInformation(String.Empty, "testName1", true, false, false);
96 UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName1", "Administrators", "Power Users");
97
98 UserVerifier.VerifyUserInformation(String.Empty, "testName2", true, true, true);
99 UserVerifier.VerifyUserIsMemberOf(String.Empty, "testName2", "Power Users");
100
101 UserVerifier.VerifyUserIsMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
102
103 productA.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, arguments);
104
105 // Verify Users marked as RemoveOnUninstall were removed.
106 Assert.False(UserVerifier.UserExists(String.Empty, "testName1"), String.Format("User '{0}' was not removed on Uninstall", "testName1"));
107 Assert.True(UserVerifier.UserExists(String.Empty, "testName2"), String.Format("User '{0}' was removed on Uninstall", "testName2"));
108
109 // clean up
110 UserVerifier.DeleteLocalUser("testName2");
111
112 UserVerifier.VerifyUserIsNotMemberOf(Environment.GetEnvironmentVariable(TempDomain), Environment.GetEnvironmentVariable(TempUsername), "Power Users");
113 }
114
115 // Verify that Installation fails if FailIfExisits is set.
116 [Fact]
117 public void FailsIfUserExists()
118 {
119 var productFailIfExists = this.CreatePackageInstaller("ProductFailIfExists");
120
121 // Create 'existinguser'
122 UserVerifier.CreateLocalUser("existinguser", "test123!@#");
123
124 try
125 {
126 productFailIfExists.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE);
127
128 // Verify User still exists.
129 bool userExists = UserVerifier.UserExists(String.Empty, "existinguser");
130
131 Assert.True(userExists, String.Format("User '{0}' was removed on Rollback", "existinguser"));
132 }
133 finally
134 {
135 // clean up
136 UserVerifier.DeleteLocalUser("existinguser");
137 }
138
139 }
140
141 // Verify that a user cannot be created on a domain on which you dont have create user permission.
142 [Fact]
143 public void FailsIfRestrictedDomain()
144 {
145 var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain");
146
147 string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "TEMPDOMAIN=DOESNOTEXIST");
148
149 // Verify expected error message in the log file
150 Assert.True(LogVerifier.MessageInLogFile(logFile, "ConfigureUsers: Failed to check existence of domain: DOESNOTEXIST, user: testName1 (error code 0x800706ba) - continuing"));
151 }
152
153 // Verify that adding a user to a non-existent group does not fail the install when non-vital.
154 [Fact]
155 public void IgnoresMissingGroupWhenNonVital()
156 {
157 var productNonVitalGroup = this.CreatePackageInstaller("ProductNonVitalUserGroup");
158
159 productNonVitalGroup.InstallProduct();
160 }
161 }
162}
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
new file mode 100644
index 00000000..ccf98042
--- /dev/null
+++ b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
@@ -0,0 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netcoreapp3.1</TargetFramework>
7 <PlatformTarget>x64</PlatformTarget>
8 <RollForward>Major</RollForward>
9 </PropertyGroup>
10
11 <ItemGroup>
12 <Content Include="runtests.cmd" CopyToOutputDirectory="PreserveNewest" />
13 </ItemGroup>
14
15 <ItemGroup>
16 <ProjectReference Include="..\..\burn\WixTestTools\WixTestTools.csproj" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <PackageReference Include="Microsoft.Win32.Registry" />
21 <PackageReference Include="System.Security.Principal.Windows" />
22 <PackageReference Include="WixBuildTools.TestSupport" />
23 <PackageReference Include="WixToolset.Data" />
24 </ItemGroup>
25
26 <ItemGroup>
27 <PackageReference Include="Microsoft.NET.Test.Sdk" />
28 <PackageReference Include="xunit" />
29 <PackageReference Include="xunit.runner.visualstudio" PrivateAssets="All" />
30 </ItemGroup>
31</Project>
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd
new file mode 100644
index 00000000..f609ebe4
--- /dev/null
+++ b/src/test/msi/WixToolsetTest.MsiE2E/runtests.cmd
@@ -0,0 +1,2 @@
1SET RuntimeTestsEnabled=true
2dotnet test WixToolsetTest.MsiE2E.dll -v normal \ No newline at end of file
diff --git a/src/test/msi/test_msi.cmd b/src/test/msi/test_msi.cmd
new file mode 100644
index 00000000..bb9d0162
--- /dev/null
+++ b/src/test/msi/test_msi.cmd
@@ -0,0 +1,23 @@
1@setlocal
2@pushd %~dp0
3
4@set _RESULT=0
5@set _C=Debug
6@set _L=%~dp0..\..\..\build\logs
7:parse_args
8@if /i "%1"=="release" set _C=Release
9@if /i "%1"=="test" set RuntimeTestsEnabled=true
10@if not "%1"=="" shift & goto parse_args
11
12@echo Msi integration tests %_C%
13
14msbuild -t:Build -Restore -p:Configuration=%_C% -warnaserror -bl:%_L%\test_msi_build.binlog || exit /b
15msbuild -t:Build -Restore TestData\TestData.proj -p:Configuration=%_C% -m -bl:%_L%\test_msi_data_build.binlog || exit /b
16
17@if not "%RuntimeTestsEnabled%"=="true" goto :LExit
18
19dotnet test -c %_C% --no-build WixToolsetTest.MsiE2E -l "trx;LogFileName=%_L%\TestResults\WixToolsetTest.MsiE2E.trx" || exit /b
20
21:LExit
22@popd
23@endlocal