@joebigelow / wix / commits / be8d724f

Testing for #6297.

Sean Hall committed Feb 6, 2021 at 17:31 UTC be8d724f4becb78743644d393ae626b3736dd5b3
12 files changed +193 -35
global.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "msbuild-sdks": {
3 - "WixToolset.Sdk": "4.0.0-build-0186"
3 + "WixToolset.Sdk": "4.0.0-build-0187"
4 },
5 "sdk": {
6 "allowPrerelease": false
src/TestData/PrereqBaTests/BundleA/BundleA.wxs
+1 -1
@@ -16,7 +16,7 @@
16 <Fragment>
17 <PackageGroup Id="BundlePackages">
18 <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" bal:PrereqPackage="yes" Permanent="yes" />
19 - <MsiPackage Id="PackageF" SourceFile="$(var.PackageF.TargetPath)" />
19 + <MsiPackage Id="PackageF" SourceFile="$(var.PackageF.TargetPath)" Cache="always" />
20 </PackageGroup>
21 </Fragment>
22 </Wix>
src/TestData/RegistrationTests/BundleA/BundleA.wixproj new
+18
@@ -0,0 +1,18 @@
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 + <OutputType>Bundle</OutputType>
5 + <UpgradeCode>{17041020-8A61-4A3B-8FDB-4591CB900049}</UpgradeCode>
6 + </PropertyGroup>
7 + <ItemGroup>
8 + <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" />
9 + </ItemGroup>
10 + <ItemGroup>
11 + <ProjectReference Include="..\PackageA\PackageA.wixproj" />
12 + <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" />
13 + </ItemGroup>
14 + <ItemGroup>
15 + <PackageReference Include="WixToolset.Bal.wixext" Version="4.0.82" />
16 + <PackageReference Include="WixToolset.NetFx.wixext" Version="4.0.59" />
17 + </ItemGroup>
18 +</Project>
\ No newline at end of file
src/TestData/RegistrationTests/BundleA/BundleA.wxs new
+10
@@ -0,0 +1,10 @@
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">
5 + <Fragment>
6 + <PackageGroup Id="BundlePackages">
7 + <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" />
8 + </PackageGroup>
9 + </Fragment>
10 +</Wix>
src/TestData/RegistrationTests/PackageA/PackageA.wixproj new
+9
@@ -0,0 +1,9 @@
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>{BF26D3E4-1D6B-480E-B312-3FECE6363E43}</UpgradeCode>
5 + </PropertyGroup>
6 + <ItemGroup>
7 + <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
8 + </ItemGroup>
9 +</Project>
\ No newline at end of file
src/Utilities/TestBA/TestBA.cs
+62 -20
@@ -18,14 +18,17 @@ namespace WixToolset.Test.BA
18 {
19 private const string BurnBundleVersionVariable = "WixBundleVersion";
20
21 - private ApplicationContext appContext;
21 private Form dummyWindow;
22 + private IntPtr windowHandle;
23 private LaunchAction action;
24 + private ManualResetEvent wait;
25 private int result;
26
27 private string updateBundlePath;
28
28 - private int redetectCount;
29 + private bool immediatelyQuit;
30 + private bool quitAfterDetect;
31 + private int redetectRemaining;
32 private int sleepDuringCache;
33 private int cancelCacheAtProgress;
34 private int sleepDuringExecute;
@@ -45,6 +48,7 @@ namespace WixToolset.Test.BA
48 : base(engine)
49 {
50 this.Command = bootstrapperCommand;
51 + this.wait = new ManualResetEvent(false);
52 }
53
54 /// <summary>
@@ -60,8 +64,17 @@ namespace WixToolset.Test.BA
64 /// <summary>
65 /// UI Thread entry point for TestUX.
66 /// </summary>
63 - protected override void Run()
67 + protected override void OnStartup(StartupEventArgs args)
68 {
69 + string immediatelyQuit = this.ReadPackageAction(null, "ImmediatelyQuit");
70 + if (!String.IsNullOrEmpty(immediatelyQuit) && Boolean.TryParse(immediatelyQuit, out this.immediatelyQuit) && this.immediatelyQuit)
71 + {
72 + this.Engine.Quit(0);
73 + return;
74 + }
75 +
76 + base.OnStartup(args);
77 +
78 this.action = this.Command.Action;
79 this.TestVariables();
80
@@ -102,20 +115,46 @@ namespace WixToolset.Test.BA
115 return;
116 }
117
105 - this.dummyWindow = new Form();
106 - this.dummyWindow.CreateControl();
107 - this.appContext = new ApplicationContext();
108 -
109 - this.redetectCount = 0;
118 + int redetectCount;
119 string redetect = this.ReadPackageAction(null, "RedetectCount");
111 - if (String.IsNullOrEmpty(redetect) || !Int32.TryParse(redetect, out this.redetectCount))
120 + if (String.IsNullOrEmpty(redetect) || !Int32.TryParse(redetect, out redetectCount))
121 + {
122 + redetectCount = 0;
123 + }
124 +
125 + string quitAfterDetect = this.ReadPackageAction(null, "QuitAfterDetect");
126 + if (String.IsNullOrEmpty(quitAfterDetect) || !Boolean.TryParse(quitAfterDetect, out this.quitAfterDetect))
127 {
113 - this.redetectCount = 0;
128 + this.quitAfterDetect = false;
129 }
130
116 - this.Engine.Detect();
131 + this.wait.WaitOne();
132 +
133 + this.redetectRemaining = redetectCount;
134 + for (int i = -1; i < redetectCount; i++)
135 + {
136 + this.Engine.Detect(this.windowHandle);
137 + }
138 + }
139 +
140 + protected override void Run()
141 + {
142 + this.dummyWindow = new Form();
143 + this.windowHandle = this.dummyWindow.Handle;
144 +
145 + this.Log("Running TestBA application");
146 + this.wait.Set();
147 + Application.Run();
148 + }
149 +
150 + private void ShutdownUiThread()
151 + {
152 + if (this.dummyWindow != null)
153 + {
154 + this.dummyWindow.Invoke(new Action(Application.ExitThread));
155 + this.dummyWindow.Dispose();
156 + }
157
118 - Application.Run(this.appContext);
158 this.Engine.Quit(this.result & 0xFFFF); // return plain old Win32 error, not HRESULT.
159 }
160
@@ -167,10 +206,13 @@ namespace WixToolset.Test.BA
206 if (Hresult.Succeeded(this.result) &&
207 (this.UpdateAvailable || LaunchAction.UpdateReplaceEmbedded != this.action && LaunchAction.UpdateReplace != this.action))
208 {
170 - if (this.redetectCount > 0)
209 + if (this.redetectRemaining > 0)
210 + {
211 + this.Log("Completed detection phase: {0} re-runs remaining", this.redetectRemaining--);
212 + }
213 + else if (this.quitAfterDetect)
214 {
172 - this.Log("Completed detection phase: {0} re-runs remaining", this.redetectCount--);
173 - this.Engine.Detect();
215 + this.ShutdownUiThread();
216 }
217 else
218 {
@@ -179,7 +221,7 @@ namespace WixToolset.Test.BA
221 }
222 else
223 {
182 - this.appContext.ExitThread();
224 + this.ShutdownUiThread();
225 }
226 }
227
@@ -218,11 +260,11 @@ namespace WixToolset.Test.BA
260 this.result = args.Status;
261 if (Hresult.Succeeded(this.result))
262 {
221 - this.Engine.Apply(this.dummyWindow.Handle);
263 + this.Engine.Apply(this.windowHandle);
264 }
265 else
266 {
225 - this.appContext.ExitThread();
267 + this.ShutdownUiThread();
268 }
269 }
270
@@ -402,7 +444,7 @@ namespace WixToolset.Test.BA
444 this.Log("After elevation: WixBundleElevated = {0}", this.Engine.GetVariableNumeric("WixBundleElevated"));
445
446 this.result = args.Status;
405 - this.appContext.ExitThread();
447 + this.ShutdownUiThread();
448 }
449
450 protected override void OnSystemShutdown(SystemShutdownEventArgs args)
@@ -411,7 +453,7 @@ namespace WixToolset.Test.BA
453 this.Log("Disallowed system request to shut down the bootstrapper application.");
454 args.Cancel = true;
455
414 - this.appContext.ExitThread();
456 + this.ShutdownUiThread();
457 }
458
459 private void TestVariables()
src/WixToolsetTest.BurnE2E/BundleVerifier.cs
+22 -4
@@ -33,14 +33,19 @@ namespace WixToolsetTest.BurnE2E
33 return this.BundleSymbol;
34 }
35
36 - public string GetExpectedCachedBundlePath()
36 + public string GetPackageCachePathForCacheId(string cacheId)
37 {
38 - var bundleSymbol = this.GetBundleSymbol();
39 -
38 using var policyKey = Registry.LocalMachine.OpenSubKey(FULL_BURN_POLICY_REGISTRY_PATH);
39 var redirectedCachePath = policyKey?.GetValue("PackageCache") as string;
40 var cachePath = redirectedCachePath ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), PACKAGE_CACHE_FOLDER_NAME);
43 - return Path.Combine(cachePath, bundleSymbol.BundleId, Path.GetFileName(this.Bundle));
41 + return Path.Combine(cachePath, cacheId);
42 + }
43 +
44 + public string GetExpectedCachedBundlePath()
45 + {
46 + var bundleSymbol = this.GetBundleSymbol();
47 + var cachePath = this.GetPackageCachePathForCacheId(bundleSymbol.BundleId);
48 + return Path.Combine(cachePath, Path.GetFileName(this.Bundle));
49 }
50
51 public bool TryGetPerMachineRegistration(out BundleRegistration registration)
@@ -74,5 +79,18 @@ namespace WixToolsetTest.BurnE2E
79 Assert.False(this.TryGetPerMachineRegistration(out _));
80 Assert.False(File.Exists(cachedBundlePath));
81 }
82 +
83 + public void RemovePackageFromCache(string packageId)
84 + {
85 + using var wixOutput = WixOutput.Read(this.BundlePdb);
86 + var intermediate = Intermediate.Load(wixOutput);
87 + var section = intermediate.Sections.Single();
88 + var packageSymbol = section.Symbols.OfType<WixBundlePackageSymbol>().Single(p => p.Id.Id == packageId);
89 + var cachePath = this.GetPackageCachePathForCacheId(packageSymbol.CacheId);
90 + if (Directory.Exists(cachePath))
91 + {
92 + Directory.Delete(cachePath, true);
93 + }
94 + }
95 }
96 }
src/WixToolsetTest.BurnE2E/BurnE2ETests.cs
+5 -5
@@ -12,32 +12,32 @@ namespace WixToolsetTest.BurnE2E
12 {
13 protected BurnE2ETests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
14
15 - private Queue<IDisposable> Installers { get; } = new Queue<IDisposable>();
15 + private Stack<IDisposable> Installers { get; } = new Stack<IDisposable>();
16
17 protected BundleInstaller CreateBundleInstaller(string name)
18 {
19 var installer = new BundleInstaller(this.TestContext, name);
20 - this.Installers.Enqueue(installer);
20 + this.Installers.Push(installer);
21 return installer;
22 }
23
24 protected PackageInstaller CreatePackageInstaller(string filename)
25 {
26 var installer = new PackageInstaller(this.TestContext, filename);
27 - this.Installers.Enqueue(installer);
27 + this.Installers.Push(installer);
28 return installer;
29 }
30
31 protected TestBAController CreateTestBAController()
32 {
33 var controller = new TestBAController(this.TestContext);
34 - this.Installers.Enqueue(controller);
34 + this.Installers.Push(controller);
35 return controller;
36 }
37
38 public void Dispose()
39 {
40 - while (this.Installers.TryDequeue(out var installer))
40 + while (this.Installers.TryPop(out var installer))
41 {
42 try
43 {
src/WixToolsetTest.BurnE2E/PackageInstaller.cs
+2 -2
@@ -40,7 +40,7 @@ namespace WixToolsetTest.BurnE2E
40 /// <param name="expectedExitCode">Expected exit code</param>
41 /// <param name="otherArguments">Other arguments to pass to MSIExec.</param>
42 /// <returns>MSIExec log File</returns>
43 - public string UninstallProduct(MSIExecReturnCode expectedExitCode, params string[] otherArguments)
43 + public string UninstallProduct(MSIExecReturnCode expectedExitCode = MSIExecReturnCode.SUCCESS, params string[] otherArguments)
44 {
45 return this.RunMSIExec(MSIExecMode.Uninstall, otherArguments, expectedExitCode);
46 }
@@ -51,7 +51,7 @@ namespace WixToolsetTest.BurnE2E
51 /// <param name="expectedExitCode">Expected exit code</param>
52 /// <param name="otherArguments">Other arguments to pass to msiexe.exe.</param>
53 /// <returns>MSIExec log File</returns>
54 - public string RepairProduct(MSIExecReturnCode expectedExitCode, params string[] otherArguments)
54 + public string RepairProduct(MSIExecReturnCode expectedExitCode = MSIExecReturnCode.SUCCESS, params string[] otherArguments)
55 {
56 return this.RunMSIExec(MSIExecMode.Repair, otherArguments, expectedExitCode);
57 }
src/WixToolsetTest.BurnE2E/PrereqBaTests.cs
+2 -2
@@ -18,7 +18,7 @@ namespace WixToolsetTest.BurnE2E
18 /// The preqba doesn't infinitely reload itself after failing to load the managed BA.
19 /// The engine automatically uninstalls the bundle since only permanent packages were installed.
20 /// </summary>
21 - [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6297")]
21 + [Fact]
22 public void DncPreqBaDetectsInfiniteLoop()
23 {
24 var packageA = this.CreatePackageInstaller("PackageA");
@@ -49,7 +49,7 @@ namespace WixToolsetTest.BurnE2E
49 /// The preqba doesn't infinitely reload itself after failing to load the managed BA.
50 /// The engine automatically uninstalls the bundle since only permanent packages were installed.
51 /// </summary>
52 - [Fact(Skip = "https://github.com/wixtoolset/issues/issues/6297")]
52 + [Fact]
53 public void MbaPreqBaDetectsInfiniteLoop()
54 {
55 var packageB = this.CreatePackageInstaller("PackageB");
src/WixToolsetTest.BurnE2E/RegistrationTests.cs new
+51
@@ -0,0 +1,51 @@
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 +namespace WixToolsetTest.BurnE2E
4 +{
5 + using System;
6 + using Xunit;
7 + using Xunit.Abstractions;
8 +
9 + public class RegistrationTests : BurnE2ETests
10 + {
11 + public RegistrationTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
12 +
13 + [Fact]
14 + public void AutomaticallyUninstallsBundleWithoutBADoingApply()
15 + {
16 + this.InstallBundleThenManuallyUninstallPackageAndRemovePackageFromCacheThenRunAndQuitWithoutApply(true);
17 + }
18 +
19 + [Fact]
20 + public void AutomaticallyUninstallsBundleWithoutBADoingDetect()
21 + {
22 + this.InstallBundleThenManuallyUninstallPackageAndRemovePackageFromCacheThenRunAndQuitWithoutApply(false);
23 + }
24 +
25 + private void InstallBundleThenManuallyUninstallPackageAndRemovePackageFromCacheThenRunAndQuitWithoutApply(bool detect)
26 + {
27 + var packageA = this.CreatePackageInstaller("PackageA");
28 + var bundleA = this.CreateBundleInstaller("BundleA");
29 + var testBAController = this.CreateTestBAController();
30 +
31 + bundleA.Install();
32 + bundleA.VerifyRegisteredAndInPackageCache();
33 + packageA.VerifyInstalled(true);
34 +
35 + packageA.UninstallProduct();
36 + bundleA.RemovePackageFromCache("PackageA");
37 +
38 + if (detect)
39 + {
40 + testBAController.SetQuitAfterDetect();
41 + }
42 + else
43 + {
44 + testBAController.SetImmediatelyQuit();
45 + }
46 + bundleA.Install();
47 + packageA.VerifyInstalled(false);
48 + bundleA.VerifyUnregisteredAndRemovedFromPackageCache();
49 + }
50 + }
51 +}
src/WixToolsetTest.BurnE2E/TestBAController.cs
+10
@@ -40,6 +40,16 @@ namespace WixToolsetTest.BurnE2E
40 }
41 }
42
43 + public void SetImmediatelyQuit(string value = "true")
44 + {
45 + this.SetBurnTestValue("ImmediatelyQuit", value);
46 + }
47 +
48 + public void SetQuitAfterDetect(string value = "true")
49 + {
50 + this.SetBurnTestValue("QuitAfterDetect", value);
51 + }
52 +
53 /// <summary>
54 /// Slows the cache progress of a package.
55 /// </summary>