aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-21 16:51:22 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-21 16:54:42 -0500
commit0531df3e9f7b3e41434def0c569bd748adc721f6 (patch)
treeec8003985cac685aee6c1ece1e0a2a05907f640e /src
parentaee568fddd21fe0fc270f7e705dc7b9e834d9ff4 (diff)
downloadwix-0531df3e9f7b3e41434def0c569bd748adc721f6.tar.gz
wix-0531df3e9f7b3e41434def0c569bd748adc721f6.tar.bz2
wix-0531df3e9f7b3e41434def0c569bd748adc721f6.zip
Detect payload collisions.
#4574
Diffstat (limited to 'src')
-rw-r--r--src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs21
-rw-r--r--src/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs10
-rw-r--r--src/WixToolset.Core.Burn/Bundles/DetectPayloadCollisionsCommand.cs137
-rw-r--r--src/WixToolset.Core.Burn/BurnBackendErrors.cs36
-rw-r--r--src/WixToolset.Core.Burn/BurnBackendWarnings.cs16
-rw-r--r--src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj3
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/BundleFixture.cs40
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs8
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/BadInput/DuplicatePayloadNames.wxs26
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs2
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs8
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs8
12 files changed, 281 insertions, 34 deletions
diff --git a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
index 4be72eec..b24481dc 100644
--- a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
+++ b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs
@@ -436,13 +436,23 @@ namespace WixToolset.Core.Burn
436 trackedFiles.Add(this.BackendHelper.TrackFile(bextManifestPath, TrackedFileType.Temporary)); 436 trackedFiles.Add(this.BackendHelper.TrackFile(bextManifestPath, TrackedFileType.Temporary));
437 } 437 }
438 438
439 var containers = section.Symbols.OfType<WixBundleContainerSymbol>().ToDictionary(t => t.Id.Id);
440 {
441 var command = new DetectPayloadCollisionsCommand(this.Messaging, containers, facades.Values, payloadSymbols, packagesPayloads);
442 command.Execute();
443 }
444
445 if (this.Messaging.EncounteredError)
446 {
447 return;
448 }
449
439 // Create all the containers except the UX container first so the manifest (that goes in the UX container) 450 // Create all the containers except the UX container first so the manifest (that goes in the UX container)
440 // can contain all size and hash information about the non-UX containers. 451 // can contain all size and hash information about the non-UX containers.
441 WixBundleContainerSymbol uxContainer; 452 WixBundleContainerSymbol uxContainer;
442 IEnumerable<WixBundlePayloadSymbol> uxPayloads; 453 IEnumerable<WixBundlePayloadSymbol> uxPayloads;
443 IEnumerable<WixBundleContainerSymbol> containers;
444 { 454 {
445 var command = new CreateNonUXContainers(this.BackendHelper, section, bundleApplicationDllSymbol, payloadSymbols, this.IntermediateFolder, layoutDirectory, this.DefaultCompressionLevel); 455 var command = new CreateNonUXContainers(this.BackendHelper, section, bundleApplicationDllSymbol, containers.Values, payloadSymbols, this.IntermediateFolder, layoutDirectory, this.DefaultCompressionLevel);
446 command.Execute(); 456 command.Execute();
447 457
448 fileTransfers.AddRange(command.FileTransfers); 458 fileTransfers.AddRange(command.FileTransfers);
@@ -450,12 +460,11 @@ namespace WixToolset.Core.Burn
450 460
451 uxContainer = command.UXContainer; 461 uxContainer = command.UXContainer;
452 uxPayloads = command.UXContainerPayloads; 462 uxPayloads = command.UXContainerPayloads;
453 containers = command.Containers;
454 } 463 }
455 464
456 // Resolve the download URLs now that we have all of the containers and payloads calculated. 465 // Resolve the download URLs now that we have all of the containers and payloads calculated.
457 { 466 {
458 var command = new ResolveDownloadUrlsCommand(this.Messaging, this.BackendExtensions, containers, payloadSymbols); 467 var command = new ResolveDownloadUrlsCommand(this.Messaging, this.BackendExtensions, containers.Values, payloadSymbols);
459 command.Execute(); 468 command.Execute();
460 } 469 }
461 470
@@ -464,7 +473,7 @@ namespace WixToolset.Core.Burn
464 { 473 {
465 var executableName = Path.GetFileName(this.OutputPath); 474 var executableName = Path.GetFileName(this.OutputPath);
466 475
467 var command = new CreateBurnManifestCommand(executableName, section, bundleSymbol, containers, chainSymbol, orderedFacades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder); 476 var command = new CreateBurnManifestCommand(executableName, section, bundleSymbol, containers.Values, chainSymbol, orderedFacades, boundaries, uxPayloads, payloadSymbols, packagesPayloads, orderedSearches, this.IntermediateFolder);
468 command.Execute(); 477 command.Execute();
469 478
470 manifestPath = command.OutputPath; 479 manifestPath = command.OutputPath;
@@ -483,7 +492,7 @@ namespace WixToolset.Core.Burn
483 } 492 }
484 493
485 { 494 {
486 var command = new CreateBundleExeCommand(this.Messaging, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers); 495 var command = new CreateBundleExeCommand(this.Messaging, this.BackendHelper, this.IntermediateFolder, this.OutputPath, bundleApplicationDllSymbol, bundleSymbol, uxContainer, containers.Values);
487 command.Execute(); 496 command.Execute();
488 497
489 fileTransfers.Add(command.Transfer); 498 fileTransfers.Add(command.Transfer);
diff --git a/src/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs b/src/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs
index 0dd2ba15..7b5984c0 100644
--- a/src/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs
+++ b/src/WixToolset.Core.Burn/Bundles/CreateNonUXContainers.cs
@@ -14,11 +14,12 @@ namespace WixToolset.Core.Burn.Bundles
14 14
15 internal class CreateNonUXContainers 15 internal class CreateNonUXContainers
16 { 16 {
17 public CreateNonUXContainers(IBackendHelper backendHelper, IntermediateSection section, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols, string intermediateFolder, string layoutFolder, CompressionLevel? defaultCompressionLevel) 17 public CreateNonUXContainers(IBackendHelper backendHelper, IntermediateSection section, WixBootstrapperApplicationDllSymbol bootstrapperApplicationDllSymbol, IEnumerable<WixBundleContainerSymbol> containerSymbols, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols, string intermediateFolder, string layoutFolder, CompressionLevel? defaultCompressionLevel)
18 { 18 {
19 this.BackendHelper = backendHelper; 19 this.BackendHelper = backendHelper;
20 this.Section = section; 20 this.Section = section;
21 this.BootstrapperApplicationDllSymbol = bootstrapperApplicationDllSymbol; 21 this.BootstrapperApplicationDllSymbol = bootstrapperApplicationDllSymbol;
22 this.Containers = containerSymbols;
22 this.PayloadSymbols = payloadSymbols; 23 this.PayloadSymbols = payloadSymbols;
23 this.IntermediateFolder = intermediateFolder; 24 this.IntermediateFolder = intermediateFolder;
24 this.LayoutFolder = layoutFolder; 25 this.LayoutFolder = layoutFolder;
@@ -33,7 +34,7 @@ namespace WixToolset.Core.Burn.Bundles
33 34
34 public IEnumerable<WixBundlePayloadSymbol> UXContainerPayloads { get; private set; } 35 public IEnumerable<WixBundlePayloadSymbol> UXContainerPayloads { get; private set; }
35 36
36 public IEnumerable<WixBundleContainerSymbol> Containers { get; private set; } 37 private IEnumerable<WixBundleContainerSymbol> Containers { get; }
37 38
38 private IBackendHelper BackendHelper { get; } 39 private IBackendHelper BackendHelper { get; }
39 40
@@ -57,11 +58,9 @@ namespace WixToolset.Core.Burn.Bundles
57 58
58 var attachedContainerIndex = 1; // count starts at one because UX container is "0". 59 var attachedContainerIndex = 1; // count starts at one because UX container is "0".
59 60
60 var containerSymbols = this.Section.Symbols.OfType<WixBundleContainerSymbol>().ToList();
61
62 var payloadsByContainer = this.PayloadSymbols.Values.ToLookup(p => p.ContainerRef); 61 var payloadsByContainer = this.PayloadSymbols.Values.ToLookup(p => p.ContainerRef);
63 62
64 foreach (var container in containerSymbols) 63 foreach (var container in this.Containers)
65 { 64 {
66 var containerId = container.Id.Id; 65 var containerId = container.Id.Id;
67 66
@@ -120,7 +119,6 @@ namespace WixToolset.Core.Burn.Bundles
120 } 119 }
121 } 120 }
122 121
123 this.Containers = containerSymbols;
124 this.UXContainerPayloads = uxPayloadSymbols; 122 this.UXContainerPayloads = uxPayloadSymbols;
125 this.FileTransfers = fileTransfers; 123 this.FileTransfers = fileTransfers;
126 this.TrackedFiles = trackedFiles; 124 this.TrackedFiles = trackedFiles;
diff --git a/src/WixToolset.Core.Burn/Bundles/DetectPayloadCollisionsCommand.cs b/src/WixToolset.Core.Burn/Bundles/DetectPayloadCollisionsCommand.cs
new file mode 100644
index 00000000..bfb6b918
--- /dev/null
+++ b/src/WixToolset.Core.Burn/Bundles/DetectPayloadCollisionsCommand.cs
@@ -0,0 +1,137 @@
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 WixToolset.Core.Burn.Bundles
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Burn;
10 using WixToolset.Data.Symbols;
11 using WixToolset.Extensibility.Services;
12
13 internal class DetectPayloadCollisionsCommand
14 {
15 public DetectPayloadCollisionsCommand(IMessaging messaging, Dictionary<string, WixBundleContainerSymbol> containerSymbols, IEnumerable<PackageFacade> packages, Dictionary<string, WixBundlePayloadSymbol> payloadSymbols, Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> packagePayloads)
16 {
17 this.Messaging = messaging;
18 this.Containers = containerSymbols;
19 this.Packages = packages;
20 this.PayloadSymbols = payloadSymbols;
21 this.PackagePayloads = packagePayloads;
22 }
23
24 private IMessaging Messaging { get; }
25
26 private Dictionary<string, WixBundleContainerSymbol> Containers { get; }
27
28 private IEnumerable<PackageFacade> Packages { get; }
29
30 private Dictionary<string, WixBundlePayloadSymbol> PayloadSymbols { get; }
31
32 private Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>> PackagePayloads { get; }
33
34 public void Execute()
35 {
36 this.DetectAttachedContainerCollisions();
37 this.DetectExternalCollisions();
38 this.DetectPackageCacheCollisions();
39 }
40
41 public void DetectAttachedContainerCollisions()
42 {
43 var attachedContainerPayloadsByNameByContainer = new Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>>();
44
45 foreach (var payload in this.PayloadSymbols.Values.Where(p => p.Packaging == PackagingType.Embedded))
46 {
47 var containerId = payload.ContainerRef;
48 var container = this.Containers[containerId];
49 if (container.Type == ContainerType.Attached)
50 {
51 if (!attachedContainerPayloadsByNameByContainer.TryGetValue(containerId, out var attachedContainerPayloadsByName))
52 {
53 attachedContainerPayloadsByName = new Dictionary<string, WixBundlePayloadSymbol>(StringComparer.OrdinalIgnoreCase);
54 attachedContainerPayloadsByNameByContainer.Add(containerId, attachedContainerPayloadsByName);
55 }
56
57 if (!attachedContainerPayloadsByName.TryGetValue(payload.Name, out var collisionPayload))
58 {
59 attachedContainerPayloadsByName.Add(payload.Name, payload);
60 }
61 else
62 {
63 if (containerId == BurnConstants.BurnUXContainerName)
64 {
65 this.Messaging.Write(BurnBackendErrors.BAContainerPayloadCollision(payload.SourceLineNumbers, payload.Id.Id, payload.Name));
66 this.Messaging.Write(BurnBackendErrors.BAContainerPayloadCollision2(collisionPayload.SourceLineNumbers));
67 }
68 else
69 {
70 this.Messaging.Write(BurnBackendWarnings.AttachedContainerPayloadCollision(payload.SourceLineNumbers, payload.Id.Id, payload.Name));
71 this.Messaging.Write(BurnBackendWarnings.AttachedContainerPayloadCollision2(collisionPayload.SourceLineNumbers));
72 }
73 }
74 }
75 }
76 }
77
78 public void DetectExternalCollisions()
79 {
80 var externalPayloadsByName = new Dictionary<string, IntermediateSymbol>(StringComparer.OrdinalIgnoreCase);
81
82 foreach (var payload in this.PayloadSymbols.Values.Where(p => p.Packaging == PackagingType.External))
83 {
84 if (!externalPayloadsByName.TryGetValue(payload.Name, out var collisionSymbol))
85 {
86 externalPayloadsByName.Add(payload.Name, payload);
87 }
88 else
89 {
90 this.Messaging.Write(BurnBackendErrors.ExternalPayloadCollision(payload.SourceLineNumbers, "Payload", payload.Id.Id, payload.Name));
91 this.Messaging.Write(BurnBackendErrors.ExternalPayloadCollision2(collisionSymbol.SourceLineNumbers));
92 }
93 }
94
95 foreach (var container in this.Containers.Values.Where(c => c.Type == ContainerType.Detached))
96 {
97 if (!externalPayloadsByName.TryGetValue(container.Name, out var collisionSymbol))
98 {
99 externalPayloadsByName.Add(container.Name, container);
100 }
101 else
102 {
103 this.Messaging.Write(BurnBackendErrors.ExternalPayloadCollision(container.SourceLineNumbers, "Container", container.Id.Id, container.Name));
104 this.Messaging.Write(BurnBackendErrors.ExternalPayloadCollision2(collisionSymbol.SourceLineNumbers));
105 }
106 }
107 }
108
109 public void DetectPackageCacheCollisions()
110 {
111 var packageCachePayloadsByNameByCacheId = new Dictionary<string, Dictionary<string, WixBundlePayloadSymbol>>();
112
113 foreach (var packageFacade in this.Packages)
114 {
115 var packagePayloads = this.PackagePayloads[packageFacade.PackageId];
116 if (!packageCachePayloadsByNameByCacheId.TryGetValue(packageFacade.PackageSymbol.CacheId, out var packageCachePayloadsByName))
117 {
118 packageCachePayloadsByName = new Dictionary<string, WixBundlePayloadSymbol>(StringComparer.OrdinalIgnoreCase);
119 packageCachePayloadsByNameByCacheId.Add(packageFacade.PackageSymbol.CacheId, packageCachePayloadsByName);
120 }
121
122 foreach (var payload in packagePayloads.Values)
123 {
124 if (!packageCachePayloadsByName.TryGetValue(payload.Name, out var collisionPayload))
125 {
126 packageCachePayloadsByName.Add(payload.Name, payload);
127 }
128 else
129 {
130 this.Messaging.Write(BurnBackendErrors.PackageCachePayloadCollision(payload.SourceLineNumbers, payload.Id.Id, payload.Name, packageFacade.PackageId));
131 this.Messaging.Write(BurnBackendErrors.PackageCachePayloadCollision2(collisionPayload.SourceLineNumbers));
132 }
133 }
134 }
135 }
136 }
137}
diff --git a/src/WixToolset.Core.Burn/BurnBackendErrors.cs b/src/WixToolset.Core.Burn/BurnBackendErrors.cs
index 02ab1b5d..6f9a3706 100644
--- a/src/WixToolset.Core.Burn/BurnBackendErrors.cs
+++ b/src/WixToolset.Core.Burn/BurnBackendErrors.cs
@@ -6,6 +6,16 @@ namespace WixToolset.Core.Burn
6 6
7 internal static class BurnBackendErrors 7 internal static class BurnBackendErrors
8 { 8 {
9 public static Message BAContainerPayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName)
10 {
11 return Message(sourceLineNumbers, Ids.BAContainerPayloadCollision, "The Payload '{0}' has a duplicate Name '{1}' in the BA container. When extracting the container at runtime, the file will get overwritten.", payloadId, payloadName);
12 }
13
14 public static Message BAContainerPayloadCollision2(SourceLineNumber sourceLineNumbers)
15 {
16 return Message(sourceLineNumbers, Ids.BAContainerPayloadCollision2, "The location of the payload related to the previous error.");
17 }
18
9 public static Message DuplicateCacheIds(SourceLineNumber originalLineNumber, string cacheId, string packageId) 19 public static Message DuplicateCacheIds(SourceLineNumber originalLineNumber, string cacheId, string packageId)
10 { 20 {
11 return Message(originalLineNumber, Ids.DuplicateCacheIds, "The CacheId '{0}' for package '{1}' is duplicated. Each package must have a unique CacheId.", cacheId, packageId); 21 return Message(originalLineNumber, Ids.DuplicateCacheIds, "The CacheId '{0}' for package '{1}' is duplicated. Each package must have a unique CacheId.", cacheId, packageId);
@@ -16,6 +26,26 @@ namespace WixToolset.Core.Burn
16 return Message(duplicateLineNumber, Ids.DuplicateCacheIds2, "The location of the package related to the previous error."); 26 return Message(duplicateLineNumber, Ids.DuplicateCacheIds2, "The location of the package related to the previous error.");
17 } 27 }
18 28
29 public static Message ExternalPayloadCollision(SourceLineNumber sourceLineNumbers, string symbolName, string payloadId, string payloadName)
30 {
31 return Message(sourceLineNumbers, Ids.ExternalPayloadCollision, "The external {0} '{1}' has a duplicate Name '{2}'. When building the bundle or laying out the bundle, the file will get overwritten.", symbolName, payloadId, payloadName);
32 }
33
34 public static Message ExternalPayloadCollision2(SourceLineNumber sourceLineNumbers)
35 {
36 return Message(sourceLineNumbers, Ids.ExternalPayloadCollision2, "The location of the symbol related to the previous error.");
37 }
38
39 public static Message PackageCachePayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName, string packageId)
40 {
41 return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision, "The Payload '{0}' has a duplicate Name '{1}' in package '{2}'. When caching the package, the file will get overwritten.", payloadId, payloadName, packageId);
42 }
43
44 public static Message PackageCachePayloadCollision2(SourceLineNumber sourceLineNumbers)
45 {
46 return Message(sourceLineNumbers, Ids.PackageCachePayloadCollision2, "The location of the payload related to the previous error.");
47 }
48
19 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) 49 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
20 { 50 {
21 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); 51 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
@@ -25,6 +55,12 @@ namespace WixToolset.Core.Burn
25 { 55 {
26 DuplicateCacheIds = 8000, 56 DuplicateCacheIds = 8000,
27 DuplicateCacheIds2 = 8001, 57 DuplicateCacheIds2 = 8001,
58 BAContainerPayloadCollision = 8002,
59 BAContainerPayloadCollision2 = 8003,
60 ExternalPayloadCollision = 8004,
61 ExternalPayloadCollision2 = 8005,
62 PackageCachePayloadCollision = 8006,
63 PackageCachePayloadCollision2 = 8007,
28 } 64 }
29 } 65 }
30} 66}
diff --git a/src/WixToolset.Core.Burn/BurnBackendWarnings.cs b/src/WixToolset.Core.Burn/BurnBackendWarnings.cs
index 9b2fa6c9..cbbc954e 100644
--- a/src/WixToolset.Core.Burn/BurnBackendWarnings.cs
+++ b/src/WixToolset.Core.Burn/BurnBackendWarnings.cs
@@ -6,10 +6,15 @@ namespace WixToolset.Core.Burn
6 6
7 internal static class BurnBackendWarnings 7 internal static class BurnBackendWarnings
8 { 8 {
9 //public static Message ReplaceThisWithTheFirstWarning(SourceLineNumber sourceLineNumbers) 9 public static Message AttachedContainerPayloadCollision(SourceLineNumber sourceLineNumbers, string payloadId, string payloadName)
10 //{ 10 {
11 // return Message(sourceLineNumbers, Ids.ReplaceThisWithTheFirstWarning, "format string", arg1, arg2); 11 return Message(sourceLineNumbers, Ids.AttachedContainerPayloadCollision, "The Payload '{0}' has a duplicate Name '{1}' in the attached container. When extracting the bundle with dark.exe, the file will get overwritten.", payloadId, payloadName);
12 //} 12 }
13
14 public static Message AttachedContainerPayloadCollision2(SourceLineNumber sourceLineNumbers)
15 {
16 return Message(sourceLineNumbers, Ids.AttachedContainerPayloadCollision2, "The location of the payload related to the previous error.");
17 }
13 18
14 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) 19 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
15 { 20 {
@@ -18,7 +23,8 @@ namespace WixToolset.Core.Burn
18 23
19 public enum Ids 24 public enum Ids
20 { 25 {
21 // ReplaceThisWithTheFirstWarning = 8500, 26 AttachedContainerPayloadCollision = 8500,
27 AttachedContainerPayloadCollision2 = 8501,
22 } 28 }
23 } 29 }
24} 30}
diff --git a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj
index 85bfae69..f2da8a50 100644
--- a/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj
+++ b/src/WixToolset.Core.Burn/WixToolset.Core.Burn.csproj
@@ -19,6 +19,9 @@
19 <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> 19 <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
20 <_Parameter1>WixToolsetTest.Core.Burn, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a9967ec28982f42ee51a47dd5204315975a6ed69294b982146a99a70130a2fa13e226aaddde14c17d1bf3af69e8956d69a86585e74d208efcc5ac98a0686055327b2e87960d3c39bf3a6bc1e572863327d19dbf4fd2616dda124dbea260755a2d1d39d3cf1049ea526493eb2bf996b8ad985e3012308529e5b9b0f5cd5fa04bd</_Parameter1> 20 <_Parameter1>WixToolsetTest.Core.Burn, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a9967ec28982f42ee51a47dd5204315975a6ed69294b982146a99a70130a2fa13e226aaddde14c17d1bf3af69e8956d69a86585e74d208efcc5ac98a0686055327b2e87960d3c39bf3a6bc1e572863327d19dbf4fd2616dda124dbea260755a2d1d39d3cf1049ea526493eb2bf996b8ad985e3012308529e5b9b0f5cd5fa04bd</_Parameter1>
21 </AssemblyAttribute> 21 </AssemblyAttribute>
22 <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
23 <_Parameter1>WixToolsetTest.CoreIntegration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a9967ec28982f42ee51a47dd5204315975a6ed69294b982146a99a70130a2fa13e226aaddde14c17d1bf3af69e8956d69a86585e74d208efcc5ac98a0686055327b2e87960d3c39bf3a6bc1e572863327d19dbf4fd2616dda124dbea260755a2d1d39d3cf1049ea526493eb2bf996b8ad985e3012308529e5b9b0f5cd5fa04bd</_Parameter1>
24 </AssemblyAttribute>
22 </ItemGroup> 25 </ItemGroup>
23 26
24 <ItemGroup> 27 <ItemGroup>
diff --git a/src/test/WixToolsetTest.CoreIntegration/BundleFixture.cs b/src/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
index d121da0f..cc91d212 100644
--- a/src/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
@@ -10,6 +10,7 @@ namespace WixToolsetTest.CoreIntegration
10 using System.Xml; 10 using System.Xml;
11 using Example.Extension; 11 using Example.Extension;
12 using WixBuildTools.TestSupport; 12 using WixBuildTools.TestSupport;
13 using WixToolset.Core.Burn;
13 using WixToolset.Core.TestPackage; 14 using WixToolset.Core.TestPackage;
14 using WixToolset.Data; 15 using WixToolset.Data;
15 using WixToolset.Data.Burn; 16 using WixToolset.Data.Burn;
@@ -306,7 +307,7 @@ namespace WixToolsetTest.CoreIntegration
306 } 307 }
307 } 308 }
308 309
309 [Fact(Skip = "https://github.com/wixtoolset/issues/issues/4574")] 310 [Fact]
310 public void CantBuildWithDuplicatePayloadNames() 311 public void CantBuildWithDuplicatePayloadNames()
311 { 312 {
312 var folder = TestData.Get(@"TestData"); 313 var folder = TestData.Get(@"TestData");
@@ -328,7 +329,42 @@ namespace WixToolsetTest.CoreIntegration
328 "-o", exePath, 329 "-o", exePath,
329 }); 330 });
330 331
331 Assert.InRange(result.ExitCode, 2, Int32.MaxValue); 332 var attachedContainerWarnings = result.Messages.Where(m => m.Id == (int)BurnBackendWarnings.Ids.AttachedContainerPayloadCollision)
333 .Select(m => m.ToString())
334 .ToArray();
335 WixAssert.CompareLineByLine(new string[]
336 {
337 "The Payload 'Auto2' has a duplicate Name 'burn.exe' in the attached container. When extracting the bundle with dark.exe, the file will get overwritten.",
338 }, attachedContainerWarnings);
339
340 var baContainerErrors = result.Messages.Where(m => m.Id == (int)BurnBackendErrors.Ids.BAContainerPayloadCollision)
341 .Select(m => m.ToString())
342 .ToArray();
343 WixAssert.CompareLineByLine(new string[]
344 {
345 "The Payload 'DuplicatePayloadNames.wxs' has a duplicate Name 'fakeba.dll' in the BA container. When extracting the container at runtime, the file will get overwritten.",
346 "The Payload 'uxTxMXPVMXwQrPTMIGa5WGt93w0Ns' has a duplicate Name 'BootstrapperApplicationData.xml' in the BA container. When extracting the container at runtime, the file will get overwritten.",
347 "The Payload 'uxYRbgitOs0K878jn5L_z7LdJ21KI' has a duplicate Name 'BundleExtensionData.xml' in the BA container. When extracting the container at runtime, the file will get overwritten.",
348 }, baContainerErrors);
349
350 var externalErrors = result.Messages.Where(m => m.Id == (int)BurnBackendErrors.Ids.ExternalPayloadCollision)
351 .Select(m => m.ToString())
352 .ToArray();
353 WixAssert.CompareLineByLine(new string[]
354 {
355 "The external Payload 'HiddenPersistedBundleVariable.wxs' has a duplicate Name 'PayloadCollision'. When building the bundle or laying out the bundle, the file will get overwritten.",
356 "The external Container 'MsiPackagesContainer' has a duplicate Name 'ContainerCollision'. When building the bundle or laying out the bundle, the file will get overwritten.",
357 }, externalErrors);
358
359 var packageCacheErrors = result.Messages.Where(m => m.Id == (int)BurnBackendErrors.Ids.PackageCachePayloadCollision)
360 .Select(m => m.ToString())
361 .ToArray();
362 WixAssert.CompareLineByLine(new string[]
363 {
364 "The Payload 'test.msi' has a duplicate Name 'test.msi' in package 'test.msi'. When caching the package, the file will get overwritten.",
365 }, packageCacheErrors);
366
367 Assert.Equal(14, result.Messages.Length);
332 } 368 }
333 } 369 }
334 370
diff --git a/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs b/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs
index 7ec0ea93..a566b490 100644
--- a/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/MsiTransactionFixture.cs
@@ -81,7 +81,7 @@ namespace WixToolsetTest.CoreIntegration
81 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), 81 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
82 "-bindpath", Path.Combine(folder, "SingleFile", "data"), 82 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
83 "-intermediateFolder", intermediateFolder, 83 "-intermediateFolder", intermediateFolder,
84 "-o", Path.Combine(binFolder, "FirstX86.msi"), 84 "-o", Path.Combine(binFolder, "FirstX86", "FirstX86.msi"),
85 }); 85 });
86 86
87 result.AssertSuccess(); 87 result.AssertSuccess();
@@ -94,7 +94,7 @@ namespace WixToolsetTest.CoreIntegration
94 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"), 94 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
95 "-bindpath", Path.Combine(folder, "SingleFile", "data"), 95 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
96 "-intermediateFolder", intermediateFolder, 96 "-intermediateFolder", intermediateFolder,
97 "-o", Path.Combine(binFolder, "SecondX86.msi"), 97 "-o", Path.Combine(binFolder, "SecondX86", "SecondX86.msi"),
98 }); 98 });
99 99
100 result.AssertSuccess(); 100 result.AssertSuccess();
@@ -108,7 +108,7 @@ namespace WixToolsetTest.CoreIntegration
108 "-bindpath", Path.Combine(folder, "SingleFile", "data"), 108 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
109 "-intermediateFolder", intermediateFolder, 109 "-intermediateFolder", intermediateFolder,
110 "-arch", "x64", 110 "-arch", "x64",
111 "-o", Path.Combine(binFolder, "FirstX64.msi"), 111 "-o", Path.Combine(binFolder, "FirstX64", "FirstX64.msi"),
112 }); 112 });
113 113
114 result.AssertSuccess(); 114 result.AssertSuccess();
@@ -122,7 +122,7 @@ namespace WixToolsetTest.CoreIntegration
122 "-bindpath", Path.Combine(folder, "SingleFile", "data"), 122 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
123 "-intermediateFolder", intermediateFolder, 123 "-intermediateFolder", intermediateFolder,
124 "-arch", "x64", 124 "-arch", "x64",
125 "-o", Path.Combine(binFolder, "SecondX64.msi"), 125 "-o", Path.Combine(binFolder, "SecondX64", "SecondX64.msi"),
126 }); 126 });
127 127
128 result.AssertSuccess(); 128 result.AssertSuccess();
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BadInput/DuplicatePayloadNames.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BadInput/DuplicatePayloadNames.wxs
index 2d4e8a3c..4fe7e097 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/BadInput/DuplicatePayloadNames.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BadInput/DuplicatePayloadNames.wxs
@@ -2,8 +2,30 @@
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment> 3 <Fragment>
4 <PackageGroup Id="BundlePackages"> 4 <PackageGroup Id="BundlePackages">
5 <ExePackage Id="Auto1" SourceFile="burn.exe" CacheId="Auto1" /> 5 <ExePackage Id="Auto1" SourceFile="burn.exe" CacheId="Auto1" DetectCondition="none" />
6 <ExePackage Id="Auto2" SourceFile="burn.exe" CacheId="Auto2" /> 6 <ExePackage Id="Auto2" SourceFile="burn.exe" CacheId="Auto2" DetectCondition="none" />
7 <ExePackage Id="DuplicateCacheIds.wxs" SourceFile="$(sys.SOURCEFILEDIR)DuplicateCacheIds.wxs" Compressed="no" DetectCondition="none" Name="PayloadCollision">
8 <Payload SourceFile="$(sys.SOURCEFILEDIR)BundleVariable.wxs" Compressed="no" Name="ContainerCollision" />
9 </ExePackage>
10 <ExePackage Id="HiddenPersistedBundleVariable.wxs" SourceFile="$(sys.SOURCEFILEDIR)HiddenPersistedBundleVariable.wxs" Compressed="no" DetectCondition="none" Name="PayloadCollision" />
11 <PackageGroupRef Id="MsiPackages" />
7 </PackageGroup> 12 </PackageGroup>
13
14 <PackageGroup Id="MsiPackages">
15 <MsiPackage SourceFile="test.msi">
16 <Payload SourceFile="$(sys.SOURCEFILEDIR)InvalidIds.wxs" Name="MsiPackage\test.txt" />
17 <Payload SourceFile="$(sys.SOURCEFILEDIR)RegistryKey.wxs" Name="test.msi" />
18 </MsiPackage>
19 </PackageGroup>
20
21 <Container Id="MsiPackagesContainer" Type="detached" Name="ContainerCollision">
22 <PackageGroupRef Id="MsiPackages" />
23 </Container>
24
25 <BootstrapperApplication>
26 <Payload Id="DuplicatePayloadNames.wxs" SourceFile="$(sys.SOURCEFILEPATH)" Name="fakeba.dll" />
27 <Payload Id="UnscheduledPackage.wxs" SourceFile="$(sys.SOURCEFILEDIR)UnscheduledPackage.wxs" Name="BootstrapperApplicationData.xml" />
28 <Payload Id="UnscheduledRollbackBoundary.wxs" SourceFile="$(sys.SOURCEFILEDIR)UnscheduledRollbackBoundary.wxs" Name="BundleExtensionData.xml" />
29 </BootstrapperApplication>
8 </Fragment> 30 </Fragment>
9</Wix> 31</Wix>
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
index db755171..e52302d4 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
@@ -48,6 +48,6 @@
48 </BundleElement> 48 </BundleElement>
49 </BundleCustomDataRef> 49 </BundleCustomDataRef>
50 50
51 <BundleExtension Id="CustomTableExtension" SourceFile="fakeba.dll" /> 51 <BundleExtension Id="CustomTableExtension" SourceFile="fakeba.dll" Name="fakebext.dll" />
52 </Fragment> 52 </Fragment>
53</Wix> 53</Wix>
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs
index 8f4fc8bd..e6527a36 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X64AfterX86Bundle.wxs
@@ -2,11 +2,11 @@
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment> 3 <Fragment>
4 <PackageGroup Id="BundlePackages"> 4 <PackageGroup Id="BundlePackages">
5 <MsiPackage SourceFile="FirstX64.msi" /> 5 <MsiPackage SourceFile="FirstX64\" Name="FirstX64\FirstX64.msi" />
6 <RollbackBoundary Transaction="yes" /> 6 <RollbackBoundary Transaction="yes" />
7 <MsiPackage SourceFile="FirstX86.msi" /> 7 <MsiPackage SourceFile="FirstX86\" Name="FirstX86\FirstX86.msi" />
8 <MsiPackage SourceFile="SecondX86.msi" /> 8 <MsiPackage SourceFile="SecondX86\" Name="SecondX86\SecondX86.msi" />
9 <MsiPackage SourceFile="SecondX64.msi" /> 9 <MsiPackage SourceFile="SecondX64\" Name="SecondX64\SecondX64.msi" />
10 </PackageGroup> 10 </PackageGroup>
11 </Fragment> 11 </Fragment>
12</Wix> 12</Wix>
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs
index 221f06c5..f1c939db 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/MsiTransaction/X86AfterX64Bundle.wxs
@@ -2,11 +2,11 @@
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Fragment> 3 <Fragment>
4 <PackageGroup Id="BundlePackages"> 4 <PackageGroup Id="BundlePackages">
5 <MsiPackage SourceFile="FirstX86.msi" /> 5 <MsiPackage SourceFile="FirstX86\" Name="FirstX86\FirstX86.msi" />
6 <RollbackBoundary Transaction="yes" /> 6 <RollbackBoundary Transaction="yes" />
7 <MsiPackage SourceFile="FirstX64.msi" /> 7 <MsiPackage SourceFile="FirstX64\" Name="FirstX64\FirstX64.msi" />
8 <MsiPackage SourceFile="SecondX64.msi" /> 8 <MsiPackage SourceFile="SecondX64\" Name="SecondX64\SecondX64.msi" />
9 <MsiPackage SourceFile="SecondX86.msi" /> 9 <MsiPackage SourceFile="SecondX86\" Name="SecondX86\SecondX86.msi" />
10 </PackageGroup> 10 </PackageGroup>
11 </Fragment> 11 </Fragment>
12</Wix> 12</Wix>