From 7d15b1bc97cdd9933ca43a6b16b84a81b22c3457 Mon Sep 17 00:00:00 2001
From: Rob Mensching <rob@firegiant.com>
Date: Thu, 3 Feb 2022 07:36:01 -0800
Subject: Fix feature/component mapping verification

---
 src/wix/WixToolset.Core/Linker.cs                  | 12 +++---
 .../FeatureFixture.cs                              | 43 ++++++++++++++++++++++
 .../PackageMissingFeatureComponentMapping.wxs      | 21 +++++++++++
 3 files changed, 69 insertions(+), 7 deletions(-)
 create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/FeatureFixture.cs
 create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/Feature/PackageMissingFeatureComponentMapping.wxs

(limited to 'src')

diff --git a/src/wix/WixToolset.Core/Linker.cs b/src/wix/WixToolset.Core/Linker.cs
index 47671f26..1fb7d18c 100644
--- a/src/wix/WixToolset.Core/Linker.cs
+++ b/src/wix/WixToolset.Core/Linker.cs
@@ -156,11 +156,11 @@ namespace WixToolset.Core
                 }
 
                 // Display an error message for Components that were not referenced by a Feature.
-                foreach (var symbolWithSection in resolve.ReferencedSymbolWithSections.Where(s => s.Symbol.Definition.Type == SymbolDefinitionType.Component))
+                foreach (var component in sections.SelectMany(s => s.Symbols.Where(y => y.Definition.Type == SymbolDefinitionType.Component)))
                 {
-                    if (!referencedComponents.Contains(symbolWithSection.Name))
+                    if (!referencedComponents.Contains(component.Id.Id))
                     {
-                        this.Messaging.Write(ErrorMessages.OrphanedComponent(symbolWithSection.Symbol.SourceLineNumbers, symbolWithSection.Symbol.Id.Id));
+                        this.Messaging.Write(ErrorMessages.OrphanedComponent(component.SourceLineNumbers, component.Id.Id));
                     }
                 }
 
@@ -451,8 +451,7 @@ namespace WixToolset.Core
                                     });
 
                                     // index the component for finding orphaned records
-                                    var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
-                                    referencedComponents.Add(symbolName);
+                                    referencedComponents.Add(wixComplexReferenceRow.Child);
 
                                     break;
 
@@ -521,8 +520,7 @@ namespace WixToolset.Core
                                     }
 
                                     // index the component for finding orphaned records
-                                    var componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
-                                    referencedComponents.Add(componentSymbolName);
+                                    referencedComponents.Add(wixComplexReferenceRow.Child);
 
                                     break;
 
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/FeatureFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/FeatureFixture.cs
new file mode 100644
index 00000000..f70db559
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/FeatureFixture.cs
@@ -0,0 +1,43 @@
+// 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.
+
+namespace WixToolsetTest.CoreIntegration
+{
+    using System;
+    using System.IO;
+    using System.Linq;
+    using WixBuildTools.TestSupport;
+    using WixToolset.Core.TestPackage;
+    using WixToolset.Data;
+    using Xunit;
+
+    public class FeatureFixture
+    {
+        [Fact]
+        public void CanDetectMissingFeatureComponentMapping()
+        {
+            var folder = TestData.Get(@"TestData");
+
+            using (var fs = new DisposableFileSystem())
+            {
+                var baseFolder = fs.GetFolder();
+                var intermediateFolder = Path.Combine(baseFolder, "obj");
+                var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
+
+                var result = WixRunner.Execute(new[]
+                {
+                    "build",
+                    Path.Combine(folder, "Feature", "PackageMissingFeatureComponentMapping.wxs"),
+                    "-bindpath", Path.Combine(folder, "SingleFile", "data"),
+                    "-intermediateFolder", intermediateFolder,
+                    "-o", msiPath
+                });
+
+                var errors = result.Messages.Where(m => m.Level == MessageLevel.Error);
+                Assert.Equal(new[]
+                {
+                    267
+                }, errors.Select(e => e.Id).ToArray());
+            }
+        }
+    }
+}
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Feature/PackageMissingFeatureComponentMapping.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Feature/PackageMissingFeatureComponentMapping.wxs
new file mode 100644
index 00000000..ea7a8a10
--- /dev/null
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Feature/PackageMissingFeatureComponentMapping.wxs
@@ -0,0 +1,21 @@
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
+    <Package Name="PackageMissingFeatureComponentMapping" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="12E4699F-E774-4D05-8A01-5BDD41BBA127">
+        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
+        
+        <StandardDirectory Id="ProgramFiles6432Folder">
+            <Directory Id="INSTALLFOLDER" Name="PackageMissingFeatureComponentMapping">
+                <Directory Name="NotMapped">
+                    <Component>
+                        <File Source="test.txt" />
+                    </Component>
+                </Directory>
+            </Directory>
+        </StandardDirectory>
+
+        <Feature Id="MissingComponentFeature" Title="Feature is Missing a ComponentRef">
+            <Component Directory="INSTALLFOLDER">
+                <File Source="test.txt" />
+            </Component>
+        </Feature>
+    </Package>
+</Wix>
-- 
cgit v1.2.3-55-g6feb