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>