| 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; |
| 6 | using System.IO; |
| 7 | using System.Linq; |
| 8 | using WixInternal.TestSupport; |
| 9 | using WixInternal.Core.TestPackage; |
| 10 | using WixToolset.Data; |
| 11 | using WixToolset.Data.Symbols; |
| 12 | using WixToolset.Data.WindowsInstaller; |
| 13 | using WixToolset.Data.WindowsInstaller.Rows; |
| 14 | using Xunit; |
| 15 | |
| 16 | public class MsiCabinetFixture |
| 17 | { |
| 18 | [Fact] |
| 19 | public void CanBuildSingleFileCompressed() |
| 20 | { |
| 21 | var folder = TestData.Get(@"TestData\SingleFileCompressed"); |
| 22 | |
| 23 | using (var fs = new DisposableFileSystem()) |
| 24 | { |
| 25 | var intermediateFolder = fs.GetFolder(); |
| 26 | |
| 27 | var result = WixRunner.Execute(new[] |
| 28 | { |
| 29 | "build", |
| 30 | Path.Combine(folder, "Package.wxs"), |
| 31 | Path.Combine(folder, "PackageComponents.wxs"), |
| 32 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), |
| 33 | "-bindpath", Path.Combine(folder, "data"), |
| 34 | "-intermediateFolder", intermediateFolder, |
| 35 | "-o", Path.Combine(intermediateFolder, @"bin\test.msi") |
| 36 | }); |
| 37 | |
| 38 | result.AssertSuccess(); |
| 39 | |
| 40 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); |
| 41 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\example.cab"))); |
| 42 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); |
| 43 | |
| 44 | var intermediate = Intermediate.Load(Path.Combine(intermediateFolder, @"bin\test.wixpdb")); |
| 45 | var section = intermediate.Sections.Single(); |
| 46 | |
| 47 | var fileSymbol = section.Symbols.OfType<FileSymbol>().Single(); |
| 48 | WixAssert.StringEqual(Path.Combine(folder, @"data\test.txt"), fileSymbol[FileSymbolFields.Source].AsPath().Path); |
| 49 | WixAssert.StringEqual(@"test.txt", fileSymbol[FileSymbolFields.Source].PreviousValue.AsPath().Path); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | [Fact] |
| 54 | public void CanBuildSingleFileCompressedWithMediaTemplate() |
| 55 | { |
| 56 | var folder = TestData.Get(@"TestData\SingleFileCompressed"); |
| 57 | |
| 58 | using (var fs = new DisposableFileSystem()) |
| 59 | { |
| 60 | var intermediateFolder = fs.GetFolder(); |
| 61 | |
| 62 | var result = WixRunner.Execute(new[] |
| 63 | { |
| 64 | "build", |
| 65 | Path.Combine(folder, "Package.wxs"), |
| 66 | Path.Combine(folder, "PackageComponents.wxs"), |
| 67 | "-d", "MediaTemplateCompressionLevel", |
| 68 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), |
| 69 | "-bindpath", Path.Combine(folder, "data"), |
| 70 | "-intermediateFolder", intermediateFolder, |
| 71 | "-o", Path.Combine(intermediateFolder, @"bin\test.msi") |
| 72 | }); |
| 73 | |
| 74 | result.AssertSuccess(); |
| 75 | |
| 76 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); |
| 77 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\cab1.cab"))); |
| 78 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | [Fact] |
| 83 | public void CanBuildSingleFileCompressedWithMediaTemplateWithLowCompression() |
| 84 | { |
| 85 | var folder = TestData.Get(@"TestData\SingleFileCompressed"); |
| 86 | |
| 87 | using (var fs = new DisposableFileSystem()) |
| 88 | { |
| 89 | var intermediateFolder = fs.GetFolder(); |
| 90 | |
| 91 | var result = WixRunner.Execute(new[] |
| 92 | { |
| 93 | "build", |
| 94 | Path.Combine(folder, "Package.wxs"), |
| 95 | Path.Combine(folder, "PackageComponents.wxs"), |
| 96 | "-d", "MediaTemplateCompressionLevel=low", |
| 97 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), |
| 98 | "-bindpath", Path.Combine(folder, "data"), |
| 99 | "-intermediateFolder", intermediateFolder, |
| 100 | "-o", Path.Combine(intermediateFolder, @"bin\test.msi") |
| 101 | }); |
| 102 | |
| 103 | result.AssertSuccess(); |
| 104 | |
| 105 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.msi"))); |
| 106 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\low1.cab"))); |
| 107 | Assert.True(File.Exists(Path.Combine(intermediateFolder, @"bin\test.wixpdb"))); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | [Fact] |
| 112 | public void CanBuildMultipleFilesCompressed() |
| 113 | { |
| 114 | var folder = TestData.Get(@"TestData\MultiFileCompressed"); |
| 115 | |
| 116 | using (var fs = new DisposableFileSystem()) |
| 117 | { |
| 118 | var intermediateFolder = fs.GetFolder(); |
| 119 | |
| 120 | var result = WixRunner.Execute(new[] |
| 121 | { |
| 122 | "build", |
| 123 | "-sw1079", // TODO: why does this test need to create a second cab which is empty? |
| 124 | Path.Combine(folder, "Package.wxs"), |
| 125 | Path.Combine(folder, "PackageComponents.wxs"), |
| 126 | "-loc", Path.Combine(folder, "Package.en-us.wxl"), |
| 127 | "-bindpath", Path.Combine(folder, "data"), |
| 128 | "-intermediateFolder", intermediateFolder, |
| 129 | "-o", Path.Combine(intermediateFolder, @"bin\test.msi") |
| 130 | }); |
| 131 | |
| 132 | result.AssertSuccess(); |
| 133 | |
| 134 | Assert.True(File.Exists(Path.Combine(intermediateFolder, "bin", "test.msi"))); |
| 135 | Assert.True(File.Exists(Path.Combine(intermediateFolder, "bin", "example1.cab"))); |
| 136 | Assert.True(File.Exists(Path.Combine(intermediateFolder, "bin", "example2.cab"))); |
| 137 | Assert.True(File.Exists(Path.Combine(intermediateFolder, "bin", "test.wixpdb"))); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | [Fact] |
| 142 | public void CanBuildMultipleFilesSpanningCabinets() |
| 143 | { |
| 144 | var folder = TestData.Get(@"TestData", "MsiCabinet"); |
| 145 | |
| 146 | using (var fs = new DisposableFileSystem()) |
| 147 | { |
| 148 | var baseFolder = fs.GetFolder(); |
| 149 | var dataFolder = Path.Combine(folder, "data"); |
| 150 | var gendataFolder = Path.Combine(baseFolder, "generated-data"); |
| 151 | var cabFolder = Path.Combine(baseFolder, "cab"); |
| 152 | var intermediateFolder = Path.Combine(baseFolder, "obj"); |
| 153 | var binFolder = Path.Combine(baseFolder, "bin"); |
| 154 | var msiPath = Path.Combine(binFolder, "test.msi"); |
| 155 | var wixpdbPath = Path.ChangeExtension(msiPath, "wixpdb"); |
| 156 | |
| 157 | TestData.CreateFile(Path.Combine(gendataFolder, "abc.gen"), (long)(25 * 1024 * 1024), fill: true); |
| 158 | TestData.CreateFile(Path.Combine(gendataFolder, "mno.gen"), (long)(45 * 1024 * 1024), fill: true); |
| 159 | TestData.CreateFile(Path.Combine(gendataFolder, "xyz.gen"), (long)(25 * 1024 * 1024), fill: true); |
| 160 | |
| 161 | var result = WixRunner.Execute(new[] |
| 162 | { |
| 163 | "build", |
| 164 | Path.Combine(folder, "MultiFileSpanningCabinets.wxs"), |
| 165 | "-bindpath", dataFolder, |
| 166 | "-bindpath", gendataFolder, |
| 167 | "-intermediateFolder", intermediateFolder, |
| 168 | "-cc", cabFolder, |
| 169 | "-o", msiPath |
| 170 | }); |
| 171 | |
| 172 | result.AssertSuccess(); |
| 173 | |
| 174 | var files = Directory.GetFiles(binFolder, "*.*", SearchOption.AllDirectories).Select(s => s.Substring(binFolder.Length + 1)).OrderBy(s => s).ToArray(); |
| 175 | WixAssert.CompareLineByLine(new[] |
| 176 | { |
| 177 | "cab1.cab", |
| 178 | "cab1a.cab", |
| 179 | "cab2.cab", |
| 180 | "cab3.cab", |
| 181 | "cab3a.cab", |
| 182 | "cab3b.cab", |
| 183 | "cab4.cab", |
| 184 | "cab5.cab", |
| 185 | "cab5a.cab", |
| 186 | "test.msi", |
| 187 | "test.wixpdb" |
| 188 | }, files); |
| 189 | |
| 190 | var query = Query.QueryDatabase(msiPath, new[] { "Media", "File" }); |
| 191 | WixAssert.CompareLineByLine(new[] |
| 192 | { |
| 193 | "File:fil2WOk5jeIBsvmL0db5z96JfeEZoU\tfil2WOk5jeIBsvmL0db5z96JfeEZoU\thij.txt\t18\t\t\t512\t3", |
| 194 | "File:filgErUV04C8ZBKWWWA0Zg5Fu_6NyM\tfilgErUV04C8ZBKWWWA0Zg5Fu_6NyM\tmno.gen\t47185920\t\t\t512\t4", |
| 195 | "File:filGqbzmUDXsQhijNpBL2rNX3dtCoo\tfilGqbzmUDXsQhijNpBL2rNX3dtCoo\tced.txt\t18\t\t\t512\t2", |
| 196 | "File:filj2uZN0Q5bCgR2YY6RRg1c9FqylQ\tfilj2uZN0Q5bCgR2YY6RRg1c9FqylQ\ttuv.txt\t18\t\t\t512\t6", |
| 197 | "File:filjEKfcIaBHXFyDRtZciPv4j105jQ\tfiljEKfcIaBHXFyDRtZciPv4j105jQ\tqrs.txt\t18\t\t\t512\t5", |
| 198 | "File:filKv93aSvdbL6M6UutiKdGim1UzcA\tfilKv93aSvdbL6M6UutiKdGim1UzcA\tabc.gen\t26214400\t\t\t512\t1", |
| 199 | "File:fillf1kS2G7fDKwbyrQIIw1OXPi.eY\tfillf1kS2G7fDKwbyrQIIw1OXPi.eY\txyz.gen\t26214400\t\t\t512\t7", |
| 200 | "Media:1\t1\t\tcab1.cab\t\t", |
| 201 | "Media:2\t1\t\tcab1a.cab\t\t", |
| 202 | "Media:3\t3\t\tcab2.cab\t\t", |
| 203 | "Media:4\t4\t\tcab3.cab\t\t", |
| 204 | "Media:5\t4\t\tcab3a.cab\t\t", |
| 205 | "Media:6\t4\t\tcab3b.cab\t\t", |
| 206 | "Media:7\t6\t\tcab4.cab\t\t", |
| 207 | "Media:8\t7\t\tcab5.cab\t\t", |
| 208 | "Media:9\t7\t\tcab5a.cab\t\t", |
| 209 | }, query); |
| 210 | |
| 211 | var wixpdb = WixOutput.Read(wixpdbPath); |
| 212 | |
| 213 | var data = WindowsInstallerData.Load(wixpdb); |
| 214 | var fileRows = data.Tables["File"].Rows.Cast<FileRow>().OrderBy(f => f.Sequence); |
| 215 | var mediaRows = data.Tables["Media"].Rows.Cast<MediaRow>().OrderBy(f => f.DiskId); |
| 216 | |
| 217 | var intermediate = Intermediate.Load(wixpdb); |
| 218 | var section = intermediate.Sections.Single(); |
| 219 | var fileSymbols = section.Symbols.OfType<FileSymbol>().OrderBy(f => f.Sequence); |
| 220 | var mediaSymbols = section.Symbols.OfType<MediaSymbol>().OrderBy(f => f.DiskId); |
| 221 | |
| 222 | var expectedFiles = new[] |
| 223 | { |
| 224 | "filKv93aSvdbL6M6UutiKdGim1UzcA abc.gen 1 1", |
| 225 | "filGqbzmUDXsQhijNpBL2rNX3dtCoo ced.txt 2 3", |
| 226 | "fil2WOk5jeIBsvmL0db5z96JfeEZoU hij.txt 3 3", |
| 227 | "filgErUV04C8ZBKWWWA0Zg5Fu_6NyM mno.gen 4 4", |
| 228 | "filjEKfcIaBHXFyDRtZciPv4j105jQ qrs.txt 5 7", |
| 229 | "filj2uZN0Q5bCgR2YY6RRg1c9FqylQ tuv.txt 6 7", |
| 230 | "fillf1kS2G7fDKwbyrQIIw1OXPi.eY xyz.gen 7 8", |
| 231 | }; |
| 232 | |
| 233 | var expectedMedia = new[] |
| 234 | { |
| 235 | "1 cab1.cab 1", |
| 236 | "2 cab1a.cab 1", |
| 237 | "3 cab2.cab 3", |
| 238 | "4 cab3.cab 4", |
| 239 | "5 cab3a.cab 4", |
| 240 | "6 cab3b.cab 4", |
| 241 | "7 cab4.cab 6", |
| 242 | "8 cab5.cab 7", |
| 243 | "9 cab5a.cab 7", |
| 244 | }; |
| 245 | |
| 246 | WixAssert.CompareLineByLine(expectedFiles, fileRows.Select(r => String.Join(" ", r.File, r.FileName, r.Sequence, r.DiskId)).ToArray()); |
| 247 | |
| 248 | WixAssert.CompareLineByLine(expectedFiles, fileSymbols.Select(s => String.Join(" ", s.Id.Id, s.Name, s.Sequence, s.DiskId)).ToArray()); |
| 249 | |
| 250 | WixAssert.CompareLineByLine(expectedMedia, mediaRows.Select(r => String.Join(" ", r.DiskId, r.Cabinet, r.LastSequence)).ToArray()); |
| 251 | |
| 252 | WixAssert.CompareLineByLine(expectedMedia, mediaSymbols.Select(s => String.Join(" ", s.DiskId, s.Cabinet, s.LastSequence)).ToArray()); |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | } |