| 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.CoreIntegration |
| 4 | { |
| 5 | using System.Collections.Generic; |
| 6 | using System.IO; |
| 7 | using System.Linq; |
| 8 | using WixInternal.Core.TestPackage; |
| 9 | using WixInternal.TestSupport; |
| 10 | using WixToolset.Data; |
| 11 | using WixToolset.Data.Symbols; |
| 12 | using Xunit; |
| 13 | |
| 14 | public class AccessModifierFixture |
| 15 | { |
| 16 | [Fact] |
| 17 | public void CanCompileVirtualSymbol() |
| 18 | { |
| 19 | var dirSymbols = BuildToGetDirectorySymbols("TestData", "AccessModifier", "HasVirtualSymbol.wxs"); |
| 20 | WixAssert.CompareLineByLine(new[] |
| 21 | { |
| 22 | "virtual:ProgramFilesFolder:TARGETDIR:PFiles", |
| 23 | "virtual:TARGETDIR::SourceDir", |
| 24 | "virtual:TestFolder:ProgramFilesFolder:Test Folder", |
| 25 | }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Access.AsString() + ":" + d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); |
| 26 | } |
| 27 | |
| 28 | [Fact] |
| 29 | public void CanCompileOverrideVirtualSymbol() |
| 30 | { |
| 31 | var dirSymbols = BuildToGetDirectorySymbols("TestData", "AccessModifier", "OverrideVirtualSymbol.wxs"); |
| 32 | WixAssert.CompareLineByLine(new[] |
| 33 | { |
| 34 | "virtual:ProgramFilesFolder:TARGETDIR:PFiles", |
| 35 | "virtual:TARGETDIR::SourceDir", |
| 36 | "override:TestFolder:ProgramFilesFolder:Override Test Folder", |
| 37 | }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Access.AsString() + ":" + d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); |
| 38 | } |
| 39 | |
| 40 | [Fact] |
| 41 | public void CanCompileVirtualSymbolOverridden() |
| 42 | { |
| 43 | var dirSymbols = BuildToGetDirectorySymbols("TestData", "AccessModifier", "VirtualSymbolOverridden.wxs"); |
| 44 | WixAssert.CompareLineByLine(new[] |
| 45 | { |
| 46 | "virtual:ProgramFilesFolder:TARGETDIR:PFiles", |
| 47 | "virtual:TARGETDIR::SourceDir", |
| 48 | "override:TestFolder:ProgramFilesFolder:Test Folder Overrode Virtual", |
| 49 | }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Access.AsString() + ":" + d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); |
| 50 | } |
| 51 | |
| 52 | [Fact] |
| 53 | public void CanCompileVirtualSymbolWithFragments() |
| 54 | { |
| 55 | var dirSymbols = BuildToGetDirectorySymbols("TestData", "AccessModifier", "OverrideVirtualSymbolWithFragments.wxs"); |
| 56 | WixAssert.CompareLineByLine(new[] |
| 57 | { |
| 58 | "global:AlsoIncluded:ProgramFilesFolder:Also Included", |
| 59 | "virtual:ProgramFilesFolder:TARGETDIR:PFiles", |
| 60 | "virtual:TARGETDIR::SourceDir", |
| 61 | "override:TestFolder:ProgramFilesFolder:Override Test Folder Includes Another", |
| 62 | }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Access.AsString() + ":" + d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); |
| 63 | } |
| 64 | |
| 65 | [Fact] |
| 66 | public void CanCompileVirtualSymbolThatDoesNotGetOverridden() |
| 67 | { |
| 68 | var dirSymbols = BuildToGetDirectorySymbols("TestData", "AccessModifier", "VirtualSymbolThatDoesNotGetOverridden.wxs"); |
| 69 | WixAssert.CompareLineByLine(new[] |
| 70 | { |
| 71 | "virtual:ProgramFilesFolder:TARGETDIR:PFiles", |
| 72 | "virtual:TARGETDIR::SourceDir", |
| 73 | "virtual:TestFolder:ProgramFilesFolder:Used", |
| 74 | }, dirSymbols.OrderBy(d => d.Id.Id).Select(d => d.Id.Access.AsString() + ":" + d.Id.Id + ":" + d.ParentDirectoryRef + ":" + d.Name).ToArray()); |
| 75 | } |
| 76 | |
| 77 | [Fact] |
| 78 | public void CannotCompileInvalidCrossFragmentReference() |
| 79 | { |
| 80 | var errors = BuildForFailure("TestData", "AccessModifier", "InvalidCrossFragmentReference.wxs"); |
| 81 | WixAssert.CompareLineByLine(new[] |
| 82 | { |
| 83 | "ln 4: The identifier 'Directory:Foo' is inaccessible due to its protection level.", |
| 84 | }, errors); |
| 85 | } |
| 86 | |
| 87 | [Fact] |
| 88 | public void CannotCompileDuplicateCrossFragmentReference() |
| 89 | { |
| 90 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicateCrossFragmentReference.wxs"); |
| 91 | WixAssert.CompareLineByLine(new[] |
| 92 | { |
| 93 | "ln 8: Duplicate Directory with identifier 'TestFolder' referenced by <sourceFolder>\\DuplicateCrossFragmentReference.wxs(4). Ensure all your identifiers of a given type (Directory, File, etc.) are unique or use an access modifier to scope the identfier.", |
| 94 | "ln 12: Location of symbol related to previous error.", |
| 95 | "ln 16: Location of symbol related to previous error." |
| 96 | }, errors); |
| 97 | } |
| 98 | |
| 99 | [Fact] |
| 100 | public void CannotCompileOverrideWithoutVirtualSymbol() |
| 101 | { |
| 102 | var errors = BuildForFailure("TestData", "AccessModifier", "OverrideWithoutVirtualSymbol.wxs"); |
| 103 | WixAssert.CompareLineByLine(new[] |
| 104 | { |
| 105 | "ln 5: Could not find a virtual symbol to override with the Directory symbol 'TestFolder'. Remove the override access modifier or include the code with the virtual symbol.", |
| 106 | }, errors); |
| 107 | } |
| 108 | |
| 109 | [Fact] |
| 110 | public void CannotCompileDuplicatedOverride() |
| 111 | { |
| 112 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatedOverrideVirtualSymbol.wxs"); |
| 113 | WixAssert.CompareLineByLine(new[] |
| 114 | { |
| 115 | "ln 6: Duplicate Directory with identifier 'TestFolder' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", |
| 116 | "ln 14: Location of symbol related to previous error." |
| 117 | }, errors); |
| 118 | } |
| 119 | |
| 120 | [Fact] |
| 121 | public void CannotCompileDuplicatedVirtual() |
| 122 | { |
| 123 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatedVirtualSymbol.wxs"); |
| 124 | WixAssert.CompareLineByLine(new[] |
| 125 | { |
| 126 | "ln 6: The virtual Directory with identifier 'TestFolder' is duplicated. Ensure identifiers of a given type (Directory, File, etc.) are unique or did you mean to make one an override for the virtual symbol?", |
| 127 | "ln 10: Location of symbol related to previous error." |
| 128 | }, errors); |
| 129 | } |
| 130 | |
| 131 | [Fact] |
| 132 | public void CannotCompilePublicWithVirtualSymbol() |
| 133 | { |
| 134 | var errors = BuildForFailure("TestData", "AccessModifier", "VirtualSymbolWithoutOverride.wxs"); |
| 135 | WixAssert.CompareLineByLine(new[] |
| 136 | { |
| 137 | "ln 9: The Directory symbol 'TestFolder' conflicts with a virtual symbol. Use the 'override' access modifier to override the virtual symbol or use a different Id to avoid the conflict.", |
| 138 | "ln 5: Location of symbol related to previous error." |
| 139 | }, errors); |
| 140 | } |
| 141 | |
| 142 | [Fact] |
| 143 | public void CannotCompilePublicAndOverrideWithVirtualSymbol() |
| 144 | { |
| 145 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatePublicOverrideVirtualSymbol.wxs"); |
| 146 | WixAssert.CompareLineByLine(new[] |
| 147 | { |
| 148 | "ln 14: The Directory symbol 'TestFolder' conflicts with a virtual symbol. Use the 'override' access modifier to override the virtual symbol or use a different Id to avoid the conflict.", |
| 149 | "ln 10: Location of symbol related to previous error." |
| 150 | }, errors); |
| 151 | } |
| 152 | |
| 153 | private static string[] BuildForFailure(params string[] testSourceFilePaths) |
| 154 | { |
| 155 | var sourceFile = TestData.Get(testSourceFilePaths); |
| 156 | var sourceFolder = Path.GetDirectoryName(sourceFile); |
| 157 | |
| 158 | using (var fs = new DisposableFileSystem()) |
| 159 | { |
| 160 | var baseFolder = fs.GetFolder(); |
| 161 | var intermediateFolder = Path.Combine(baseFolder, "obj"); |
| 162 | var msiPath = Path.Combine(baseFolder, "bin", "test.msi"); |
| 163 | |
| 164 | var result = WixRunner.Execute(new[] |
| 165 | { |
| 166 | "build", |
| 167 | sourceFile, |
| 168 | "-intermediateFolder", intermediateFolder, |
| 169 | "-o", msiPath |
| 170 | }); |
| 171 | |
| 172 | return result.Messages.Where(m => m.Level == MessageLevel.Error) |
| 173 | .Select(m => $"ln {m.SourceLineNumbers.LineNumber}: {m}".Replace(sourceFolder, "<sourceFolder>").Replace(baseFolder, "<baseFolder>")) |
| 174 | .ToArray(); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | private static List<DirectorySymbol> BuildToGetDirectorySymbols(params string[] testSourceFilePaths) |
| 179 | { |
| 180 | var sourceFile = TestData.Get(testSourceFilePaths); |
| 181 | |
| 182 | using (var fs = new DisposableFileSystem()) |
| 183 | { |
| 184 | var baseFolder = fs.GetFolder(); |
| 185 | var intermediateFolder = Path.Combine(baseFolder, "obj"); |
| 186 | var msiPath = Path.Combine(baseFolder, "bin", "test.msi"); |
| 187 | |
| 188 | var result = WixRunner.Execute(new[] |
| 189 | { |
| 190 | "build", |
| 191 | sourceFile, |
| 192 | "-intermediateFolder", intermediateFolder, |
| 193 | "-o", msiPath |
| 194 | }); |
| 195 | |
| 196 | result.AssertSuccess(); |
| 197 | |
| 198 | var intermediate = Intermediate.Load(Path.Combine(baseFolder, "bin", "test.wixpdb")); |
| 199 | var section = intermediate.Sections.Single(); |
| 200 | |
| 201 | return section.Symbols.OfType<WixToolset.Data.Symbols.DirectorySymbol>().ToList(); |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |