aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/burn/Directory.wixproj.targets1
-rw-r--r--src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wixproj19
-rw-r--r--src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wxs10
-rw-r--r--src/test/burn/TestData/LongPathTests/PackageA/PackageA.wixproj10
-rw-r--r--src/test/burn/TestData/Templates/Bundle.wxs5
-rw-r--r--src/test/burn/TestExe/Task.cs67
-rw-r--r--src/test/burn/WixTestTools/BundleInstaller.cs4
-rw-r--r--src/test/burn/WixTestTools/MSIExec.cs14
-rw-r--r--src/test/burn/WixTestTools/TestTool.cs2
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/LongPathTests.cs298
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/testhost.longpathaware.manifest11
-rw-r--r--src/test/burn/test_burn.cmd5
12 files changed, 439 insertions, 7 deletions
diff --git a/src/test/burn/Directory.wixproj.targets b/src/test/burn/Directory.wixproj.targets
index 17a46e2a..4037e865 100644
--- a/src/test/burn/Directory.wixproj.targets
+++ b/src/test/burn/Directory.wixproj.targets
@@ -7,6 +7,7 @@
7 <WebServerBaseUrl Condition=" '$(WebServerBaseUrl)' == '' ">http://localhost:9999/e2e/</WebServerBaseUrl> 7 <WebServerBaseUrl Condition=" '$(WebServerBaseUrl)' == '' ">http://localhost:9999/e2e/</WebServerBaseUrl>
8 <DefineConstants>TestGroupName=$(TestGroupName);PackageName=$(PackageName);BundleName=$(BundleName);WebServerBaseUrl=$(WebServerBaseUrl);$(DefineConstants)</DefineConstants> 8 <DefineConstants>TestGroupName=$(TestGroupName);PackageName=$(PackageName);BundleName=$(BundleName);WebServerBaseUrl=$(WebServerBaseUrl);$(DefineConstants)</DefineConstants>
9 <DefineConstants Condition=" '$(BA)' != '' ">BA=$(BA);$(DefineConstants)</DefineConstants> 9 <DefineConstants Condition=" '$(BA)' != '' ">BA=$(BA);$(DefineConstants)</DefineConstants>
10 <DefineConstants Condition=" '$(BundleLogDirectory)' != '' ">BundleLogDirectory=$(BundleLogDirectory);$(DefineConstants)</DefineConstants>
10 <DefineConstants Condition=" '$(CabPrefix)' != '' ">CabPrefix=$(CabPrefix);$(DefineConstants)</DefineConstants> 11 <DefineConstants Condition=" '$(CabPrefix)' != '' ">CabPrefix=$(CabPrefix);$(DefineConstants)</DefineConstants>
11 <DefineConstants Condition=" '$(IncludeSoftwareTag)' == 'true' ">SoftwareTag=1;$(DefineConstants)</DefineConstants> 12 <DefineConstants Condition=" '$(IncludeSoftwareTag)' == 'true' ">SoftwareTag=1;$(DefineConstants)</DefineConstants>
12 <DefineConstants Condition=" '$(ProductCode)' != '' ">ProductCode=$(ProductCode);$(DefineConstants)</DefineConstants> 13 <DefineConstants Condition=" '$(ProductCode)' != '' ">ProductCode=$(ProductCode);$(DefineConstants)</DefineConstants>
diff --git a/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wixproj b/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wixproj
new file mode 100644
index 00000000..3686200c
--- /dev/null
+++ b/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wixproj
@@ -0,0 +1,19 @@
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>{EFCF768F-1B06-4B68-9DE0-9244F8212D31}</UpgradeCode>
6 <BundleLogDirectory>[LocalAppDataFolder]Temp</BundleLogDirectory>
7 </PropertyGroup>
8 <ItemGroup>
9 <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" />
10 </ItemGroup>
11 <ItemGroup>
12 <ProjectReference Include="..\PackageA\PackageA.wixproj" />
13 <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" />
14 </ItemGroup>
15 <ItemGroup>
16 <PackageReference Include="WixToolset.Bal.wixext" />
17 <PackageReference Include="WixToolset.NetFx.wixext" />
18 </ItemGroup>
19</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wxs b/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wxs
new file mode 100644
index 00000000..e3872eb1
--- /dev/null
+++ b/src/test/burn/TestData/LongPathTests/NonCompressedBundle/NonCompressedBundle.wxs
@@ -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 Compressed="no" Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" />
8 </PackageGroup>
9 </Fragment>
10</Wix>
diff --git a/src/test/burn/TestData/LongPathTests/PackageA/PackageA.wixproj b/src/test/burn/TestData/LongPathTests/PackageA/PackageA.wixproj
new file mode 100644
index 00000000..798452e7
--- /dev/null
+++ b/src/test/burn/TestData/LongPathTests/PackageA/PackageA.wixproj
@@ -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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <CabPrefix>a</CabPrefix>
5 <UpgradeCode>{4DC05A2A-382D-4E7D-B6DA-163908396373}</UpgradeCode>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9 </ItemGroup>
10</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/Templates/Bundle.wxs b/src/test/burn/TestData/Templates/Bundle.wxs
index b211d9c3..612e67f5 100644
--- a/src/test/burn/TestData/Templates/Bundle.wxs
+++ b/src/test/burn/TestData/Templates/Bundle.wxs
@@ -3,10 +3,13 @@
3<?ifndef Version?> 3<?ifndef Version?>
4<?define Version = 1.0.0.0?> 4<?define Version = 1.0.0.0?>
5<?endif?> 5<?endif?>
6<?ifndef BundleLogDirectory?>
7<?define BundleLogDirectory = .?>
8<?endif?>
6 9
7<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal"> 10<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
8 <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="yes"> 11 <Bundle Name="~$(var.TestGroupName) - $(var.BundleName)" Version="$(var.Version)" UpgradeCode="$(var.UpgradeCode)" Compressed="yes">
9 <Log Prefix="~$(var.TestGroupName)_$(var.BundleName)" /> 12 <Log Prefix="$(var.BundleLogDirectory)\~$(var.TestGroupName)_$(var.BundleName)" />
10 13
11 <Variable Name="TestGroupName" Value="$(var.TestGroupName)" /> 14 <Variable Name="TestGroupName" Value="$(var.TestGroupName)" />
12 15
diff --git a/src/test/burn/TestExe/Task.cs b/src/test/burn/TestExe/Task.cs
index 59f774fb..0d283c6c 100644
--- a/src/test/burn/TestExe/Task.cs
+++ b/src/test/burn/TestExe/Task.cs
@@ -2,8 +2,10 @@
2 2
3using System; 3using System;
4using System.Collections.Generic; 4using System.Collections.Generic;
5using System.ComponentModel;
5using System.Diagnostics; 6using System.Diagnostics;
6using System.IO; 7using System.IO;
8using System.Runtime.InteropServices;
7using Microsoft.Win32; 9using Microsoft.Win32;
8 10
9namespace TestExe 11namespace TestExe
@@ -151,6 +153,67 @@ namespace TestExe
151 } 153 }
152 } 154 }
153 155
156 public class DeleteManifestsTask : Task
157 {
158 public DeleteManifestsTask(string Data) : base(Data) { }
159
160 public override void RunTask()
161 {
162 string filePath = System.Environment.ExpandEnvironmentVariables(this.data);
163 IntPtr type = new IntPtr(24); //RT_MANIFEST
164 IntPtr name = new IntPtr(1); //CREATEPROCESS_MANIFEST_RESOURCE_ID
165 DeleteResource(filePath, type, name, 1033);
166 }
167
168 private static void DeleteResource(string filePath, IntPtr type, IntPtr name, ushort language, bool throwOnError = false)
169 {
170 bool discard = true;
171 IntPtr handle = BeginUpdateResourceW(filePath, false);
172 try
173 {
174 if (handle == IntPtr.Zero)
175 {
176 throw new Win32Exception();
177 }
178
179 if (!UpdateResourceW(handle, type, name, language, IntPtr.Zero, 0))
180 {
181 throw new Win32Exception();
182 }
183
184 discard = false;
185 }
186 catch
187 {
188 if (throwOnError)
189 {
190 throw;
191 }
192 }
193 finally
194 {
195 if (handle != IntPtr.Zero)
196 {
197 if (!EndUpdateResourceW(handle, discard) && throwOnError)
198 {
199 throw new Win32Exception();
200 }
201 }
202 }
203 }
204
205 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
206 private extern static IntPtr BeginUpdateResourceW(string fileName, [MarshalAs(UnmanagedType.Bool)] bool deleteExistingResources);
207
208 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
209 [return: MarshalAs(UnmanagedType.Bool)]
210 private extern static bool UpdateResourceW(IntPtr hUpdate, IntPtr type, IntPtr name, ushort language, IntPtr pData, uint cb);
211
212 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
213 [return: MarshalAs(UnmanagedType.Bool)]
214 private extern static bool EndUpdateResourceW(IntPtr hUpdate, [MarshalAs(UnmanagedType.Bool)] bool discard);
215 }
216
154 public class TaskParser 217 public class TaskParser
155 { 218 {
156 219
@@ -197,6 +260,10 @@ namespace TestExe
197 t = new FileExistsTask(args[i + 1]); 260 t = new FileExistsTask(args[i + 1]);
198 tasks.Add(t); 261 tasks.Add(t);
199 break; 262 break;
263 case "/dm":
264 t = new DeleteManifestsTask(args[i + 1]);
265 tasks.Add(t);
266 break;
200#if NET35 267#if NET35
201 case "/pinfo": 268 case "/pinfo":
202 t = new ProcessInfoTask(args[i + 1]); 269 t = new ProcessInfoTask(args[i + 1]);
diff --git a/src/test/burn/WixTestTools/BundleInstaller.cs b/src/test/burn/WixTestTools/BundleInstaller.cs
index 5551d3c0..0f2cfa8f 100644
--- a/src/test/burn/WixTestTools/BundleInstaller.cs
+++ b/src/test/burn/WixTestTools/BundleInstaller.cs
@@ -28,6 +28,8 @@ namespace WixTestTools
28 28
29 public int? AlternateExitCode { get; set; } 29 public int? AlternateExitCode { get; set; }
30 30
31 public string LogDirectory { get; set; }
32
31 public int? LastExitCode { get; set; } 33 public int? LastExitCode { get; set; }
32 34
33 /// <summary> 35 /// <summary>
@@ -194,7 +196,7 @@ namespace WixTestTools
194 sb.Append(" -quiet"); 196 sb.Append(" -quiet");
195 197
196 // Generate the log file name. 198 // Generate the log file name.
197 string logFile = Path.Combine(Path.GetTempPath(), String.Format("{0}_{1}_{2:yyyyMMddhhmmss}_{4}_{3}.log", this.TestGroupName, this.TestName, DateTime.UtcNow, Path.GetFileNameWithoutExtension(this.Bundle), mode)); 199 string logFile = Path.Combine(this.LogDirectory ?? Path.GetTempPath(), String.Format("{0}_{1}_{2:yyyyMMddhhmmss}_{4}_{3}.log", this.TestGroupName, this.TestName, DateTime.UtcNow, Path.GetFileNameWithoutExtension(this.Bundle), mode));
198 sb.AppendFormat(" -log \"{0}\"", logFile); 200 sb.AppendFormat(" -log \"{0}\"", logFile);
199 201
200 // Set operation. 202 // Set operation.
diff --git a/src/test/burn/WixTestTools/MSIExec.cs b/src/test/burn/WixTestTools/MSIExec.cs
index a10a48d6..5f57da7b 100644
--- a/src/test/burn/WixTestTools/MSIExec.cs
+++ b/src/test/burn/WixTestTools/MSIExec.cs
@@ -110,7 +110,7 @@ namespace WixTestTools
110 this.NoRestart = true; 110 this.NoRestart = true;
111 this.ForceRestart = false; 111 this.ForceRestart = false;
112 this.PromptRestart = false; 112 this.PromptRestart = false;
113 this.LogFile = string.Empty; 113 this.LogFile = String.Empty;
114 this.LoggingOptions = MSIExecLoggingOptions.VOICEWARMUP; 114 this.LoggingOptions = MSIExecLoggingOptions.VOICEWARMUP;
115 this.OtherArguments = String.Empty; 115 this.OtherArguments = String.Empty;
116 } 116 }
@@ -230,14 +230,14 @@ namespace WixTestTools
230 } 230 }
231 231
232 // logfile and logging options 232 // logfile and logging options
233 if (0 != loggingOptionsString.Length || !string.IsNullOrEmpty(this.LogFile)) 233 if (0 != loggingOptionsString.Length || !String.IsNullOrEmpty(this.LogFile))
234 { 234 {
235 arguments.Append(" /l"); 235 arguments.Append(" /l");
236 if (0 != loggingOptionsString.Length) 236 if (0 != loggingOptionsString.Length)
237 { 237 {
238 arguments.AppendFormat("{0} ", loggingOptionsString); 238 arguments.AppendFormat("{0} ", loggingOptionsString);
239 } 239 }
240 if (!string.IsNullOrEmpty(this.LogFile)) 240 if (!String.IsNullOrEmpty(this.LogFile))
241 { 241 {
242 arguments.AppendFormat(" \"{0}\" ", this.LogFile); 242 arguments.AppendFormat(" \"{0}\" ", this.LogFile);
243 } 243 }
@@ -268,7 +268,7 @@ namespace WixTestTools
268 }; 268 };
269 269
270 // product 270 // product
271 if (!string.IsNullOrEmpty(this.Product)) 271 if (!String.IsNullOrEmpty(this.Product))
272 { 272 {
273 arguments.AppendFormat(" \"{0}\" ", this.Product); 273 arguments.AppendFormat(" \"{0}\" ", this.Product);
274 } 274 }
@@ -311,6 +311,12 @@ namespace WixTestTools
311 ERROR_CALL_NOT_IMPLEMENTED = 120, 311 ERROR_CALL_NOT_IMPLEMENTED = 120,
312 312
313 /// <summary> 313 /// <summary>
314 /// ERROR_FILENAME_EXCED_RANGE 206
315 /// The filename or extension is too long.
316 /// </summary>
317 ERROR_FILENAME_EXCED_RANGE = 206,
318
319 /// <summary>
314 /// ERROR_APPHELP_BLOCK 1259 320 /// ERROR_APPHELP_BLOCK 1259
315 /// If Windows Installer determines a product may be incompatible with the current operating system, 321 /// If Windows Installer determines a product may be incompatible with the current operating system,
316 /// it displays a dialog box informing the user and asking whether to try to install anyway. 322 /// it displays a dialog box informing the user and asking whether to try to install anyway.
diff --git a/src/test/burn/WixTestTools/TestTool.cs b/src/test/burn/WixTestTools/TestTool.cs
index eb77c75b..79e7004c 100644
--- a/src/test/burn/WixTestTools/TestTool.cs
+++ b/src/test/burn/WixTestTools/TestTool.cs
@@ -229,7 +229,7 @@ namespace WixTestTools
229 returnValue.AppendLine("Tool run result:"); 229 returnValue.AppendLine("Tool run result:");
230 returnValue.AppendLine("----------------"); 230 returnValue.AppendLine("----------------");
231 returnValue.AppendLine("Command:"); 231 returnValue.AppendLine("Command:");
232 returnValue.AppendLine($"\"{result.StartInfo.FileName}\" {result.StartInfo.Arguments}"); 232 returnValue.AppendLine($"\"{result.FileName}\" {result.Arguments}");
233 returnValue.AppendLine(); 233 returnValue.AppendLine();
234 returnValue.AppendLine("Standard Output:"); 234 returnValue.AppendLine("Standard Output:");
235 foreach (var line in result.StandardOutput ?? new string[0]) 235 foreach (var line in result.StandardOutput ?? new string[0])
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/LongPathTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/LongPathTests.cs
new file mode 100644
index 00000000..ba793d7a
--- /dev/null
+++ b/src/test/burn/WixToolsetTest.BurnE2E/LongPathTests.cs
@@ -0,0 +1,298 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolsetTest.BurnE2E
4{
5 using System;
6 using System.ComponentModel;
7 using System.IO;
8 using System.Runtime.InteropServices;
9 using Microsoft.Win32;
10 using WixBuildTools.TestSupport;
11 using WixTestTools;
12 using WixToolset.Mba.Core;
13 using Xunit;
14 using Xunit.Abstractions;
15
16 public class LongPathTests : BurnE2ETests
17 {
18 public LongPathTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
19
20 [RuntimeFact]
21 public void CanInstallAndUninstallSimpleBundle_x86_wixstdba()
22 {
23 this.CanInstallAndUninstallSimpleBundle("PackageA", "BundleA");
24 }
25
26 [RuntimeFact]
27 public void CanInstallAndUninstallSimpleBundle_x86_testba()
28 {
29 this.CanInstallAndUninstallSimpleBundle("PackageA", "BundleB");
30 }
31
32 [RuntimeFact]
33 public void CanInstallAndUninstallSimpleBundle_x86_dnctestba()
34 {
35 this.CanInstallAndUninstallSimpleBundle("PackageA", "BundleC");
36 }
37
38 [RuntimeFact]
39 public void CanInstallAndUninstallSimpleBundle_x86_wixba()
40 {
41 this.CanInstallAndUninstallSimpleBundle("PackageA", "BundleD");
42 }
43
44 [RuntimeFact]
45 public void CanInstallAndUninstallSimpleBundle_x64_wixstdba()
46 {
47 this.CanInstallAndUninstallSimpleBundle("PackageA_x64", "BundleA_x64");
48 }
49
50 [RuntimeFact]
51 public void CanInstallAndUninstallSimplePerUserBundle_x64_wixstdba()
52 {
53 this.CanInstallAndUninstallSimpleBundle("PackageApu_x64", "BundleApu_x64", "PackagePerUser.wxs", unchecked((int)0xc0000005));
54 }
55
56 [RuntimeFact]
57 public void CanInstallAndUninstallSimpleBundle_x64_testba()
58 {
59 this.CanInstallAndUninstallSimpleBundle("PackageA_x64", "BundleB_x64");
60 }
61
62 [RuntimeFact]
63 public void CanInstallAndUninstallSimpleBundle_x64_dnctestba()
64 {
65 this.CanInstallAndUninstallSimpleBundle("PackageA_x64", "BundleC_x64");
66 }
67
68 [RuntimeFact]
69 public void CanInstallAndUninstallSimpleBundle_x64_dncwixba()
70 {
71 this.CanInstallAndUninstallSimpleBundle("PackageA_x64", "BundleD_x64");
72 }
73
74 private void CanInstallAndUninstallSimpleBundle(string packageName, string bundleName, string fileName = "Package.wxs", int? alternateExitCode = null)
75 {
76 var package = this.CreatePackageInstaller(Path.Combine("..", "BasicFunctionalityTests", packageName));
77
78 var bundle = this.CreateBundleInstaller(Path.Combine("..", "BasicFunctionalityTests", bundleName));
79 bundle.AlternateExitCode = alternateExitCode;
80
81 using var dfs = new DisposableFileSystem();
82 var baseFolder = GetLongPath(dfs.GetFolder());
83
84 var packageSourceCodeInstalled = package.GetInstalledFilePath(fileName);
85
86 // Source file should *not* be installed
87 Assert.False(File.Exists(packageSourceCodeInstalled), $"{packageName} payload should not be there on test start: {packageSourceCodeInstalled}");
88
89 var bundleFileInfo = new FileInfo(bundle.Bundle);
90 var bundleCopiedPath = Path.Combine(baseFolder, bundleFileInfo.Name);
91 bundleFileInfo.CopyTo(bundleCopiedPath);
92
93 bundle.Install(bundleCopiedPath);
94 bundle.VerifyRegisteredAndInPackageCache();
95
96 // Source file should be installed
97 Assert.True(File.Exists(packageSourceCodeInstalled), $"Should have found {packageName} payload installed at: {packageSourceCodeInstalled}");
98
99 if (alternateExitCode == bundle.LastExitCode)
100 {
101 WixAssert.Skip($"Install exited with {bundle.LastExitCode}");
102 }
103
104 bundle.Uninstall(bundleCopiedPath);
105
106 // Source file should *not* be installed
107 Assert.False(File.Exists(packageSourceCodeInstalled), $"{packageName} payload should have been removed by uninstall from: {packageSourceCodeInstalled}");
108
109 bundle.VerifyUnregisteredAndRemovedFromPackageCache();
110
111 if (alternateExitCode == bundle.LastExitCode)
112 {
113 WixAssert.Skip($"Uninstall exited with {bundle.LastExitCode}");
114 }
115 }
116
117 [RuntimeFact]
118 public void CanLayoutNonCompressedBundleToLongPath()
119 {
120 var nonCompressedBundle = this.CreateBundleInstaller("NonCompressedBundle");
121 var testBAController = this.CreateTestBAController();
122
123 testBAController.SetPackageRequestedState("NetFx48Web", RequestState.None);
124
125 using var dfs = new DisposableFileSystem();
126 var layoutDirectory = GetLongPath(dfs.GetFolder());
127
128 nonCompressedBundle.Layout(layoutDirectory);
129 nonCompressedBundle.VerifyUnregisteredAndRemovedFromPackageCache();
130
131 Assert.True(File.Exists(Path.Combine(layoutDirectory, "NonCompressedBundle.exe")));
132 Assert.True(File.Exists(Path.Combine(layoutDirectory, "PackageA.msi")));
133 Assert.True(File.Exists(Path.Combine(layoutDirectory, "1a.cab")));
134 Assert.False(File.Exists(Path.Combine(layoutDirectory, @"redist\ndp48-web.exe")));
135 }
136
137 [RuntimeFact]
138 public void CanInstallNonCompressedBundleWithLongTempPath()
139 {
140 this.InstallNonCompressedBundle(longTemp: true, useOriginalTempForLog: true);
141 }
142
143 [RuntimeFact]
144 public void CannotInstallNonCompressedBundleWithLongPackageCachePath()
145 {
146 var installLogPath = this.InstallNonCompressedBundle((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, longPackageCache: true);
147 Assert.True(LogVerifier.MessageInLogFile(installLogPath, @"Error 0x80070643: Failed to install MSI package"));
148 }
149
150 [RuntimeFact]
151 public void CannotInstallNonCompressedBundleWithLongWorkingPath()
152 {
153 var installLogPath = this.InstallNonCompressedBundle((int)MSIExec.MSIExecReturnCode.ERROR_FILENAME_EXCED_RANGE | unchecked((int)0x80070000), longWorkingPath: true);
154 Assert.True(LogVerifier.MessageInLogFile(installLogPath, @"Error 0x800700ce: Failed to load BA DLL"));
155 }
156
157 public string InstallNonCompressedBundle(int expectedExitCode = 0, bool longTemp = false, bool useOriginalTempForLog = false, bool longWorkingPath = false, bool longPackageCache = false, int? alternateExitCode = null)
158 {
159 var deletePolicyKey = false;
160 string originalEngineWorkingDirectoryValue = null;
161 string originalPackageCacheValue = null;
162 var originalTemp = Environment.GetEnvironmentVariable("TMP");
163 var packageA = this.CreatePackageInstaller("PackageA");
164 var nonCompressedBundle = this.CreateBundleInstaller("NonCompressedBundle");
165 var policyPath = nonCompressedBundle.GetFullBurnPolicyRegistryPath();
166 string installLogPath = null;
167
168 try
169 {
170 using var dfs = new DisposableFileSystem();
171 var originalBaseFolder = dfs.GetFolder();
172 var baseFolder = GetLongPath(originalBaseFolder);
173 var sourceFolder = Path.Combine(baseFolder, "source");
174 var workingFolder = Path.Combine(baseFolder, "working");
175 var tempFolder = Path.Combine(originalBaseFolder, new string('d', 260 - originalBaseFolder.Length - 2));
176 var packageCacheFolder = Path.Combine(baseFolder, "package cache");
177
178 var copyResult = TestDataFolderFileSystem.RobocopyFolder(this.TestContext.TestDataFolder, sourceFolder);
179 Assert.True(copyResult.ExitCode >= 0 && copyResult.ExitCode < 8, $"Exit code: {copyResult.ExitCode}\r\nOutput: {String.Join("\r\n", copyResult.StandardOutput)}\r\nError: {String.Join("\r\n", copyResult.StandardError)}");
180
181 var bundleFileInfo = new FileInfo(nonCompressedBundle.Bundle);
182 var bundleCopiedPath = Path.Combine(sourceFolder, bundleFileInfo.Name);
183
184 var policyKey = Registry.LocalMachine.OpenSubKey(policyPath, writable: true);
185 if (policyKey == null)
186 {
187 policyKey = Registry.LocalMachine.CreateSubKey(policyPath, writable: true);
188 deletePolicyKey = true;
189 }
190
191 using (policyKey)
192 {
193 originalEngineWorkingDirectoryValue = policyKey.GetValue("EngineWorkingDirectory") as string;
194 originalPackageCacheValue = policyKey.GetValue("PackageCache") as string;
195
196 if (longWorkingPath)
197 {
198 policyKey.SetValue("EngineWorkingDirectory", workingFolder);
199 }
200
201 if (longPackageCache)
202 {
203 policyKey.SetValue("PackageCache", packageCacheFolder);
204 }
205 }
206
207 if (longTemp)
208 {
209 Environment.SetEnvironmentVariable("TMP", tempFolder);
210
211 if (useOriginalTempForLog)
212 {
213 nonCompressedBundle.LogDirectory = originalTemp;
214 }
215 }
216
217 try
218 {
219 nonCompressedBundle.AlternateExitCode = alternateExitCode;
220 installLogPath = nonCompressedBundle.Install(bundleCopiedPath, expectedExitCode);
221
222 if (alternateExitCode == nonCompressedBundle.LastExitCode)
223 {
224 WixAssert.Skip($"Install exited with {nonCompressedBundle.LastExitCode}");
225 }
226 }
227 finally
228 {
229 TestDataFolderFileSystem.RobocopyFolder(tempFolder, originalTemp);
230 }
231
232 installLogPath = Path.Combine(originalTemp, Path.GetFileName(installLogPath));
233
234 if (expectedExitCode == 0)
235 {
236 var registration = nonCompressedBundle.VerifyRegisteredAndInPackageCache();
237 packageA.VerifyInstalled(true);
238
239 nonCompressedBundle.Uninstall(registration.CachePath);
240
241 if (alternateExitCode == nonCompressedBundle.LastExitCode)
242 {
243 WixAssert.Skip($"Uninstall exited with {nonCompressedBundle.LastExitCode}");
244 }
245 }
246
247 nonCompressedBundle.VerifyUnregisteredAndRemovedFromPackageCache();
248 packageA.VerifyInstalled(false);
249
250 return installLogPath;
251 }
252 finally
253 {
254 Environment.SetEnvironmentVariable("TMP", originalTemp);
255
256 if (deletePolicyKey)
257 {
258 Registry.LocalMachine.DeleteSubKeyTree(policyPath);
259 }
260 else
261 {
262 using (var policyKey = Registry.LocalMachine.OpenSubKey(policyPath, writable: true))
263 {
264 policyKey?.SetValue("EngineWorkingDirectory", originalEngineWorkingDirectoryValue);
265 policyKey?.SetValue("PackageCache", originalPackageCacheValue);
266 }
267 }
268 }
269 }
270
271 private static string GetLongPath(string baseFolder)
272 {
273 Directory.CreateDirectory(baseFolder);
274
275 // Try to create a directory that is longer than MAX_PATH but without the \\?\ prefix to detect OS support for long paths.
276 // Need to PInvoke CreateDirectoryW directly because .NET methods will append the \\?\ prefix.
277 foreach (var c in new char[] { 'a', 'b', 'c' })
278 {
279 baseFolder = Path.Combine(baseFolder, new string(c, 100));
280 if (!CreateDirectoryW(baseFolder, IntPtr.Zero))
281 {
282 int lastError = Marshal.GetLastWin32Error();
283 if (lastError == 206)
284 {
285 WixAssert.Skip($"MAX_PATH is being enforced ({baseFolder})");
286 }
287 throw new Win32Exception(lastError);
288 }
289 }
290
291 return baseFolder;
292 }
293
294 [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
295 [return: MarshalAs(UnmanagedType.Bool)]
296 private extern static bool CreateDirectoryW(string lpPathName, IntPtr lpSecurityAttributes);
297 }
298}
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/testhost.longpathaware.manifest b/src/test/burn/WixToolsetTest.BurnE2E/testhost.longpathaware.manifest
new file mode 100644
index 00000000..a56ab91a
--- /dev/null
+++ b/src/test/burn/WixToolsetTest.BurnE2E/testhost.longpathaware.manifest
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4
5<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
6 <application xmlns="urn:schemas-microsoft-com:asm.v3">
7 <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
8 <ws2:longPathAware>true</ws2:longPathAware>
9 </windowsSettings>
10 </application>
11</assembly>
diff --git a/src/test/burn/test_burn.cmd b/src/test/burn/test_burn.cmd
index 83401614..80467f39 100644
--- a/src/test/burn/test_burn.cmd
+++ b/src/test/burn/test_burn.cmd
@@ -9,11 +9,16 @@
9@if /i "%1"=="test" set RuntimeTestsEnabled=true 9@if /i "%1"=="test" set RuntimeTestsEnabled=true
10@if not "%1"=="" shift & goto parse_args 10@if not "%1"=="" shift & goto parse_args
11 11
12@set _B=%~dp0..\..\..\build\IntegrationBurn\%_C%
13
12@echo Burn integration tests %_C% 14@echo Burn integration tests %_C%
13 15
14msbuild -t:Build -Restore -p:Configuration=%_C% -warnaserror -bl:%_L%\test_burn_build.binlog || exit /b 16msbuild -t:Build -Restore -p:Configuration=%_C% -warnaserror -bl:%_L%\test_burn_build.binlog || exit /b
15msbuild -t:Build -Restore TestData\TestData.proj -p:Configuration=%_C% -m -bl:%_L%\test_burn_data_build.binlog || exit /b 17msbuild -t:Build -Restore TestData\TestData.proj -p:Configuration=%_C% -m -bl:%_L%\test_burn_data_build.binlog || exit /b
16 18
19"%_B%\net35\win-x86\testexe.exe" /dm "%_B%\netcoreapp3.1\testhost.exe"
20mt.exe -manifest "WixToolsetTest.BurnE2E\testhost.longpathaware.manifest" -updateresource:"%_B%\netcoreapp3.1\testhost.exe"
21
17@if not "%RuntimeTestsEnabled%"=="true" goto :LExit 22@if not "%RuntimeTestsEnabled%"=="true" goto :LExit
18 23
19dotnet test -c %_C% --no-build WixToolsetTest.BurnE2E -l "trx;LogFileName=%_L%\TestResults\WixToolsetTest.BurnE2E.trx" || exit /b 24dotnet test -c %_C% --no-build WixToolsetTest.BurnE2E -l "trx;LogFileName=%_L%\TestResults\WixToolsetTest.BurnE2E.trx" || exit /b