From 99d7440134d0f33683d1150a770a2bc594be41de Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 8 Mar 2021 16:06:01 -0600 Subject: Port dependency tests from old repo. --- .../DependencyTests/BundleAv1/BundleA.props | 11 + .../DependencyTests/BundleAv1/BundleAv1.wixproj | 16 + .../DependencyTests/BundleAv1/BundleAv1.wxs | 21 + .../BundleAv1_0_1/BundleAv1_0_1.wixproj | 16 + .../BundleAv1_0_1/BundleAv1_0_1.wxs | 21 + src/TestData/DependencyTests/BundleB/Bundle.wxs | 40 ++ .../DependencyTests/BundleB/BundleB.wixproj | 18 + src/TestData/DependencyTests/BundleB/BundleB.wxs | 22 + .../DependencyTests/BundleC/BundleC.wixproj | 22 + src/TestData/DependencyTests/BundleC/BundleC.wxs | 12 + .../DependencyTests/BundleD/BundleD.wixproj | 22 + src/TestData/DependencyTests/BundleD/BundleD.wxs | 12 + .../DependencyTests/BundleE/BundleE.wixproj | 21 + src/TestData/DependencyTests/BundleE/BundleE.wxs | 19 + .../DependencyTests/BundleF/BundleF.wixproj | 21 + src/TestData/DependencyTests/BundleF/BundleF.wxs | 12 + .../BundleF_AddOnA/BundleF_AddOn.wxs | 22 + .../BundleF_AddOnA/BundleF_AddOnA.wixproj | 20 + .../BundleF_AddOnB/BundleF_AddOnB.wixproj | 21 + .../BundleF_PatchAv1_0_1/BundleF_PatchA.props | 11 + .../BundleF_PatchAv1_0_1.wixproj | 16 + .../BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wxs | 13 + .../BundleF_PatchAv1_0_2.wixproj | 17 + .../BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wxs | 16 + .../DependencyTests/BundleHv1/BundleH.props | 10 + .../DependencyTests/BundleHv1/BundleHv1.wixproj | 13 + .../DependencyTests/BundleHv1/BundleHv1.wxs | 11 + .../DependencyTests/BundleHv2/BundleHv2.wixproj | 16 + .../DependencyTests/BundleHv2/BundleHv2.wxs | 11 + .../DependencyTests/BundleJ/BundleJ.wixproj | 21 + src/TestData/DependencyTests/BundleJ/BundleJ.wxs | 12 + .../BundleJ_Patch/BundleJ_Patch.wixproj | 21 + .../BundleJ_Patch/BundleJ_Patch.wxs | 16 + .../DependencyTests/BundleL/BundleL.wixproj | 20 + src/TestData/DependencyTests/BundleL/BundleL.wxs | 10 + .../DependencyTests/PackageAv1/PackageA.props | 12 + .../DependencyTests/PackageAv1/PackageAv1.wixproj | 7 + .../PackageAv1/ProductComponents.wxs | 16 + .../PackageAv1_0_1/PackageAv1_0_1.wixproj | 13 + .../PackageAv1_0_2/PackageAv1_0_2.wixproj | 13 + .../DependencyTests/PackageB/PackageB.wixproj | 13 + .../DependencyTests/PackageB/ProductComponents.wxs | 18 + .../DependencyTests/PackageC/PackageC.wixproj | 13 + .../DependencyTests/PackageDv1/Package.wxs | 66 +++ .../DependencyTests/PackageDv1/PackageD.props | 7 + .../DependencyTests/PackageDv1/PackageDv1.wixproj | 7 + .../DependencyTests/PackageDv2/PackageDv2.wixproj | 13 + .../DependencyTests/PackageEv1/PackageE.props | 12 + .../DependencyTests/PackageEv1/PackageEv1.wixproj | 7 + .../PackageEv1/ProductComponents.wxs | 16 + .../PackageEv1_0_1/PackageEv1_0_1.wixproj | 13 + src/TestData/DependencyTests/PatchA/PatchA.wixproj | 15 + src/TestData/DependencyTests/PatchA/PatchA.wxs | 22 + src/TestData/DependencyTests/PatchB/PatchB.wixproj | 15 + src/TestData/DependencyTests/PatchB/PatchB.wxs | 21 + src/TestData/Templates/PackageFail.wxs | 2 +- src/TestData/TestBA/TestBAWixlib/TestExe.wxs | 9 + .../TestBA/TestBAWixlib/testbawixlib.wixproj | 1 + src/TestData/TestData.proj | 8 + src/TestExe/Program.cs | 74 +++ src/TestExe/Task.cs | 471 +++++++++++++++++ src/TestExe/TestExe.csproj | 17 + src/TestExe/app.config | 10 + src/WixTestTools/BundleInstaller.cs | 3 + src/WixTestTools/BundleRegistration.cs | 14 +- src/WixTestTools/BundleVerifier.cs | 65 ++- src/WixTestTools/MsiUtilities.cs | 20 + src/WixTestTools/PackageVerifier.cs | 7 + src/WixTestTools/WixTestTools.csproj | 2 +- src/WixToolsetTest.BurnE2E/DependencyTests.cs | 586 ++++++++++++++++++++- .../WixToolsetTest.BurnE2E.csproj | 2 +- 71 files changed, 2190 insertions(+), 23 deletions(-) create mode 100644 src/TestData/DependencyTests/BundleAv1/BundleA.props create mode 100644 src/TestData/DependencyTests/BundleAv1/BundleAv1.wixproj create mode 100644 src/TestData/DependencyTests/BundleAv1/BundleAv1.wxs create mode 100644 src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wixproj create mode 100644 src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wxs create mode 100644 src/TestData/DependencyTests/BundleB/Bundle.wxs create mode 100644 src/TestData/DependencyTests/BundleB/BundleB.wixproj create mode 100644 src/TestData/DependencyTests/BundleB/BundleB.wxs create mode 100644 src/TestData/DependencyTests/BundleC/BundleC.wixproj create mode 100644 src/TestData/DependencyTests/BundleC/BundleC.wxs create mode 100644 src/TestData/DependencyTests/BundleD/BundleD.wixproj create mode 100644 src/TestData/DependencyTests/BundleD/BundleD.wxs create mode 100644 src/TestData/DependencyTests/BundleE/BundleE.wixproj create mode 100644 src/TestData/DependencyTests/BundleE/BundleE.wxs create mode 100644 src/TestData/DependencyTests/BundleF/BundleF.wixproj create mode 100644 src/TestData/DependencyTests/BundleF/BundleF.wxs create mode 100644 src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOn.wxs create mode 100644 src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOnA.wixproj create mode 100644 src/TestData/DependencyTests/BundleF_AddOnB/BundleF_AddOnB.wixproj create mode 100644 src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchA.props create mode 100644 src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wixproj create mode 100644 src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wxs create mode 100644 src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wixproj create mode 100644 src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wxs create mode 100644 src/TestData/DependencyTests/BundleHv1/BundleH.props create mode 100644 src/TestData/DependencyTests/BundleHv1/BundleHv1.wixproj create mode 100644 src/TestData/DependencyTests/BundleHv1/BundleHv1.wxs create mode 100644 src/TestData/DependencyTests/BundleHv2/BundleHv2.wixproj create mode 100644 src/TestData/DependencyTests/BundleHv2/BundleHv2.wxs create mode 100644 src/TestData/DependencyTests/BundleJ/BundleJ.wixproj create mode 100644 src/TestData/DependencyTests/BundleJ/BundleJ.wxs create mode 100644 src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wixproj create mode 100644 src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wxs create mode 100644 src/TestData/DependencyTests/BundleL/BundleL.wixproj create mode 100644 src/TestData/DependencyTests/BundleL/BundleL.wxs create mode 100644 src/TestData/DependencyTests/PackageAv1/PackageA.props create mode 100644 src/TestData/DependencyTests/PackageAv1/PackageAv1.wixproj create mode 100644 src/TestData/DependencyTests/PackageAv1/ProductComponents.wxs create mode 100644 src/TestData/DependencyTests/PackageAv1_0_1/PackageAv1_0_1.wixproj create mode 100644 src/TestData/DependencyTests/PackageAv1_0_2/PackageAv1_0_2.wixproj create mode 100644 src/TestData/DependencyTests/PackageB/PackageB.wixproj create mode 100644 src/TestData/DependencyTests/PackageB/ProductComponents.wxs create mode 100644 src/TestData/DependencyTests/PackageC/PackageC.wixproj create mode 100644 src/TestData/DependencyTests/PackageDv1/Package.wxs create mode 100644 src/TestData/DependencyTests/PackageDv1/PackageD.props create mode 100644 src/TestData/DependencyTests/PackageDv1/PackageDv1.wixproj create mode 100644 src/TestData/DependencyTests/PackageDv2/PackageDv2.wixproj create mode 100644 src/TestData/DependencyTests/PackageEv1/PackageE.props create mode 100644 src/TestData/DependencyTests/PackageEv1/PackageEv1.wixproj create mode 100644 src/TestData/DependencyTests/PackageEv1/ProductComponents.wxs create mode 100644 src/TestData/DependencyTests/PackageEv1_0_1/PackageEv1_0_1.wixproj create mode 100644 src/TestData/DependencyTests/PatchA/PatchA.wixproj create mode 100644 src/TestData/DependencyTests/PatchA/PatchA.wxs create mode 100644 src/TestData/DependencyTests/PatchB/PatchB.wixproj create mode 100644 src/TestData/DependencyTests/PatchB/PatchB.wxs create mode 100644 src/TestData/TestBA/TestBAWixlib/TestExe.wxs create mode 100644 src/TestExe/Program.cs create mode 100644 src/TestExe/Task.cs create mode 100644 src/TestExe/TestExe.csproj create mode 100644 src/TestExe/app.config (limited to 'src') diff --git a/src/TestData/DependencyTests/BundleAv1/BundleA.props b/src/TestData/DependencyTests/BundleAv1/BundleA.props new file mode 100644 index 00000000..256501c7 --- /dev/null +++ b/src/TestData/DependencyTests/BundleAv1/BundleA.props @@ -0,0 +1,11 @@ + + + + Bundle + BundleA + {6950EF3F-674E-4689-A5C8-80D12AB6E34F} + + + + + diff --git a/src/TestData/DependencyTests/BundleAv1/BundleAv1.wixproj b/src/TestData/DependencyTests/BundleAv1/BundleAv1.wixproj new file mode 100644 index 00000000..ede63892 --- /dev/null +++ b/src/TestData/DependencyTests/BundleAv1/BundleAv1.wixproj @@ -0,0 +1,16 @@ + + + + + 1.0.0.0 + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleAv1/BundleAv1.wxs b/src/TestData/DependencyTests/BundleAv1/BundleAv1.wxs new file mode 100644 index 00000000..9218e823 --- /dev/null +++ b/src/TestData/DependencyTests/BundleAv1/BundleAv1.wxs @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wixproj b/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wixproj new file mode 100644 index 00000000..26a61a70 --- /dev/null +++ b/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wixproj @@ -0,0 +1,16 @@ + + + + + 1.0.1.0 + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wxs b/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wxs new file mode 100644 index 00000000..1590574f --- /dev/null +++ b/src/TestData/DependencyTests/BundleAv1_0_1/BundleAv1_0_1.wxs @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleB/Bundle.wxs b/src/TestData/DependencyTests/BundleB/Bundle.wxs new file mode 100644 index 00000000..8d2dce60 --- /dev/null +++ b/src/TestData/DependencyTests/BundleB/Bundle.wxs @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleB/BundleB.wixproj b/src/TestData/DependencyTests/BundleB/BundleB.wixproj new file mode 100644 index 00000000..34c76ccb --- /dev/null +++ b/src/TestData/DependencyTests/BundleB/BundleB.wixproj @@ -0,0 +1,18 @@ + + + + Bundle + {228859BB-F917-4F43-A1E0-50C8DCCA92EF} + 1.0.0.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleB/BundleB.wxs b/src/TestData/DependencyTests/BundleB/BundleB.wxs new file mode 100644 index 00000000..026100fa --- /dev/null +++ b/src/TestData/DependencyTests/BundleB/BundleB.wxs @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleC/BundleC.wixproj b/src/TestData/DependencyTests/BundleC/BundleC.wixproj new file mode 100644 index 00000000..f77e772f --- /dev/null +++ b/src/TestData/DependencyTests/BundleC/BundleC.wixproj @@ -0,0 +1,22 @@ + + + + Bundle + + {6950EF3F-674E-4689-A5C8-80D12AB6E34F} + 1.0.1.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleC/BundleC.wxs b/src/TestData/DependencyTests/BundleC/BundleC.wxs new file mode 100644 index 00000000..2ce8ed44 --- /dev/null +++ b/src/TestData/DependencyTests/BundleC/BundleC.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleD/BundleD.wixproj b/src/TestData/DependencyTests/BundleD/BundleD.wixproj new file mode 100644 index 00000000..6f2f098e --- /dev/null +++ b/src/TestData/DependencyTests/BundleD/BundleD.wixproj @@ -0,0 +1,22 @@ + + + + Bundle + + {6950EF3F-674E-4689-A5C8-80D12AB6E34F} + 1.0.1.0 + 1153 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleD/BundleD.wxs b/src/TestData/DependencyTests/BundleD/BundleD.wxs new file mode 100644 index 00000000..8ee40558 --- /dev/null +++ b/src/TestData/DependencyTests/BundleD/BundleD.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleE/BundleE.wixproj b/src/TestData/DependencyTests/BundleE/BundleE.wixproj new file mode 100644 index 00000000..e43ffceb --- /dev/null +++ b/src/TestData/DependencyTests/BundleE/BundleE.wixproj @@ -0,0 +1,21 @@ + + + + Bundle + {250B4261-E67F-47E0-AB15-209EF58B769D} + 1.0.0.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleE/BundleE.wxs b/src/TestData/DependencyTests/BundleE/BundleE.wxs new file mode 100644 index 00000000..204e66ab --- /dev/null +++ b/src/TestData/DependencyTests/BundleE/BundleE.wxs @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleF/BundleF.wixproj b/src/TestData/DependencyTests/BundleF/BundleF.wixproj new file mode 100644 index 00000000..0bbe9ae6 --- /dev/null +++ b/src/TestData/DependencyTests/BundleF/BundleF.wixproj @@ -0,0 +1,21 @@ + + + + Bundle + {EC2B2B3F-E57C-45A4-A0E8-762156DAD99D} + 1.0.0.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleF/BundleF.wxs b/src/TestData/DependencyTests/BundleF/BundleF.wxs new file mode 100644 index 00000000..1347836a --- /dev/null +++ b/src/TestData/DependencyTests/BundleF/BundleF.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOn.wxs b/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOn.wxs new file mode 100644 index 00000000..c8ca4a3f --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOn.wxs @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOnA.wixproj b/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOnA.wixproj new file mode 100644 index 00000000..31994fb1 --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_AddOnA/BundleF_AddOnA.wixproj @@ -0,0 +1,20 @@ + + + + Bundle + {022D0F5D-D140-47E1-A19A-5B2CEEE52668} + 1.0.0.0 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleF_AddOnB/BundleF_AddOnB.wixproj b/src/TestData/DependencyTests/BundleF_AddOnB/BundleF_AddOnB.wixproj new file mode 100644 index 00000000..056f8a1b --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_AddOnB/BundleF_AddOnB.wixproj @@ -0,0 +1,21 @@ + + + + Bundle + {8AB16F34-CA65-46E1-BDC0-08F157B4781C} + 1.0.0.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchA.props b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchA.props new file mode 100644 index 00000000..cbc025ef --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchA.props @@ -0,0 +1,11 @@ + + + + Bundle + BundleF_PatchA + {90F41437-BEF8-4ED8-8902-C5DED74E4F6C} + + + + + diff --git a/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wixproj b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wixproj new file mode 100644 index 00000000..3c113acd --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wixproj @@ -0,0 +1,16 @@ + + + + + 1.0.1.0 + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wxs b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wxs new file mode 100644 index 00000000..8ef8a351 --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_PatchAv1_0_1/BundleF_PatchAv1_0_1.wxs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wixproj b/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wixproj new file mode 100644 index 00000000..cd88b4bf --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wixproj @@ -0,0 +1,17 @@ + + + + + 1.0.2.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wxs b/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wxs new file mode 100644 index 00000000..2b47d5ed --- /dev/null +++ b/src/TestData/DependencyTests/BundleF_PatchAv1_0_2/BundleF_PatchAv1_0_2.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleHv1/BundleH.props b/src/TestData/DependencyTests/BundleHv1/BundleH.props new file mode 100644 index 00000000..14801ec3 --- /dev/null +++ b/src/TestData/DependencyTests/BundleHv1/BundleH.props @@ -0,0 +1,10 @@ + + + + Bundle + {C5EA6B61-EF32-48E0-A6F9-08EB6D096843} + + + + + diff --git a/src/TestData/DependencyTests/BundleHv1/BundleHv1.wixproj b/src/TestData/DependencyTests/BundleHv1/BundleHv1.wixproj new file mode 100644 index 00000000..7c3d87f2 --- /dev/null +++ b/src/TestData/DependencyTests/BundleHv1/BundleHv1.wixproj @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleHv1/BundleHv1.wxs b/src/TestData/DependencyTests/BundleHv1/BundleHv1.wxs new file mode 100644 index 00000000..b553d829 --- /dev/null +++ b/src/TestData/DependencyTests/BundleHv1/BundleHv1.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleHv2/BundleHv2.wixproj b/src/TestData/DependencyTests/BundleHv2/BundleHv2.wixproj new file mode 100644 index 00000000..4cf14238 --- /dev/null +++ b/src/TestData/DependencyTests/BundleHv2/BundleHv2.wixproj @@ -0,0 +1,16 @@ + + + + + 2.0.0.0 + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleHv2/BundleHv2.wxs b/src/TestData/DependencyTests/BundleHv2/BundleHv2.wxs new file mode 100644 index 00000000..690f8e7a --- /dev/null +++ b/src/TestData/DependencyTests/BundleHv2/BundleHv2.wxs @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleJ/BundleJ.wixproj b/src/TestData/DependencyTests/BundleJ/BundleJ.wixproj new file mode 100644 index 00000000..004b2d6a --- /dev/null +++ b/src/TestData/DependencyTests/BundleJ/BundleJ.wixproj @@ -0,0 +1,21 @@ + + + + Bundle + {37BDF884-C24A-4C12-9D0C-421FC30747F2} + 1.0.0.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleJ/BundleJ.wxs b/src/TestData/DependencyTests/BundleJ/BundleJ.wxs new file mode 100644 index 00000000..422b4b22 --- /dev/null +++ b/src/TestData/DependencyTests/BundleJ/BundleJ.wxs @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wixproj b/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wixproj new file mode 100644 index 00000000..b7dbd86a --- /dev/null +++ b/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wixproj @@ -0,0 +1,21 @@ + + + + Bundle + {353B5A34-3B46-424E-8817-25B3D01C8C16} + 1.0.1.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wxs b/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wxs new file mode 100644 index 00000000..ddd4d8db --- /dev/null +++ b/src/TestData/DependencyTests/BundleJ_Patch/BundleJ_Patch.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/BundleL/BundleL.wixproj b/src/TestData/DependencyTests/BundleL/BundleL.wixproj new file mode 100644 index 00000000..f25af7f9 --- /dev/null +++ b/src/TestData/DependencyTests/BundleL/BundleL.wixproj @@ -0,0 +1,20 @@ + + + + Bundle + {2EDB07DC-DCCD-419F-AD25-52ABF36B53AE} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/BundleL/BundleL.wxs b/src/TestData/DependencyTests/BundleL/BundleL.wxs new file mode 100644 index 00000000..d3789e63 --- /dev/null +++ b/src/TestData/DependencyTests/BundleL/BundleL.wxs @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PackageAv1/PackageA.props b/src/TestData/DependencyTests/PackageAv1/PackageA.props new file mode 100644 index 00000000..8cbe9aa9 --- /dev/null +++ b/src/TestData/DependencyTests/PackageAv1/PackageA.props @@ -0,0 +1,12 @@ + + + + PackageA + true + {6F171EC9-0774-4974-A8D1-493EF53CAB74} + {45E933B7-B56A-44D5-8EEC-625EC199085E} + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageAv1/PackageAv1.wixproj b/src/TestData/DependencyTests/PackageAv1/PackageAv1.wixproj new file mode 100644 index 00000000..561f181a --- /dev/null +++ b/src/TestData/DependencyTests/PackageAv1/PackageAv1.wixproj @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageAv1/ProductComponents.wxs b/src/TestData/DependencyTests/PackageAv1/ProductComponents.wxs new file mode 100644 index 00000000..eca7f6b4 --- /dev/null +++ b/src/TestData/DependencyTests/PackageAv1/ProductComponents.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PackageAv1_0_1/PackageAv1_0_1.wixproj b/src/TestData/DependencyTests/PackageAv1_0_1/PackageAv1_0_1.wixproj new file mode 100644 index 00000000..41917a56 --- /dev/null +++ b/src/TestData/DependencyTests/PackageAv1_0_1/PackageAv1_0_1.wixproj @@ -0,0 +1,13 @@ + + + + + 1.0.1.0 + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageAv1_0_2/PackageAv1_0_2.wixproj b/src/TestData/DependencyTests/PackageAv1_0_2/PackageAv1_0_2.wixproj new file mode 100644 index 00000000..8cf6dcd1 --- /dev/null +++ b/src/TestData/DependencyTests/PackageAv1_0_2/PackageAv1_0_2.wixproj @@ -0,0 +1,13 @@ + + + + + 1.0.2.0 + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageB/PackageB.wixproj b/src/TestData/DependencyTests/PackageB/PackageB.wixproj new file mode 100644 index 00000000..2e6b9ffb --- /dev/null +++ b/src/TestData/DependencyTests/PackageB/PackageB.wixproj @@ -0,0 +1,13 @@ + + + + true + {E26243B0-F1A2-4E74-A82D-25B306908E78} + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageB/ProductComponents.wxs b/src/TestData/DependencyTests/PackageB/ProductComponents.wxs new file mode 100644 index 00000000..b59e53e1 --- /dev/null +++ b/src/TestData/DependencyTests/PackageB/ProductComponents.wxs @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PackageC/PackageC.wixproj b/src/TestData/DependencyTests/PackageC/PackageC.wixproj new file mode 100644 index 00000000..0e7fe0ea --- /dev/null +++ b/src/TestData/DependencyTests/PackageC/PackageC.wixproj @@ -0,0 +1,13 @@ + + + + {F21201D4-4782-4658-99C9-2E75D51FCFA6} + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageDv1/Package.wxs b/src/TestData/DependencyTests/PackageDv1/Package.wxs new file mode 100644 index 00000000..348f8ebb --- /dev/null +++ b/src/TestData/DependencyTests/PackageDv1/Package.wxs @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PackageDv1/PackageD.props b/src/TestData/DependencyTests/PackageDv1/PackageD.props new file mode 100644 index 00000000..999de0de --- /dev/null +++ b/src/TestData/DependencyTests/PackageDv1/PackageD.props @@ -0,0 +1,7 @@ + + + + PackageD + {AD82A938-2F54-45B8-A637-B14D8405A959} + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageDv1/PackageDv1.wixproj b/src/TestData/DependencyTests/PackageDv1/PackageDv1.wixproj new file mode 100644 index 00000000..8094c897 --- /dev/null +++ b/src/TestData/DependencyTests/PackageDv1/PackageDv1.wixproj @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageDv2/PackageDv2.wixproj b/src/TestData/DependencyTests/PackageDv2/PackageDv2.wixproj new file mode 100644 index 00000000..e0e27fe5 --- /dev/null +++ b/src/TestData/DependencyTests/PackageDv2/PackageDv2.wixproj @@ -0,0 +1,13 @@ + + + + + 2.0.0.0 + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageEv1/PackageE.props b/src/TestData/DependencyTests/PackageEv1/PackageE.props new file mode 100644 index 00000000..96f07b8c --- /dev/null +++ b/src/TestData/DependencyTests/PackageEv1/PackageE.props @@ -0,0 +1,12 @@ + + + + PackageE + true + {70FA13C7-0338-483F-A256-E5C83750BDE5} + {212A5698-457E-440F-88CC-98FC49A17378} + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageEv1/PackageEv1.wixproj b/src/TestData/DependencyTests/PackageEv1/PackageEv1.wixproj new file mode 100644 index 00000000..7d59cdbe --- /dev/null +++ b/src/TestData/DependencyTests/PackageEv1/PackageEv1.wixproj @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PackageEv1/ProductComponents.wxs b/src/TestData/DependencyTests/PackageEv1/ProductComponents.wxs new file mode 100644 index 00000000..d388d2a3 --- /dev/null +++ b/src/TestData/DependencyTests/PackageEv1/ProductComponents.wxs @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PackageEv1_0_1/PackageEv1_0_1.wixproj b/src/TestData/DependencyTests/PackageEv1_0_1/PackageEv1_0_1.wixproj new file mode 100644 index 00000000..4d2ef922 --- /dev/null +++ b/src/TestData/DependencyTests/PackageEv1_0_1/PackageEv1_0_1.wixproj @@ -0,0 +1,13 @@ + + + + + 1.0.1.0 + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PatchA/PatchA.wixproj b/src/TestData/DependencyTests/PatchA/PatchA.wixproj new file mode 100644 index 00000000..1c90b6f4 --- /dev/null +++ b/src/TestData/DependencyTests/PatchA/PatchA.wixproj @@ -0,0 +1,15 @@ + + + + PatchCreation + .msp + 1079 + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PatchA/PatchA.wxs b/src/TestData/DependencyTests/PatchA/PatchA.wxs new file mode 100644 index 00000000..acb6f887 --- /dev/null +++ b/src/TestData/DependencyTests/PatchA/PatchA.wxs @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/TestData/DependencyTests/PatchB/PatchB.wixproj b/src/TestData/DependencyTests/PatchB/PatchB.wixproj new file mode 100644 index 00000000..5efc2350 --- /dev/null +++ b/src/TestData/DependencyTests/PatchB/PatchB.wixproj @@ -0,0 +1,15 @@ + + + + PatchCreation + .msp + 1079 + + + + + + + + + \ No newline at end of file diff --git a/src/TestData/DependencyTests/PatchB/PatchB.wxs b/src/TestData/DependencyTests/PatchB/PatchB.wxs new file mode 100644 index 00000000..a906dbc8 --- /dev/null +++ b/src/TestData/DependencyTests/PatchB/PatchB.wxs @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/src/TestData/Templates/PackageFail.wxs b/src/TestData/Templates/PackageFail.wxs index 73858fde..54921ec6 100644 --- a/src/TestData/Templates/PackageFail.wxs +++ b/src/TestData/Templates/PackageFail.wxs @@ -19,7 +19,7 @@ - + diff --git a/src/TestData/TestBA/TestBAWixlib/TestExe.wxs b/src/TestData/TestBA/TestBAWixlib/TestExe.wxs new file mode 100644 index 00000000..f27275b0 --- /dev/null +++ b/src/TestData/TestBA/TestBAWixlib/TestExe.wxs @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/TestData/TestBA/TestBAWixlib/testbawixlib.wixproj b/src/TestData/TestBA/TestBAWixlib/testbawixlib.wixproj index 83d947cd..33b1379e 100644 --- a/src/TestData/TestBA/TestBAWixlib/testbawixlib.wixproj +++ b/src/TestData/TestBA/TestBAWixlib/testbawixlib.wixproj @@ -11,6 +11,7 @@ + diff --git a/src/TestData/TestData.proj b/src/TestData/TestData.proj index e8e61a94..c5682fc7 100644 --- a/src/TestData/TestData.proj +++ b/src/TestData/TestData.proj @@ -5,6 +5,14 @@ + + + + + + + + diff --git a/src/TestExe/Program.cs b/src/TestExe/Program.cs new file mode 100644 index 00000000..e92c413b --- /dev/null +++ b/src/TestExe/Program.cs @@ -0,0 +1,74 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TestExe +{ + class Program + { + static List tasks; + static int exitCodeToReturn = 0; + + static int Main(string[] args) + { + Usage(); + tasks = TaskParser.ParseTasks(args); + + foreach (Task t in tasks) + { + // special case for the ExitCodeTask + if (t.GetType() == typeof(ExitCodeTask)) + { + exitCodeToReturn = int.Parse(t.data); + } + else + { + t.RunTask(); + } + } + + Console.WriteLine("Exiting with ExitCode = {0}", exitCodeToReturn); + return exitCodeToReturn; + } + + static void Usage() + { + Console.WriteLine(@"TestExe.exe"); + Console.WriteLine(@""); + Console.WriteLine(@"TestExe can be passed various switches to define how it will behave and what tasks it will perform."); + Console.WriteLine(@"All switches are optional."); + Console.WriteLine(@"Any # of switches can be combined in any order."); + Console.WriteLine(@"Switches can be specified multiple times."); + Console.WriteLine(@"The order of the switches listed is the order they will be processed."); + Console.WriteLine(@"Info is written to stdout to describe what tasks are being performed as they are executed."); + Console.WriteLine(@""); + Console.WriteLine(@"Usage: TestExe.exe [tasks...]"); + Console.WriteLine(@""); + Console.WriteLine(@""); + Console.WriteLine(@"/ec # Exit code to return. Can only be specified once. If not specified, 0 will be returned. Example: “/ec 3010” would return 3010"); + Console.WriteLine(@"/s # Milliseconds to sleep before continuing. Example: “/s 5000” would sleep 5 seconds."); + Console.WriteLine(@"/sr #-# Random range of Milliseconds to sleep before continuing. Example: “/sr 5000-10000” would sleep between 5-10 seconds."); + Console.WriteLine(@"/log filename Create a log file called filename. Contents of the log are static text. Example: “/log %temp%\test.log” would create a %temp%\test.log file."); + Console.WriteLine(@"/Pinfo filename Create an xml file containing information about the process: PID, start time, user running the process, etc."); + Console.WriteLine(@"/fe filename Wait for a file to exist before continuing. Example: “/fe %temp%\cache\file.msi” would wait until %temp%\cache\file.msi exists."); + Console.WriteLine(@"/regw regkey,name,type,value (Re)writes a registry key with the specified value"); + Console.WriteLine(@"/regd regkey,[name] Deletes registry key name or key and all of its children (subkeys and values)"); + Console.WriteLine(@""); + Console.WriteLine(@"Example: "); + Console.WriteLine(@""); + Console.WriteLine(@"TestExe.exe /ec 1603 /Pinfo %temp%\Pinfo1.xml /s 1000 /log %temp%\log1.log /sr 5000-10000 /log %temp%\log2.log"); + Console.WriteLine(@""); + Console.WriteLine(@"This would result in the following execution:"); + Console.WriteLine(@" - Create an xml file with the current process info in it."); + Console.WriteLine(@" - Sleep 1 seconds"); + Console.WriteLine(@" - Create log1.log"); + Console.WriteLine(@" - Sleep between 5-10 seconds"); + Console.WriteLine(@" - Create log2.log"); + Console.WriteLine(@" - Exit with 1603"); + Console.WriteLine(@""); + } + } +} diff --git a/src/TestExe/Task.cs b/src/TestExe/Task.cs new file mode 100644 index 00000000..577acbea --- /dev/null +++ b/src/TestExe/Task.cs @@ -0,0 +1,471 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using Microsoft.Win32; + +namespace TestExe +{ + public abstract class Task + { + public string data; + + public Task(string Data) + { + data = Data; + } + + public abstract void RunTask(); + + } + + public class ExitCodeTask : Task + { + public ExitCodeTask(string Data) : base(Data) { } + + public override void RunTask() + { + // this task does nothing. Just stores data about what exit code to return. + } + } + + public class SleepTask : Task + { + public SleepTask(string Data) : base(Data) { } + + public override void RunTask() + { + int milliseconds = int.Parse(this.data); + Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds); + System.Threading.Thread.Sleep(milliseconds); + } + } + + public class SleepRandomTask : Task + { + public SleepRandomTask(string Data) : base(Data) { } + + public override void RunTask() + { + int low = int.Parse(data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[0]); + int high = int.Parse(data.Split(new string[] { ":" }, 2, StringSplitOptions.None)[1]); + + Random r = new Random(); + int milliseconds = r.Next(high - low) + low; + Console.WriteLine("Starting to sleep for {0} milliseconds", milliseconds); + System.Threading.Thread.Sleep(milliseconds); + } + } + + public class LogTask : Task + { + string[] argsUsed; + public LogTask(string Data, string[] args) + : base(Data) + { + argsUsed = args; + } + + public override void RunTask() + { + string logFile = ""; + string argsUsedString = ""; + + foreach (string a in argsUsed) + { + argsUsedString += a + " "; + } + + try + { + logFile = System.Environment.ExpandEnvironmentVariables(data); + Console.WriteLine("creating log file: " + logFile); + StreamWriter textFile = File.CreateText(logFile); + textFile.WriteLine("This is a log file created by TestExe.exe"); + textFile.WriteLine("Args used: " + argsUsedString); + textFile.Close(); + } + catch + { + Console.WriteLine("creating a log file failed for: {0}", logFile); + } + + } + } + + public class ProcessInfoTask : Task + { + public ProcessInfoTask(string Data) : base(Data) { } + + public override void RunTask() + { + try + { + string processInfoXml = ""; + + // Get information about the process and who is running it + Process thisProc = Process.GetCurrentProcess(); + string username = thisProc.StartInfo.EnvironmentVariables["username"].ToString(); + + int parentProcId = GetParentProcess(thisProc.Id); + Process parentProc = Process.GetProcessById(parentProcId); + string parentUsername = parentProc.StartInfo.EnvironmentVariables["username"].ToString(); + + int grandparentProcId = GetParentProcess(parentProc.Id); + Process grandparentProc = Process.GetProcessById(grandparentProcId); + string grandparentUsername = grandparentProc.StartInfo.EnvironmentVariables["username"].ToString(); + + processInfoXml += ""; + processInfoXml += " " + thisProc.ProcessName + ""; + processInfoXml += " " + thisProc.Id.ToString() + ""; + processInfoXml += " " + thisProc.SessionId.ToString() + ""; + processInfoXml += " " + thisProc.MachineName + ""; + // this stuff isn't set since we didn't start the process and tell it what to use. So don't bother + //processInfoXml += " "; + //processInfoXml += " " + thisProc.StartInfo.FileName + ""; + //processInfoXml += " " + thisProc.StartInfo.UserName + ""; + //processInfoXml += " " + thisProc.StartInfo.WorkingDirectory + ""; + //processInfoXml += " " + thisProc.StartInfo.Arguments + ""; + //processInfoXml += " "; + processInfoXml += " " + thisProc.StartTime.ToString() + ""; + processInfoXml += " " + username + ""; + processInfoXml += " "; + processInfoXml += " " + parentProc.ProcessName + ""; + processInfoXml += " " + parentProc.Id.ToString() + ""; + processInfoXml += " " + parentProc.StartTime.ToString() + ""; + processInfoXml += " " + parentUsername + ""; + processInfoXml += " "; + processInfoXml += " "; + processInfoXml += " " + grandparentProc.ProcessName + ""; + processInfoXml += " " + grandparentProc.Id.ToString() + ""; + processInfoXml += " " + grandparentProc.StartTime.ToString() + ""; + processInfoXml += " " + grandparentUsername + ""; + processInfoXml += " "; + processInfoXml += ""; + + string logFile = System.Environment.ExpandEnvironmentVariables(data); + Console.WriteLine("Creating Process Info data file: " + logFile); + StreamWriter textFile = File.CreateText(logFile); + textFile.WriteLine(processInfoXml); + textFile.Close(); + } + catch (Exception eX) + { + Console.WriteLine("Creating Process Info data file failed"); + Console.WriteLine(eX.Message); + } + + + } + + private static int GetParentProcess(int Id) + { + int parentPid = 0; + using (ManagementObject mo = new ManagementObject("win32_process.handle='" + Id.ToString() + "'")) + { + mo.Get(); + parentPid = Convert.ToInt32(mo["ParentProcessId"]); + } + return parentPid; + } + } + + public class FileExistsTask : Task + { + public FileExistsTask(string Data) : base(Data) { } + + public override void RunTask() + { + string fileToExist = System.Environment.ExpandEnvironmentVariables(data); + + if (!String.IsNullOrEmpty(fileToExist)) + { + Console.WriteLine("Waiting for this file to exist: \"" + fileToExist + "\""); + while (!System.IO.File.Exists(fileToExist)) + { + System.Threading.Thread.Sleep(250); + } + Console.WriteLine("Found: \"" + fileToExist + "\""); + } + + } + } + + /// + /// Task class that will create a registry key and write a name and value in it + /// + public class RegistryWriterTask : Task + { + private string hive; + private string keyPath; + private string[] keyPathArray; + private string name; + private RegistryValueKind regValueKind; + private object value; + + public RegistryWriterTask(string Data) : base(Data) { } + + public override void RunTask() + { + if (parseRegKeyNameTypeValue(System.Environment.ExpandEnvironmentVariables(data))) + { + RegistryKey rk = Registry.LocalMachine; + + if (hive == "HKCU") rk = Microsoft.Win32.Registry.CurrentUser; + if (hive == "HKCC") rk = Microsoft.Win32.Registry.CurrentConfig; + if (hive == "HKLM") rk = Microsoft.Win32.Registry.LocalMachine; + + foreach (string key in keyPathArray) + { + rk = rk.CreateSubKey(key, RegistryKeyPermissionCheck.ReadWriteSubTree); + } + + rk.SetValue(name, value, regValueKind); + Console.WriteLine("Created registry key: '{0}' name: '{1}' value: '{2}' of type: '{3}'", + hive + "\\" + keyPath, + name, + value.ToString(), + regValueKind.ToString()); + } + else + { + Console.WriteLine("Unable to write registry key."); + } + + } + + private bool parseRegKeyNameTypeValue(string delimittedData) + { + string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None); + if (splitString.Length != 4) + { + Console.WriteLine("Invalid regkey. Unable to parse key,name,type,value from: \"" + delimittedData + "\""); + return false; + } + else + { + keyPath = splitString[0]; + name = splitString[1]; + string datatype = splitString[2]; + if (datatype == "DWord") + { + value = UInt32.Parse(splitString[3]); + } + else if (datatype == "QWord") + { + value = UInt64.Parse(splitString[3]); + } + else + { + value = splitString[3]; + } + + if (keyPath.ToUpper().StartsWith("HKLM\\")) + { + hive = "HKLM"; + keyPath = keyPath.Replace("HKLM\\", ""); + } + else if (keyPath.ToUpper().StartsWith("HKCC\\")) + { + hive = "HKCC"; + keyPath = keyPath.Replace("HKCC\\", ""); + } + else if (keyPath.ToUpper().StartsWith("HKCU\\")) + { + hive = "HKCU"; + keyPath = keyPath.Replace("HKCU\\", ""); + } + else + { + Console.WriteLine("Invalid regkey. Unable to determin hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]"); + return false; + } + keyPathArray = keyPath.Split(new string[] { "\\" }, StringSplitOptions.None); + + try + { + regValueKind = (RegistryValueKind)System.Enum.Parse(typeof(RegistryValueKind), datatype); + } + catch (Exception ex) + { + Console.WriteLine("Invalid datatype. It must be: String, DWord, or QWord (case sensitive)"); + Console.WriteLine(ex.Message); + return false; + } + } + return true; + } + } + + /// + /// Task class that will delete a registry key value or registry key and all of its children + /// + public class RegistryDeleterTask : Task + { + private string hive; + private string keyPath; + private string[] keyPathArray; + private string name; + + public RegistryDeleterTask(string Data) : base(Data) { } + + public override void RunTask() + { + if (parseRegKeyName(System.Environment.ExpandEnvironmentVariables(data))) + { + try + { + RegistryKey rk = Registry.LocalMachine; + + if (hive == "HKCU") rk = Microsoft.Win32.Registry.CurrentUser; + if (hive == "HKCC") rk = Microsoft.Win32.Registry.CurrentConfig; + if (hive == "HKLM") rk = Microsoft.Win32.Registry.LocalMachine; + + RegistryKey rkParent = null; + foreach (string key in keyPathArray) + { + rkParent = rk; + rk = rk.OpenSubKey(key, true); + } + + if (String.IsNullOrEmpty(name)) + { + // delete the key and all of its children + string subkeyToDelete = keyPathArray[keyPathArray.Length - 1]; + rkParent.DeleteSubKeyTree(subkeyToDelete); + Console.WriteLine("Deleted registry key: '{0}'", hive + "\\" + keyPath); + } + else + { + // just delete this value + rk.DeleteValue(name); + Console.WriteLine("Deleted registry key: '{0}' name: '{1}'", hive + "\\" + keyPath, name); + } + } + catch (Exception ex) + { + Console.WriteLine("Unable to delete registry key: '{0}'", hive + "\\" + keyPath); + Console.WriteLine(ex.Message); + } + } + else + { + Console.WriteLine("Unable to delete registry key."); + } + + } + + private bool parseRegKeyName(string delimittedData) + { + string[] splitString = delimittedData.Split(new string[] { "," }, StringSplitOptions.None); + + if (splitString.Length > 2) + { + Console.WriteLine("Unable to parse registry key and name."); + return false; + } + + keyPath = splitString[0]; + if (splitString.Length == 2) + { + name = splitString[1]; + } + + if (keyPath.ToUpper().StartsWith("HKLM\\")) + { + hive = "HKLM"; + keyPath = keyPath.Replace("HKLM\\", ""); + } + else if (keyPath.ToUpper().StartsWith("HKCC\\")) + { + hive = "HKCC"; + keyPath = keyPath.Replace("HKCC\\", ""); + } + else if (keyPath.ToUpper().StartsWith("HKCU\\")) + { + hive = "HKCU"; + keyPath = keyPath.Replace("HKCU\\", ""); + } + else + { + Console.WriteLine("Invalid regkey. Unable to determine hive. regkey must start with either: [HKLM], [HKCU], or [HKCC]"); + return false; + } + keyPathArray = keyPath.Split(new string[] { "\\" }, StringSplitOptions.None); + return true; + } + } + + public class TaskParser + { + + public static List ParseTasks(string[] args) + { + List tasks = new List(); + + try + { + // for invalid args. return empty list + if (args.Length % 2 == 0) + { + Task t; + + for (int i = 0; i < args.Length; i += 2) + { + switch (args[i].ToLower()) + { + case "/ec": + t = new ExitCodeTask(args[i + 1]); + tasks.Add(t); + break; + case "/s": + t = new SleepTask(args[i + 1]); + tasks.Add(t); + break; + case "/sr": + t = new SleepRandomTask(args[i + 1]); + tasks.Add(t); + break; + case "/log": + t = new LogTask(args[i + 1], args); + tasks.Add(t); + break; + case "/pinfo": + t = new ProcessInfoTask(args[i + 1]); + tasks.Add(t); + break; + case "/fe": + t = new FileExistsTask(args[i + 1]); + tasks.Add(t); + break; + case "/regw": + t = new RegistryWriterTask(args[i + 1]); + tasks.Add(t); + break; + case "/regd": + t = new RegistryDeleterTask(args[i + 1]); + tasks.Add(t); + break; + + default: + Console.WriteLine("Error: Invalid switch specified."); + return new List(); + } + } + } + } + catch + { + Console.WriteLine("Error: Invalid switch data specified. Couldn't parse the data."); + return new List(); + } + + return tasks; + } + } +} diff --git a/src/TestExe/TestExe.csproj b/src/TestExe/TestExe.csproj new file mode 100644 index 00000000..933fa932 --- /dev/null +++ b/src/TestExe/TestExe.csproj @@ -0,0 +1,17 @@ + + + + + + net35 + TestExe + TestExe + Exe + embedded + win-x86 + + + + + + \ No newline at end of file diff --git a/src/TestExe/app.config b/src/TestExe/app.config new file mode 100644 index 00000000..f9811b74 --- /dev/null +++ b/src/TestExe/app.config @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/WixTestTools/BundleInstaller.cs b/src/WixTestTools/BundleInstaller.cs index 044486fe..854c12f0 100644 --- a/src/WixTestTools/BundleInstaller.cs +++ b/src/WixTestTools/BundleInstaller.cs @@ -12,12 +12,15 @@ namespace WixTestTools { this.Bundle = Path.Combine(testContext.TestDataFolder, $"{name}.exe"); this.BundlePdb = Path.Combine(testContext.TestDataFolder, $"{name}.wixpdb"); + this.TestContext = testContext; this.TestGroupName = testContext.TestGroupName; this.TestName = testContext.TestName; } public string Bundle { get; } + private WixTestContext TestContext { get; } + public string TestGroupName { get; } public string TestName { get; } diff --git a/src/WixTestTools/BundleRegistration.cs b/src/WixTestTools/BundleRegistration.cs index d473dcdd..1a066232 100644 --- a/src/WixTestTools/BundleRegistration.cs +++ b/src/WixTestTools/BundleRegistration.cs @@ -7,7 +7,8 @@ namespace WixTestTools public class BundleRegistration { - public const string BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY = "SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; + 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_DETECT_CODE = "BundleDetectCode"; @@ -89,13 +90,22 @@ namespace WixTestTools public static bool TryGetPerMachineBundleRegistrationById(string bundleId, out BundleRegistration registration) { - var registrationKeyPath = $"{BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY}\\{bundleId}"; + var registrationKeyPath = $"{BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY_WOW6432NODE}\\{bundleId}"; using var registrationKey = Registry.LocalMachine.OpenSubKey(registrationKeyPath); var success = registrationKey != null; registration = success ? GetBundleRegistration(registrationKey) : null; return success; } + public static bool TryGetPerUserBundleRegistrationById(string bundleId, 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; + } + private static BundleRegistration GetBundleRegistration(RegistryKey idKey) { var registration = new BundleRegistration(); diff --git a/src/WixTestTools/BundleVerifier.cs b/src/WixTestTools/BundleVerifier.cs index 96c86fdf..433b6a0a 100644 --- a/src/WixTestTools/BundleVerifier.cs +++ b/src/WixTestTools/BundleVerifier.cs @@ -33,31 +33,46 @@ namespace WixTestTools return this.BundleSymbol; } - public string GetPackageCachePathForCacheId(string cacheId) + public string GetPackageCachePathForCacheId(string cacheId, bool perMachine) { - using var policyKey = Registry.LocalMachine.OpenSubKey(FULL_BURN_POLICY_REGISTRY_PATH); - var redirectedCachePath = policyKey?.GetValue("PackageCache") as string; - var cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME); + string cachePath; + if (perMachine) + { + using var policyKey = Registry.LocalMachine.OpenSubKey(FULL_BURN_POLICY_REGISTRY_PATH); + var redirectedCachePath = policyKey?.GetValue("PackageCache") as string; + cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME); + } + else + { + cachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), PACKAGE_CACHE_FOLDER_NAME); + } return Path.Combine(cachePath, cacheId); } public string GetExpectedCachedBundlePath() { var bundleSymbol = this.GetBundleSymbol(); - var cachePath = this.GetPackageCachePathForCacheId(bundleSymbol.BundleId); + var cachePath = this.GetPackageCachePathForCacheId(bundleSymbol.BundleId, bundleSymbol.PerMachine); return Path.Combine(cachePath, Path.GetFileName(this.Bundle)); } - public bool TryGetPerMachineRegistration(out BundleRegistration registration) + public bool TryGetRegistration(out BundleRegistration registration) { var bundleSymbol = this.GetBundleSymbol(); var bundleId = bundleSymbol.BundleId; - return BundleRegistration.TryGetPerMachineBundleRegistrationById(bundleId, out registration); + if (bundleSymbol.PerMachine) + { + return BundleRegistration.TryGetPerMachineBundleRegistrationById(bundleId, out registration); + } + else + { + return BundleRegistration.TryGetPerUserBundleRegistrationById(bundleId, out registration); + } } public string VerifyRegisteredAndInPackageCache() { - Assert.True(this.TryGetPerMachineRegistration(out var registration)); + Assert.True(this.TryGetRegistration(out var registration)); Assert.NotNull(registration.CachePath); Assert.True(File.Exists(registration.CachePath)); @@ -76,7 +91,7 @@ namespace WixTestTools public void VerifyUnregisteredAndRemovedFromPackageCache(string cachedBundlePath) { - Assert.False(this.TryGetPerMachineRegistration(out _)); + Assert.False(this.TryGetRegistration(out _)); Assert.False(File.Exists(cachedBundlePath)); } @@ -86,11 +101,41 @@ namespace WixTestTools var intermediate = Intermediate.Load(wixOutput); var section = intermediate.Sections.Single(); var packageSymbol = section.Symbols.OfType().Single(p => p.Id.Id == packageId); - var cachePath = this.GetPackageCachePathForCacheId(packageSymbol.CacheId); + var cachePath = this.GetPackageCachePathForCacheId(packageSymbol.CacheId, packageSymbol.PerMachine == YesNoDefaultType.Yes); if (Directory.Exists(cachePath)) { Directory.Delete(cachePath, true); } } + + public void VerifyPackageIsCached(string packageId) + { + using var wixOutput = WixOutput.Read(this.BundlePdb); + var intermediate = Intermediate.Load(wixOutput); + var section = intermediate.Sections.Single(); + var packageSymbol = section.Symbols.OfType().Single(p => p.Id.Id == packageId); + var cachePath = this.GetPackageCachePathForCacheId(packageSymbol.CacheId, packageSymbol.PerMachine == YesNoDefaultType.Yes); + Assert.True(Directory.Exists(cachePath)); + } + + public void VerifyExeTestRegistryRootDeleted(string name) + { + using var testRegistryRoot = this.TestContext.GetTestRegistryRoot(name); + if (testRegistryRoot != null) + { + var actualValue = testRegistryRoot.GetValue("Version") as string; + Assert.Null(actualValue); + } + } + + public void VerifyExeTestRegistryValue(string name, string expectedValue) + { + using (var root = this.TestContext.GetTestRegistryRoot(name)) + { + Assert.NotNull(root); + var actualValue = root.GetValue("Version") as string; + Assert.Equal(expectedValue, actualValue); + } + } } } diff --git a/src/WixTestTools/MsiUtilities.cs b/src/WixTestTools/MsiUtilities.cs index 2a848938..4c7d1601 100644 --- a/src/WixTestTools/MsiUtilities.cs +++ b/src/WixTestTools/MsiUtilities.cs @@ -2,6 +2,7 @@ namespace WixTestTools { + using System; using WixToolset.Dtf.WindowsInstaller; public class MsiUtilities @@ -23,5 +24,24 @@ namespace WixTestTools } return false; } + + /// + /// Return true if it finds the given productcode in system with the specified version otherwise it returns false + /// + /// + /// + /// + public static bool IsProductInstalledWithVersion(string prodCode, Version prodVersion) + { + //look in all user's products (both per-machine and per-user) + foreach (ProductInstallation product in ProductInstallation.GetProducts(null, "s-1-1-0", UserContexts.All)) + { + if (product.ProductCode == prodCode && product.ProductVersion == prodVersion) + { + return true; + } + } + return false; + } } } diff --git a/src/WixTestTools/PackageVerifier.cs b/src/WixTestTools/PackageVerifier.cs index b4289032..073e83b0 100644 --- a/src/WixTestTools/PackageVerifier.cs +++ b/src/WixTestTools/PackageVerifier.cs @@ -58,6 +58,13 @@ namespace WixTestTools Assert.Equal(installed, MsiUtilities.IsProductInstalled(productCode)); } + public void VerifyInstalledWithVersion(bool installed) + { + var productCode = this.GetProperty("ProductCode"); + Version prodVersion = new Version(this.GetProperty("ProductVersion")); + Assert.Equal(installed, MsiUtilities.IsProductInstalledWithVersion(productCode, prodVersion)); + } + public void DeleteTestRegistryValue(string name) { using (var root = this.TestContext.GetTestRegistryRoot()) diff --git a/src/WixTestTools/WixTestTools.csproj b/src/WixTestTools/WixTestTools.csproj index f81c82d1..0c3c4c76 100644 --- a/src/WixTestTools/WixTestTools.csproj +++ b/src/WixTestTools/WixTestTools.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/WixToolsetTest.BurnE2E/DependencyTests.cs b/src/WixToolsetTest.BurnE2E/DependencyTests.cs index a3994cf6..2e27239f 100644 --- a/src/WixToolsetTest.BurnE2E/DependencyTests.cs +++ b/src/WixToolsetTest.BurnE2E/DependencyTests.cs @@ -2,6 +2,9 @@ namespace WixToolsetTest.BurnE2E { + using System; + using WixTestTools; + using WixToolset.Mba.Core; using Xunit; using Xunit.Abstractions; @@ -12,27 +15,594 @@ namespace WixToolsetTest.BurnE2E [Fact] public void CanKeepSameExactPackageAfterUpgradingBundle() { - var packageA = this.CreatePackageInstaller("PackageF"); - var bundleAv1 = this.CreateBundleInstaller("BundleKv1"); - var bundleAv2 = this.CreateBundleInstaller("BundleKv2"); + var packageF = this.CreatePackageInstaller("PackageF"); + var bundleKv1 = this.CreateBundleInstaller("BundleKv1"); + var bundleKv2 = this.CreateBundleInstaller("BundleKv2"); + + packageF.VerifyInstalled(false); + + bundleKv1.Install(); + bundleKv1.VerifyRegisteredAndInPackageCache(); + + packageF.VerifyInstalled(true); + + bundleKv2.Install(); + bundleKv2.VerifyRegisteredAndInPackageCache(); + bundleKv1.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageF.VerifyInstalled(true); + + bundleKv2.VerifyPackageIsCached("PackageF"); + + bundleKv2.Uninstall(); + bundleKv2.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageF.VerifyInstalled(false); + } + + [Fact (Skip = "https://github.com/wixtoolset/issues/issues/6387")] + public void CanKeepSameExactPackageAfterUpgradingBundleWithSlipstreamedPatch() + { + var originalVersion = "1.0.0.0"; + var patchedVersion = "1.0.1.0"; + var testRegistryValue = "PackageA"; + var testRegistryValueExe = "ExeA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var bundleA = this.CreateBundleInstaller("BundleAv1"); + var bundleC = this.CreateBundleInstaller("BundleC"); packageA.VerifyInstalled(false); + bundleA.Install(); + bundleA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, originalVersion); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, originalVersion); + + // Verify https://github.com/wixtoolset/issues/issues/3294 - Uninstalling bundle registers a dependency on a package + bundleC.Install(); + bundleC.VerifyRegisteredAndInPackageCache(); + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, patchedVersion); + bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + + // Verify https://github.com/wixtoolset/issues/issues/2915 - Update bundle removes previously cached MSIs + bundleC.Repair(); + + bundleC.Uninstall(); + bundleC.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + } + + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/exea")] + public void CanKeepUpgradedPackageAfterUninstallUpgradedBundle() + { + var testRegistryValueExe = "ExeA"; + + var packageAv1 = this.CreatePackageInstaller("PackageAv1"); + var packageAv101 = this.CreatePackageInstaller("PackageAv1_0_1"); + var packageB = this.CreatePackageInstaller("PackageB"); + var bundleAv1 = this.CreateBundleInstaller("BundleAv1"); + var bundleAv101 = this.CreateBundleInstaller("BundleAv1_0_1"); + var bundleB = this.CreateBundleInstaller("BundleB"); + + packageAv1.VerifyInstalledWithVersion(false); + packageAv101.VerifyInstalledWithVersion(false); + packageB.VerifyInstalled(false); + bundleAv1.Install(); bundleAv1.VerifyRegisteredAndInPackageCache(); - packageA.VerifyInstalled(true); + packageAv1.VerifyInstalledWithVersion(true); + bundleAv1.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + + bundleB.Install(); + bundleB.VerifyRegisteredAndInPackageCache(); - bundleAv2.Install(); - bundleAv2.VerifyRegisteredAndInPackageCache(); + packageAv1.VerifyInstalledWithVersion(true); + bundleAv1.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(true); + + bundleAv101.Install(); + bundleAv101.VerifyRegisteredAndInPackageCache(); bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache(); + packageAv1.VerifyInstalledWithVersion(false); + packageAv101.VerifyInstalledWithVersion(true); + bundleAv1.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.1.0"); + + bundleAv101.Uninstall(); + bundleAv101.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageAv101.VerifyInstalledWithVersion(true); + bundleAv1.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.1.0"); + } + +#if SUPPORT_ADDON_AND_PATCH_RELATED_BUNDLES + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6387")] +#else + [Fact(Skip = "addon/patch related bundle")] +#endif + public void CanMinorUpgradeDependencyPackageFromPatchBundle() + { + var originalVersion = "1.0.0.0"; + var patchedVersion = "1.0.1.0"; + var testRegistryValue = "PackageA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageBv1 = this.CreatePackageInstaller("PackageBv1"); + var packageBv101 = this.CreatePackageInstaller("PackageBv1_0_1"); + var bundleJ = this.CreateBundleInstaller("BundleJ"); + var bundleJ_Patch = this.CreateBundleInstaller("BundleJ_Patch"); + + packageA.VerifyInstalled(false); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(false); + + bundleJ.Install(); + bundleJ.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, originalVersion); + packageBv1.VerifyInstalled(true); + + bundleJ_Patch.Install(); + bundleJ_Patch.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, patchedVersion); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(true); + + bundleJ.Uninstall(); + bundleJ.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleJ_Patch.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(false); + } + +#if SUPPORT_ADDON_AND_PATCH_RELATED_BUNDLES + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6387")] +#else + [Fact(Skip = "addon/patch related bundle")] +#endif + public void CanMinorUpgradeDependencyPackageFromPatchBundleThenUninstallToRestoreBase() + { + var originalVersion = "1.0.0.0"; + var patchedVersion = "1.0.1.0"; + var testRegistryValue = "PackageA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageBv1 = this.CreatePackageInstaller("PackageBv1"); + var packageBv101 = this.CreatePackageInstaller("PackageBv1_0_1"); + var bundleJ = this.CreateBundleInstaller("BundleJ"); + var bundleJ_Patch = this.CreateBundleInstaller("BundleJ_Patch"); + + packageA.VerifyInstalled(false); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(false); + + bundleJ.Install(); + bundleJ.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, originalVersion); + packageBv1.VerifyInstalled(true); + + bundleJ_Patch.Install(); + bundleJ_Patch.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, patchedVersion); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(true); + + bundleJ_Patch.Uninstall(); + bundleJ_Patch.VerifyUnregisteredAndRemovedFromPackageCache(); + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, originalVersion); + packageBv1.VerifyInstalled(true); + packageBv101.VerifyInstalled(false); + + bundleJ.Uninstall(); + bundleJ.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageBv1.VerifyInstalled(false); + packageBv101.VerifyInstalled(false); + } + +#if SUPPORT_ADDON_AND_PATCH_RELATED_BUNDLES + [Fact] +#else + [Fact(Skip = "addon/patch related bundle")] +#endif + public void CanUninstallBaseWithAddOnsWhenAllSharePackages() + { + var testRegistryValueExe = "ExeA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageB = this.CreatePackageInstaller("PackageB"); + var bundleF = this.CreateBundleInstaller("BundleF"); + var bundleF_AddOnA = this.CreateBundleInstaller("BundleF_AddOnA"); + var bundleF_AddOnB = this.CreateBundleInstaller("BundleF_AddOnB"); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + + bundleF.Install(); + bundleF.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageB.VerifyInstalled(true); + + bundleF_AddOnA.Install(); + bundleF_AddOnA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleF.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(true); + + bundleF_AddOnB.Install(); + bundleF_AddOnB.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleF.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(true); + + bundleF.Uninstall(); + bundleF.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleF_AddOnA.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleF_AddOnB.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + bundleF.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + packageB.VerifyInstalled(false); + } + + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6388")] + public void CanUninstallDependencyPackagesWithBundlesUninstalledInFifoOrder() + { + var testRegistryValueExe = "ExeA"; - bundleAv2.Uninstall(); - bundleAv2.VerifyUnregisteredAndRemovedFromPackageCache(); + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageB = this.CreatePackageInstaller("PackageB"); + var bundleA = this.CreateBundleInstaller("BundleAv1"); + var bundleB = this.CreateBundleInstaller("BundleB"); packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + + bundleA.Install(); + bundleA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + + bundleB.Install(); + bundleB.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(true); + + bundleA.Uninstall(); + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(true); + + bundleB.Uninstall(); + bundleB.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + packageB.VerifyInstalled(false); + } + + [Fact] + public void CanUninstallDependencyPackagesWithBundlesUninstalledInReverseOrder() + { + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageB = this.CreatePackageInstaller("PackageB"); + var bundleA = this.CreateBundleInstaller("BundleAv1"); + var bundleB = this.CreateBundleInstaller("BundleB"); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + + bundleA.Install(); + bundleA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + + bundleB.Install(); + bundleB.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageB.VerifyInstalled(true); + + bundleB.Uninstall(); + bundleB.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + + bundleA.Uninstall(); + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + } + +#if SUPPORT_ADDON_AND_PATCH_RELATED_BUNDLES + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6387")] +#else + [Fact(Skip = "addon/patch related bundle")] +#endif + public void CanUpgradePatchBundleWithAdditionalPatch() + { + var originalVersion = "1.0.0.0"; + var patchedVersion = "1.0.1.0"; + var patchedVersion2 = "1.0.2.0"; + var testRegistryValue = "PackageA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageB = this.CreatePackageInstaller("PackageBv1"); + var bundleF = this.CreateBundleInstaller("BundleJ"); + var bundleF_PatchAv101 = this.CreateBundleInstaller("BundleF_PatchAv1_0_1"); + var bundleF_PatchAv102 = this.CreateBundleInstaller("BundleF_PatchAv1_0_2"); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + + bundleF.Install(); + bundleF.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, originalVersion); + packageB.VerifyInstalled(true); + + bundleF_PatchAv101.Install(); + bundleF_PatchAv101.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, patchedVersion); + packageB.VerifyInstalled(false); + + bundleF_PatchAv102.Install(); + bundleF_PatchAv102.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageA.VerifyTestRegistryValue(testRegistryValue, patchedVersion2); + packageB.VerifyInstalled(false); + + bundleF.Uninstall(); + bundleF.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleF_PatchAv101.VerifyUnregisteredAndRemovedFromPackageCache(); + bundleF_PatchAv102.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + } + + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6388")] + public void DoesntRegisterDependencyOnPackageNotSelectedForInstall() + { + var testRegistryValueExe = "ExeA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageB = this.CreatePackageInstaller("PackageB"); + var bundleA = this.CreateBundleInstaller("BundleAv1"); + var bundleB = this.CreateBundleInstaller("BundleB"); + var testBAController = this.CreateTestBAController(); + + packageA.VerifyInstalled(false); + packageB.VerifyInstalled(false); + + bundleA.Install(); + bundleA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + + // Verify https://github.com/wixtoolset/issues/issues/3456 - Dependency registered on package though unselected to instal + testBAController.SetPackageRequestedState("PackageA", RequestState.None); + testBAController.SetPackageRequestedState("PackageB", RequestState.None); + + bundleB.Install(); + bundleB.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(false); + + bundleA.Uninstall(); + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + packageB.VerifyInstalled(false); + + bundleB.Uninstall(); + bundleB.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + packageB.VerifyInstalled(false); + } + + [Fact(Skip = "https://github.com/wixtoolset/issues/issues/3516")] + public void DoesntRollbackPackageInstallIfPreexistingDependents() + { + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageC = this.CreatePackageInstaller("PackageC"); + var bundleE = this.CreateBundleInstaller("BundleE"); + var bundleL = this.CreateBundleInstaller("BundleL"); + var testBAController = this.CreateTestBAController(); + + packageA.VerifyInstalled(false); + packageC.VerifyInstalled(false); + + // Make PackageC fail. + testBAController.SetPackageCancelExecuteAtProgress("PackageC", 10); + + bundleE.Install(); + bundleE.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(false); + + // Make PackageC install then rollback. + testBAController.SetPackageCancelExecuteAtProgress("PackageC", null); + testBAController.SetPackageCancelOnProgressAtProgress("PackageC", 10); + + bundleL.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); + bundleL.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(true); + + testBAController.SetPackageCancelOnProgressAtProgress("PackageC", null); + + bundleE.Uninstall(); + bundleE.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageC.VerifyInstalled(false); + } + + [Fact] + public void RegistersDependencyOnFailedNonVitalPackages() + { + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageC = this.CreatePackageInstaller("PackageC"); + var bundleE = this.CreateBundleInstaller("BundleE"); + var bundleL = this.CreateBundleInstaller("BundleL"); + var testBAController = this.CreateTestBAController(); + + packageA.VerifyInstalled(false); + packageC.VerifyInstalled(false); + + // Make PackageC fail. + testBAController.SetPackageCancelExecuteAtProgress("PackageC", 10); + + // Verify https://github.com/wixtoolset/issues/issues/3406 - Non-vital failure result in bundle failure (install) + bundleE.Install(); + bundleE.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(false); + + // Verify https://github.com/wixtoolset/issues/issues/3406 - Non-vital failure result in bundle failure (repair) + bundleE.Repair(); + bundleE.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(false); + + testBAController.SetPackageCancelExecuteAtProgress("PackageC", null); + + bundleL.Install(); + bundleL.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(true); + + // Verify https://github.com/wixtoolset/issues/issues/3516 - Burn registers dependency on failed packages + bundleL.Uninstall(); + bundleL.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + packageC.VerifyInstalled(true); + + bundleE.Uninstall(); + bundleE.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + packageC.VerifyInstalled(false); + } + + [Fact] + public void RemovesDependencyDuringUpgradeRollback() + { + var testRegistryValueExe = "ExeA"; + + var packageA = this.CreatePackageInstaller("PackageAv1"); + var bundleA = this.CreateBundleInstaller("BundleAv1"); + var bundleD = this.CreateBundleInstaller("BundleD"); + + packageA.VerifyInstalled(false); + bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + + bundleA.Install(); + bundleA.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + + // Verify https://github.com/wixtoolset/issues/issues/3341 - pkg dependecy not removed in rollback if pkg already present + bundleD.Install((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE); + bundleD.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + bundleA.VerifyExeTestRegistryValue(testRegistryValueExe, "1.0.0.0"); + + bundleA.Uninstall(); + bundleA.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(false); + bundleA.VerifyExeTestRegistryRootDeleted(testRegistryValueExe); + } + + [Fact] + public void SkipsCrossScopeDependencyRegistration() + { + var packageA = this.CreatePackageInstaller("PackageAv1"); + var packageDv1 = this.CreatePackageInstaller("PackageDv1"); + var packageDv2 = this.CreatePackageInstaller("PackageDv2"); + var bundleHv1 = this.CreateBundleInstaller("BundleHv1"); + var bundleHv2 = this.CreateBundleInstaller("BundleHv2"); + + packageA.VerifyInstalled(false); + packageDv1.VerifyInstalled(false); + packageDv2.VerifyInstalled(false); + + var bundleHv1InstallLogFilePath = bundleHv1.Install(); + bundleHv1.VerifyRegisteredAndInPackageCache(); + + packageA.VerifyInstalled(true); + packageDv1.VerifyInstalled(true); + + Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv1InstallLogFilePath, @"Skipping cross-scope dependency registration on package: PackageA, bundle scope: PerUser, package scope: PerMachine")); + + var bundleHv2InstallLogFilePath = bundleHv2.Install(); + bundleHv2.VerifyRegisteredAndInPackageCache(); + bundleHv1.VerifyUnregisteredAndRemovedFromPackageCache(); + + packageA.VerifyInstalled(true); + packageDv1.VerifyInstalled(false); + packageDv2.VerifyInstalled(true); + + Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv2InstallLogFilePath, @"Skipping cross-scope dependency registration on package: PackageA, bundle scope: PerUser, package scope: PerMachine")); + Assert.True(LogVerifier.MessageInLogFileRegex(bundleHv2InstallLogFilePath, @"Detected related bundle: \{[0-9A-Za-z\-]{36}\}, type: Upgrade, scope: PerUser, version: 1\.0\.0\.0, operation: MajorUpgrade")); + + bundleHv2.Uninstall(); + bundleHv2.VerifyUnregisteredAndRemovedFromPackageCache(); + + // Verify that permanent packageA is still installed and then remove. + packageA.VerifyInstalled(true); + packageDv2.VerifyInstalled(false); + packageA.UninstallProduct(); + packageA.VerifyInstalled(false); } } } diff --git a/src/WixToolsetTest.BurnE2E/WixToolsetTest.BurnE2E.csproj b/src/WixToolsetTest.BurnE2E/WixToolsetTest.BurnE2E.csproj index 820ae24f..f1db82e7 100644 --- a/src/WixToolsetTest.BurnE2E/WixToolsetTest.BurnE2E.csproj +++ b/src/WixToolsetTest.BurnE2E/WixToolsetTest.BurnE2E.csproj @@ -20,7 +20,7 @@ - + -- cgit v1.2.3-55-g6feb