aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/dtf/test')
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/CabTest.cs1165
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/WixToolsetTests.Dtf.Compression.Cab.csproj43
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/WixToolsetTests.Dtf.Compression.Zip.csproj41
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/ZipTest.cs518
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression/CompressionTestUtil.cs649
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression/MisbehavingStreamContext.cs202
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression/OptionStreamContext.cs42
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.Compression/WixToolsetTests.Dtf.Compression.csproj36
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/CustomActionTest.cs206
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/WixToolsetTests.Dtf.WindowsInstaller.CustomActions.csproj32
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/LinqTest.cs509
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/WixToolsetTests.Dtf.WindowsInstaller.Linq.csproj42
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/EmbeddedExternalUI.cs173
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/Schema.cs238
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTest.cs409
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTransactions.cs161
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerUtils.cs174
-rw-r--r--src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WixToolsetTests.Dtf.WindowsInstaller.csproj39
18 files changed, 4679 insertions, 0 deletions
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/CabTest.cs b/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/CabTest.cs
new file mode 100644
index 00000000..981ecc69
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/CabTest.cs
@@ -0,0 +1,1165 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Text;
8 using System.Threading;
9 using System.Collections.Generic;
10 using System.Runtime.Serialization;
11 using System.Runtime.Serialization.Formatters.Binary;
12 using Microsoft.VisualStudio.TestTools.UnitTesting;
13 using WixToolset.Dtf.Compression;
14 using WixToolset.Dtf.Compression.Cab;
15
16 [TestClass]
17 public class CabTest
18 {
19 public CabTest()
20 {
21 }
22
23 [TestInitialize]
24 public void Initialize()
25 {
26 }
27
28 [TestCleanup]
29 public void Cleanup()
30 {
31 }
32
33 [TestMethod]
34 public void CabinetMultithread()
35 {
36 this.multithreadExceptions = new List<Exception>();
37
38 const int threadCount = 10;
39 IList<Thread> threads = new List<Thread>(threadCount);
40
41 for (int i = 0; i < threadCount; i++)
42 {
43 Thread thread = new Thread(new ThreadStart(this.CabinetMultithreadWorker));
44 thread.Name = "CabinetMultithreadWorker_" + i;
45 threads.Add(thread);
46 }
47
48 foreach (Thread thread in threads)
49 {
50 thread.Start();
51 }
52
53 foreach (Thread thread in threads)
54 {
55 thread.Join();
56 }
57
58 foreach (Exception ex in this.multithreadExceptions)
59 {
60 Console.WriteLine();
61 Console.WriteLine(ex);
62 }
63 Assert.AreEqual<int>(0, this.multithreadExceptions.Count);
64 }
65
66 private IList<Exception> multithreadExceptions;
67
68 private void CabinetMultithreadWorker()
69 {
70 try
71 {
72 string threadName = Thread.CurrentThread.Name;
73 int threadNumber = Int32.Parse(threadName.Substring(threadName.IndexOf('_') + 1));
74 this.RunCabinetPackUnpack(100, 10240 + threadNumber, 0, 0, CompressionLevel.Normal);
75 }
76 catch (Exception ex)
77 {
78 this.multithreadExceptions.Add(ex);
79 }
80 }
81
82 [TestMethod]
83 public void CabinetFileCounts()
84 {
85 this.RunCabinetPackUnpack(0, 10, 0, 0, CompressionLevel.Normal);
86 this.RunCabinetPackUnpack(1, 10, 0, 0, CompressionLevel.Normal);
87 this.RunCabinetPackUnpack(100, 10, 0, 0, CompressionLevel.Normal);
88 }
89
90 [TestMethod]
91 [Ignore] // Takes ~5 minutes and 66000 is over the 65535 limit anyway.
92 public void CabinetExtremeFileCounts()
93 {
94 this.RunCabinetPackUnpack(66000, 10);
95 }
96
97 [TestMethod]
98 public void CabinetFileSizes()
99 {
100 this.RunCabinetPackUnpack(1, 0, 0, 0, CompressionLevel.Normal);
101 this.RunCabinetPackUnpack(1, 1, 0, 0, CompressionLevel.Normal);
102 this.RunCabinetPackUnpack(1, 2, 0, 0, CompressionLevel.Normal);
103 this.RunCabinetPackUnpack(1, 3, 0, 0, CompressionLevel.Normal);
104 this.RunCabinetPackUnpack(1, 4, 0, 0, CompressionLevel.Normal);
105 this.RunCabinetPackUnpack(1, 5, 0, 0, CompressionLevel.Normal);
106 this.RunCabinetPackUnpack(1, 6, 0, 0, CompressionLevel.Normal);
107 // Skip file sizes 7-9: see "buggy" file sizes test below.
108 this.RunCabinetPackUnpack(1, 10, 0, 0, CompressionLevel.Normal);
109 this.RunCabinetPackUnpack(1, 11, 0, 0, CompressionLevel.Normal);
110 this.RunCabinetPackUnpack(1, 12, 0, 0, CompressionLevel.Normal);
111 this.RunCabinetPackUnpack(1, 100 * 1024, 0, 0, CompressionLevel.Normal);
112 this.RunCabinetPackUnpack(1, 10 * 1024 * 1024, 0, 0, CompressionLevel.Normal);
113 }
114
115 [TestMethod]
116 public void CabinetBuggyFileSizes()
117 {
118 // Windows' cabinet.dll has a known bug (#55001 in Windows OS Bugs)
119 // LZX compression causes an AV with file sizes of 7, 8, or 9 bytes.
120 try
121 {
122 this.RunCabinetPackUnpack(1, 7, 0, 0, CompressionLevel.Normal);
123 this.RunCabinetPackUnpack(1, 8, 0, 0, CompressionLevel.Normal);
124 this.RunCabinetPackUnpack(1, 9, 0, 0, CompressionLevel.Normal);
125 }
126 catch (AccessViolationException)
127 {
128 Assert.Fail("Known 7,8,9 file size bug detected in Windows' cabinet.dll.");
129 }
130 }
131
132 [Timeout(36000000), TestMethod]
133 [Ignore] // Takes too long to run regularly.
134 public void CabinetExtremeFileSizes()
135 {
136 this.RunCabinetPackUnpack(10, 512L * 1024 * 1024); // 5GB
137 //this.RunCabinetPackUnpack(1, 5L * 1024 * 1024 * 1024); // 5GB
138 }
139
140 [TestMethod]
141 public void CabinetFolders()
142 {
143 this.RunCabinetPackUnpack(0, 10, 1, 0, CompressionLevel.Normal);
144 this.RunCabinetPackUnpack(1, 10, 1, 0, CompressionLevel.Normal);
145 this.RunCabinetPackUnpack(100, 10, 1, 0, CompressionLevel.Normal);
146
147 IList<ArchiveFileInfo> fileInfo;
148 fileInfo = this.RunCabinetPackUnpack(7, 100 * 1024, 250 * 1024, 0, CompressionLevel.None);
149 Assert.AreEqual<int>(2, ((CabFileInfo) fileInfo[fileInfo.Count - 1]).CabinetFolderNumber,
150 "Testing whether cabinet has the correct # of folders.");
151
152 fileInfo = this.RunCabinetPackUnpack(10, 100 * 1024, 250 * 1024, 0, CompressionLevel.None);
153 Assert.AreEqual<int>(3, ((CabFileInfo) fileInfo[fileInfo.Count - 1]).CabinetFolderNumber,
154 "Testing whether cabinet has the correct # of folders.");
155
156 fileInfo = this.RunCabinetPackUnpack(2, 100 * 1024, 40 * 1024, 0, CompressionLevel.None);
157 Assert.AreEqual<int>(1, ((CabFileInfo) fileInfo[fileInfo.Count - 1]).CabinetFolderNumber,
158 "Testing whether cabinet has the correct # of folders.");
159 }
160
161 [TestMethod]
162 public void CabinetArchiveCounts()
163 {
164 IList<ArchiveFileInfo> fileInfo;
165 fileInfo = this.RunCabinetPackUnpack(10, 100 * 1024, 0, 400 * 1024, CompressionLevel.None);
166 Assert.AreEqual<int>(2, fileInfo[fileInfo.Count - 1].ArchiveNumber,
167 "Testing whether archive spans the correct # of cab files.");
168
169 fileInfo = this.RunCabinetPackUnpack(2, 90 * 1024, 0, 40 * 1024, CompressionLevel.None);
170 Assert.AreEqual<int>(2, fileInfo[fileInfo.Count - 1].ArchiveNumber,
171 "Testing whether archive spans the correct # of cab files.");
172 }
173
174 [TestMethod]
175 public void CabinetProgress()
176 {
177 CompressionTestUtil.ExpectedProgress = new List<int[]>(new int[][] {
178 // StatusType, CurFile,TotalFiles,CurFolder,CurCab,TotalCabs
179 new int[] { (int) ArchiveProgressType.StartFile, 0, 15, 0, 0, 1 },
180 new int[] { (int) ArchiveProgressType.FinishFile, 0, 15, 0, 0, 1 },
181 new int[] { (int) ArchiveProgressType.StartFile, 1, 15, 0, 0, 1 },
182 new int[] { (int) ArchiveProgressType.FinishFile, 1, 15, 0, 0, 1 },
183 new int[] { (int) ArchiveProgressType.StartFile, 2, 15, 1, 0, 1 },
184 new int[] { (int) ArchiveProgressType.FinishFile, 2, 15, 1, 0, 1 },
185 new int[] { (int) ArchiveProgressType.StartFile, 3, 15, 1, 0, 1 },
186 new int[] { (int) ArchiveProgressType.FinishFile, 3, 15, 1, 0, 1 },
187 new int[] { (int) ArchiveProgressType.StartFile, 4, 15, 2, 0, 1 },
188 new int[] { (int) ArchiveProgressType.FinishFile, 4, 15, 2, 0, 1 },
189 new int[] { (int) ArchiveProgressType.StartFile, 5, 15, 2, 0, 1 },
190 new int[] { (int) ArchiveProgressType.FinishFile, 5, 15, 2, 0, 1 },
191 new int[] { (int) ArchiveProgressType.StartFile, 6, 15, 3, 0, 1 },
192 new int[] { (int) ArchiveProgressType.FinishFile, 6, 15, 3, 0, 1 },
193 new int[] { (int) ArchiveProgressType.StartFile, 7, 15, 3, 0, 1 },
194 new int[] { (int) ArchiveProgressType.FinishFile, 7, 15, 3, 0, 1 },
195 new int[] { (int) ArchiveProgressType.StartArchive, 7, 15, 3, 0, 1 },
196 new int[] { (int) ArchiveProgressType.FinishArchive, 7, 15, 3, 0, 1 },
197 new int[] { (int) ArchiveProgressType.StartFile, 8, 15, 4, 1, 2 },
198 new int[] { (int) ArchiveProgressType.FinishFile, 8, 15, 4, 1, 2 },
199 new int[] { (int) ArchiveProgressType.StartFile, 9, 15, 4, 1, 2 },
200 new int[] { (int) ArchiveProgressType.FinishFile, 9, 15, 4, 1, 2 },
201 new int[] { (int) ArchiveProgressType.StartFile, 10, 15, 5, 1, 2 },
202 new int[] { (int) ArchiveProgressType.FinishFile, 10, 15, 5, 1, 2 },
203 new int[] { (int) ArchiveProgressType.StartFile, 11, 15, 5, 1, 2 },
204 new int[] { (int) ArchiveProgressType.FinishFile, 11, 15, 5, 1, 2 },
205 new int[] { (int) ArchiveProgressType.StartFile, 12, 15, 6, 1, 2 },
206 new int[] { (int) ArchiveProgressType.FinishFile, 12, 15, 6, 1, 2 },
207 new int[] { (int) ArchiveProgressType.StartFile, 13, 15, 6, 1, 2 },
208 new int[] { (int) ArchiveProgressType.FinishFile, 13, 15, 6, 1, 2 },
209 new int[] { (int) ArchiveProgressType.StartArchive, 13, 15, 6, 1, 2 },
210 new int[] { (int) ArchiveProgressType.FinishArchive, 13, 15, 6, 1, 2 },
211 new int[] { (int) ArchiveProgressType.StartFile, 14, 15, 7, 2, 3 },
212 new int[] { (int) ArchiveProgressType.FinishFile, 14, 15, 7, 2, 3 },
213 new int[] { (int) ArchiveProgressType.StartArchive, 14, 15, 7, 2, 3 },
214 new int[] { (int) ArchiveProgressType.FinishArchive, 14, 15, 7, 2, 3 },
215 // StatusType, CurFile,TotalFiles,CurFolder,CurCab,TotalCabs
216 new int[] { (int) ArchiveProgressType.StartArchive, 0, 15, 0, 0, 3 },
217 new int[] { (int) ArchiveProgressType.StartFile, 0, 15, 0, 0, 3 },
218 new int[] { (int) ArchiveProgressType.FinishFile, 0, 15, 0, 0, 3 },
219 new int[] { (int) ArchiveProgressType.StartFile, 1, 15, 0, 0, 3 },
220 new int[] { (int) ArchiveProgressType.FinishFile, 1, 15, 0, 0, 3 },
221 new int[] { (int) ArchiveProgressType.StartFile, 2, 15, 1, 0, 3 },
222 new int[] { (int) ArchiveProgressType.FinishFile, 2, 15, 1, 0, 3 },
223 new int[] { (int) ArchiveProgressType.StartFile, 3, 15, 1, 0, 3 },
224 new int[] { (int) ArchiveProgressType.FinishFile, 3, 15, 1, 0, 3 },
225 new int[] { (int) ArchiveProgressType.StartFile, 4, 15, 2, 0, 3 },
226 new int[] { (int) ArchiveProgressType.FinishFile, 4, 15, 2, 0, 3 },
227 new int[] { (int) ArchiveProgressType.StartFile, 5, 15, 2, 0, 3 },
228 new int[] { (int) ArchiveProgressType.FinishFile, 5, 15, 2, 0, 3 },
229 new int[] { (int) ArchiveProgressType.StartFile, 6, 15, 3, 0, 3 },
230 new int[] { (int) ArchiveProgressType.FinishArchive, 6, 15, 3, 0, 3 },
231 new int[] { (int) ArchiveProgressType.StartArchive, 6, 15, 3, 1, 3 },
232 new int[] { (int) ArchiveProgressType.FinishFile, 6, 15, 3, 1, 3 },
233 new int[] { (int) ArchiveProgressType.StartFile, 7, 15, 3, 1, 3 },
234 new int[] { (int) ArchiveProgressType.FinishFile, 7, 15, 3, 1, 3 },
235 new int[] { (int) ArchiveProgressType.StartFile, 8, 15, 4, 1, 3 },
236 new int[] { (int) ArchiveProgressType.FinishFile, 8, 15, 4, 1, 3 },
237 new int[] { (int) ArchiveProgressType.StartFile, 9, 15, 4, 1, 3 },
238 new int[] { (int) ArchiveProgressType.FinishFile, 9, 15, 4, 1, 3 },
239 new int[] { (int) ArchiveProgressType.StartFile, 10, 15, 5, 1, 3 },
240 new int[] { (int) ArchiveProgressType.FinishFile, 10, 15, 5, 1, 3 },
241 new int[] { (int) ArchiveProgressType.StartFile, 11, 15, 5, 1, 3 },
242 new int[] { (int) ArchiveProgressType.FinishFile, 11, 15, 5, 1, 3 },
243 new int[] { (int) ArchiveProgressType.StartFile, 12, 15, 6, 1, 3 },
244 new int[] { (int) ArchiveProgressType.FinishArchive, 12, 15, 6, 1, 3 },
245 new int[] { (int) ArchiveProgressType.StartArchive, 12, 15, 6, 2, 3 },
246 new int[] { (int) ArchiveProgressType.FinishFile, 12, 15, 6, 2, 3 },
247 new int[] { (int) ArchiveProgressType.StartFile, 13, 15, 6, 2, 3 },
248 new int[] { (int) ArchiveProgressType.FinishFile, 13, 15, 6, 2, 3 },
249 new int[] { (int) ArchiveProgressType.StartFile, 14, 15, 7, 2, 3 },
250 new int[] { (int) ArchiveProgressType.FinishFile, 14, 15, 7, 2, 3 },
251 new int[] { (int) ArchiveProgressType.FinishArchive, 14, 15, 7, 2, 3 },
252 });
253
254 try
255 {
256 this.RunCabinetPackUnpack(15, 20 * 1024, 1 * 1024, 130 * 1024, CompressionLevel.None);
257 }
258 finally
259 {
260 CompressionTestUtil.ExpectedProgress = null;
261 }
262 }
263
264 [TestMethod]
265 public void CabArchiveSizeParam()
266 {
267 Console.WriteLine("Testing various values for the maxArchiveSize parameter.");
268 this.RunCabinetPackUnpack(5, 1024, 0, Int64.MinValue);
269 this.RunCabinetPackUnpack(5, 1024, 0, -1);
270 this.RunCabinetPackUnpack(5, 10, 0, 2);
271 this.RunCabinetPackUnpack(5, 100, 0, 256);
272 this.RunCabinetPackUnpack(5, 24000, 0, 32768);
273 this.RunCabinetPackUnpack(5, 1024, 0, Int64.MaxValue);
274 }
275
276 [TestMethod]
277 public void CabFolderSizeParam()
278 {
279 Console.WriteLine("Testing various values for the maxFolderSize parameter.");
280 this.RunCabinetPackUnpack(5, 10, Int64.MinValue, 0);
281 this.RunCabinetPackUnpack(5, 10, -1, 0);
282 this.RunCabinetPackUnpack(5, 10, 2, 0);
283 this.RunCabinetPackUnpack(5, 10, 16, 0);
284 this.RunCabinetPackUnpack(5, 10, 100, 0);
285 this.RunCabinetPackUnpack(5, 10, Int64.MaxValue, 0);
286 }
287
288 [TestMethod]
289 public void CabCompLevelParam()
290 {
291 Console.WriteLine("Testing various values for the compressionLevel parameter.");
292 this.RunCabinetPackUnpack(5, 1024, 0, 0, CompressionLevel.None);
293 this.RunCabinetPackUnpack(5, 1024, 0, 0, CompressionLevel.Min);
294 this.RunCabinetPackUnpack(5, 1024, 0, 0, CompressionLevel.Normal);
295 this.RunCabinetPackUnpack(5, 1024, 0, 0, CompressionLevel.Max);
296 this.RunCabinetPackUnpack(5, 1024, 0, 0, (CompressionLevel) ((int) CompressionLevel.None - 1));
297 this.RunCabinetPackUnpack(5, 1024, 0, 0, (CompressionLevel) ((int) CompressionLevel.Max + 1));
298 this.RunCabinetPackUnpack(5, 1024, 0, 0, (CompressionLevel) Int32.MinValue);
299 this.RunCabinetPackUnpack(5, 1024, 0, 0, (CompressionLevel) Int32.MaxValue);
300 }
301
302 [TestMethod]
303 public void CabEngineNullParams()
304 {
305 string[] testFiles = new string[] { "test.txt" };
306 ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext("test.cab", null, null);
307
308 using (CabEngine cabEngine = new CabEngine())
309 {
310 cabEngine.CompressionLevel = CompressionLevel.None;
311
312 CompressionTestUtil.TestCompressionEngineNullParams(
313 cabEngine, streamContext, testFiles);
314 }
315 }
316
317 [TestMethod]
318 public void CabBadPackStreamContexts()
319 {
320 string[] testFiles = new string[] { "test.txt" };
321 CompressionTestUtil.GenerateRandomFile(testFiles[0], 0, 20000);
322
323 using (CabEngine cabEngine = new CabEngine())
324 {
325 cabEngine.CompressionLevel = CompressionLevel.None;
326
327 CompressionTestUtil.TestBadPackStreamContexts(cabEngine, "test.cab", testFiles);
328 }
329 }
330
331 [TestMethod]
332 public void CabEngineNoTempFileTest()
333 {
334 int txtSize = 10240;
335 CompressionTestUtil.GenerateRandomFile("testnotemp.txt", 0, txtSize);
336
337 ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext("testnotemp.cab", null, null);
338
339 using (CabEngine cabEngine = new CabEngine())
340 {
341 cabEngine.UseTempFiles = false;
342 cabEngine.Pack(streamContext, new string[] { "testnotemp.txt" });
343 }
344
345 new CabInfo("testnotemp.cab").UnpackFile("testnotemp.txt", "testnotemp2.txt");
346 Assert.AreEqual(txtSize, new FileInfo("testnotemp2.txt").Length);
347 }
348
349 [TestMethod]
350 public void CabExtractorIsCabinet()
351 {
352 int txtSize = 10240;
353 CompressionTestUtil.GenerateRandomFile("test.txt", 0, txtSize);
354 new CabInfo("test.cab").PackFiles(null, new string[] { "test.txt" }, null);
355 using (CabEngine cabEngine = new CabEngine())
356 {
357 bool isCab;
358 using (Stream fileStream = File.OpenRead("test.txt"))
359 {
360 isCab = cabEngine.IsArchive(fileStream);
361 }
362 Assert.IsFalse(isCab);
363 using (Stream cabStream = File.OpenRead("test.cab"))
364 {
365 isCab = cabEngine.IsArchive(cabStream);
366 }
367 Assert.IsTrue(isCab);
368 using (Stream cabStream = File.OpenRead("test.cab"))
369 {
370 using (Stream fileStream = new FileStream("test.txt", FileMode.Open, FileAccess.ReadWrite))
371 {
372 fileStream.Seek(0, SeekOrigin.End);
373 byte[] buf = new byte[1024];
374 int count;
375 while ((count = cabStream.Read(buf, 0, buf.Length)) > 0)
376 {
377 fileStream.Write(buf, 0, count);
378 }
379 fileStream.Seek(0, SeekOrigin.Begin);
380 isCab = cabEngine.IsArchive(fileStream);
381 }
382 }
383 Assert.IsFalse(isCab);
384 using (Stream fileStream = new FileStream("test.txt", FileMode.Open, FileAccess.ReadWrite))
385 {
386 fileStream.Write(new byte[] { (byte) 'M', (byte) 'S', (byte) 'C', (byte) 'F' }, 0, 4);
387 fileStream.Seek(0, SeekOrigin.Begin);
388 isCab = cabEngine.IsArchive(fileStream);
389 }
390 Assert.IsFalse(isCab);
391 }
392 }
393
394 [TestMethod]
395 public void CabExtractorFindOffset()
396 {
397 int txtSize = 10240;
398 CompressionTestUtil.GenerateRandomFile("test.txt", 0, txtSize);
399 new CabInfo("test.cab").PackFiles(null, new string[] { "test.txt" }, null);
400 using (CabEngine cabEngine = new CabEngine())
401 {
402 long offset;
403 using (Stream fileStream = File.OpenRead("test.txt"))
404 {
405 offset = cabEngine.FindArchiveOffset(fileStream);
406 }
407 Assert.AreEqual<long>(-1, offset);
408 using (Stream cabStream = File.OpenRead("test.cab"))
409 {
410 using (Stream fileStream = new FileStream("test.txt", FileMode.Open, FileAccess.ReadWrite))
411 {
412 fileStream.Seek(0, SeekOrigin.End);
413 byte[] buf = new byte[1024];
414 int count;
415 while ((count = cabStream.Read(buf, 0, buf.Length)) > 0)
416 {
417 fileStream.Write(buf, 0, count);
418 }
419 fileStream.Seek(0, SeekOrigin.Begin);
420 offset = cabEngine.FindArchiveOffset(fileStream);
421 }
422 }
423 Assert.AreEqual<long>(txtSize, offset);
424 }
425 }
426
427 [TestMethod]
428 public void CabExtractorGetFiles()
429 {
430 IList<ArchiveFileInfo> fileInfo;
431 CabInfo cabInfo = new CabInfo("testgetfiles.cab");
432 int txtSize = 10240;
433 CompressionTestUtil.GenerateRandomFile("testgetfiles0.txt", 0, txtSize);
434 CompressionTestUtil.GenerateRandomFile("testgetfiles1.txt", 1, txtSize);
435 cabInfo.PackFiles(null, new string[] { "testgetfiles0.txt", "testgetfiles1.txt" }, null);
436 using (CabEngine cabEngine = new CabEngine())
437 {
438 IList<string> files;
439 using (Stream cabStream = File.OpenRead("testgetfiles.cab"))
440 {
441 files = cabEngine.GetFiles(cabStream);
442 }
443 Assert.IsNotNull(files);
444 Assert.AreEqual<int>(2, files.Count);
445 Assert.AreEqual<string>("testgetfiles0.txt", files[0]);
446 Assert.AreEqual<string>("testgetfiles1.txt", files[1]);
447
448 using (Stream cabStream = File.OpenRead("testgetfiles.cab"))
449 {
450 files = cabEngine.GetFiles(new ArchiveFileStreamContext("testgetfiles.cab"), null);
451 }
452 Assert.IsNotNull(files);
453 Assert.AreEqual<int>(2, files.Count);
454 Assert.AreEqual<string>("testgetfiles0.txt", files[0]);
455 Assert.AreEqual<string>("testgetfiles1.txt", files[1]);
456
457 using (Stream cabStream = File.OpenRead("testgetfiles.cab"))
458 {
459 fileInfo = cabEngine.GetFileInfo(cabStream);
460 }
461 Assert.IsNotNull(fileInfo);
462 Assert.AreEqual<int>(2, fileInfo.Count);
463 Assert.AreEqual<string>("testgetfiles0.txt", fileInfo[0].Name);
464 Assert.AreEqual<string>("testgetfiles1.txt", fileInfo[1].Name);
465 using (Stream cabStream = File.OpenRead("testgetfiles.cab"))
466 {
467 fileInfo = cabEngine.GetFileInfo(new ArchiveFileStreamContext("testgetfiles.cab"), null);
468 }
469 Assert.IsNotNull(fileInfo);
470 Assert.AreEqual<int>(2, fileInfo.Count);
471 Assert.AreEqual<string>("testgetfiles0.txt", fileInfo[0].Name);
472 Assert.AreEqual<string>("testgetfiles1.txt", fileInfo[1].Name);
473 }
474
475 fileInfo = this.RunCabinetPackUnpack(15, 20 * 1024, 1 * 1024, 130 * 1024);
476 Assert.IsNotNull(fileInfo);
477 Assert.AreEqual<int>(15, fileInfo.Count);
478 for (int i = 0; i < fileInfo.Count; i++)
479 {
480 Assert.IsNull(fileInfo[i].Archive);
481 Assert.AreEqual<string>(TEST_FILENAME_PREFIX + i + ".txt", fileInfo[i].Name);
482 Assert.IsTrue(DateTime.Now - fileInfo[i].LastWriteTime < new TimeSpan(0, 1, 0));
483 }
484 }
485
486 [TestMethod]
487 public void CabExtractorExtract()
488 {
489 int txtSize = 40960;
490 CabInfo cabInfo = new CabInfo("test.cab");
491 CompressionTestUtil.GenerateRandomFile("test0.txt", 0, txtSize);
492 CompressionTestUtil.GenerateRandomFile("test1.txt", 1, txtSize);
493 cabInfo.PackFiles(null, new string[] { "test0.txt", "test1.txt" }, null);
494 using (CabEngine cabEngine = new CabEngine())
495 {
496 using (Stream cabStream = File.OpenRead("test.cab"))
497 {
498 using (Stream exStream = cabEngine.Unpack(cabStream, "test0.txt"))
499 {
500 string str = new StreamReader(exStream).ReadToEnd();
501 string expected = new StreamReader("test0.txt").ReadToEnd();
502 Assert.AreEqual<string>(expected, str);
503 }
504 cabStream.Seek(0, SeekOrigin.Begin);
505 using (Stream exStream = cabEngine.Unpack(cabStream, "test1.txt"))
506 {
507 string str = new StreamReader(exStream).ReadToEnd();
508 string expected = new StreamReader("test1.txt").ReadToEnd();
509 Assert.AreEqual<string>(expected, str);
510 }
511 }
512 using (Stream txtStream = File.OpenRead("test0.txt"))
513 {
514 Exception caughtEx = null;
515 try
516 {
517 cabEngine.Unpack(txtStream, "test0.txt");
518 }
519 catch (Exception ex) { caughtEx = ex; }
520 Assert.IsInstanceOfType(caughtEx, typeof(CabException));
521 Assert.AreEqual<int>(2, ((CabException) caughtEx).Error);
522 Assert.AreEqual<int>(0, ((CabException) caughtEx).ErrorCode);
523 Assert.AreEqual<string>("Cabinet file does not have the correct format.", caughtEx.Message);
524 }
525 }
526 }
527
528 [TestMethod]
529 public void CabBadUnpackStreamContexts()
530 {
531 int txtSize = 40960;
532 CabInfo cabInfo = new CabInfo("test2.cab");
533 CompressionTestUtil.GenerateRandomFile("cabtest-0.txt", 0, txtSize);
534 CompressionTestUtil.GenerateRandomFile("cabtest-1.txt", 1, txtSize);
535 cabInfo.PackFiles(null, new string[] { "cabtest-0.txt", "cabtest-1.txt" }, null);
536
537 using (CabEngine cabEngine = new CabEngine())
538 {
539 CompressionTestUtil.TestBadUnpackStreamContexts(cabEngine, "test2.cab");
540 }
541 }
542
543 [TestMethod]
544 public void CabinetExtractUpdate()
545 {
546 int fileCount = 5, fileSize = 2048;
547 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
548 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
549 Directory.CreateDirectory(dirA);
550 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
551 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
552 Directory.CreateDirectory(dirB);
553
554 string[] files = new string[fileCount];
555 for (int iFile = 0; iFile < fileCount; iFile++)
556 {
557 files[iFile] = "€" + iFile + ".txt";
558 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
559 }
560
561 CabInfo cabInfo = new CabInfo("testupdate.cab");
562 cabInfo.Pack(dirA);
563 cabInfo.Unpack(dirB);
564
565 DateTime originalTime = File.GetLastWriteTime(Path.Combine(dirA, "€1.txt"));
566 DateTime pastTime = originalTime - new TimeSpan(0, 5, 0);
567 DateTime futureTime = originalTime + new TimeSpan(0, 5, 0);
568
569 using (CabEngine cabEngine = new CabEngine())
570 {
571 string cabName = "testupdate.cab";
572 ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext(cabName, dirB, null);
573 streamContext.ExtractOnlyNewerFiles = true;
574
575 Assert.AreEqual<bool>(true, streamContext.ExtractOnlyNewerFiles);
576 Assert.IsNotNull(streamContext.ArchiveFiles);
577 Assert.AreEqual<int>(1, streamContext.ArchiveFiles.Count);
578 Assert.AreEqual<string>(cabName, streamContext.ArchiveFiles[0]);
579 Assert.AreEqual<string>(dirB, streamContext.Directory);
580
581 File.SetLastWriteTime(Path.Combine(dirB, "€1.txt"), futureTime);
582 cabEngine.Unpack(streamContext, null);
583 Assert.IsTrue(File.GetLastWriteTime(Path.Combine(dirB, "€1.txt")) - originalTime > new TimeSpan(0, 4, 55));
584
585 File.SetLastWriteTime(Path.Combine(dirB, "€1.txt"), pastTime);
586 File.SetLastWriteTime(Path.Combine(dirB, "€2.txt"), pastTime);
587 File.SetAttributes(Path.Combine(dirB, "€2.txt"), FileAttributes.ReadOnly);
588 File.SetAttributes(Path.Combine(dirB, "€2.txt"), FileAttributes.Hidden);
589 File.SetAttributes(Path.Combine(dirB, "€2.txt"), FileAttributes.System);
590
591 cabEngine.Unpack(streamContext, null);
592 Assert.IsTrue((File.GetLastWriteTime(Path.Combine(dirB, "€1.txt")) - originalTime).Duration() < new TimeSpan(0, 0, 5));
593
594 // Just test the rest of the streamContext properties here.
595 IDictionary<string, string> testMap = new Dictionary<string, string>();
596 streamContext = new ArchiveFileStreamContext(cabName, dirB, testMap);
597 Assert.AreSame(testMap, streamContext.Files);
598
599 Assert.IsFalse(streamContext.EnableOffsetOpen);
600 streamContext.EnableOffsetOpen = true;
601 Assert.IsTrue(streamContext.EnableOffsetOpen);
602 streamContext = new ArchiveFileStreamContext(cabName, ".", testMap);
603 Assert.AreEqual<string>(".", streamContext.Directory);
604 string[] testArchiveFiles = new string[] { cabName };
605 streamContext = new ArchiveFileStreamContext(testArchiveFiles, ".", testMap);
606 Assert.AreSame(testArchiveFiles, streamContext.ArchiveFiles);
607 }
608 }
609
610 [TestMethod]
611 public void CabinetOffset()
612 {
613 int txtSize = 10240;
614 CompressionTestUtil.GenerateRandomFile("test.txt", 0, txtSize);
615 CompressionTestUtil.GenerateRandomFile("base.txt", 1, 2 * txtSize + 4);
616
617 ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext("base.txt", null, null);
618 streamContext.EnableOffsetOpen = true;
619
620 using (CabEngine cabEngine = new CabEngine())
621 {
622 cabEngine.Pack(streamContext, new string[] { "test.txt" });
623 }
624
625 Assert.IsTrue(new FileInfo("base.txt").Length > 2 * txtSize + 4);
626
627 string saveText;
628 using (Stream txtStream = File.OpenRead("test.txt"))
629 {
630 saveText = new StreamReader(txtStream).ReadToEnd();
631 }
632 File.Delete("test.txt");
633
634 using (CabEngine cex = new CabEngine())
635 {
636 cex.Unpack(streamContext, null);
637 }
638 string testText;
639 using (Stream txtStream = File.OpenRead("test.txt"))
640 {
641 testText = new StreamReader(txtStream).ReadToEnd();
642 }
643 Assert.AreEqual<string>(saveText, testText);
644 }
645
646 [TestMethod]
647 public void CabinetUtfPaths()
648 {
649 string[] files = new string[]
650 {
651 "어그리먼트送信ポート1ßà_Agreement.txt",
652 "콘토소ßà_MyProfile.txt",
653 "파트너1ßà_PartnerProfile.txt",
654 };
655
656 string dirA = "utf8-A";
657 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
658 Directory.CreateDirectory(dirA);
659 string dirB = "utf8-B";
660 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
661 Directory.CreateDirectory(dirB);
662
663 int txtSize = 1024;
664 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[0]), 0, txtSize);
665 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[1]), 1, txtSize);
666 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[2]), 2, txtSize);
667
668 ArchiveFileStreamContext streamContextA = new ArchiveFileStreamContext("utf8.cab", dirA, null);
669 using (CabEngine cabEngine = new CabEngine())
670 {
671 cabEngine.Pack(streamContextA, files);
672 }
673
674 ArchiveFileStreamContext streamContextB = new ArchiveFileStreamContext("utf8.cab", dirB, null);
675 using (CabEngine cex = new CabEngine())
676 {
677 cex.Unpack(streamContextB, null);
678 }
679
680 bool directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
681 Assert.IsTrue(directoryMatch,
682 "Testing whether cabinet output directory matches input directory.");
683 }
684
685 [TestMethod]
686 //[Ignore] // Requires clean environment.
687 public void CabInfoProperties()
688 {
689 Exception caughtEx;
690 CabInfo cabInfo = new CabInfo("test.cab");
691 int txtSize = 10240;
692 CompressionTestUtil.GenerateRandomFile("test00.txt", 0, txtSize);
693 CompressionTestUtil.GenerateRandomFile("test01.txt", 1, txtSize);
694 cabInfo.PackFiles(null, new string[] { "test00.txt", "test01.txt" }, null);
695
696 Assert.AreEqual<string>(new FileInfo("test.cab").Directory.FullName, cabInfo.Directory.FullName, "CabInfo.FullName");
697 Assert.AreEqual<string>(new FileInfo("test.cab").DirectoryName, cabInfo.DirectoryName, "CabInfo.DirectoryName");
698 Assert.AreEqual<long>(new FileInfo("test.cab").Length, cabInfo.Length, "CabInfo.Length");
699 Assert.AreEqual<string>("test.cab", cabInfo.Name, "CabInfo.Name");
700 Assert.AreEqual<string>(new FileInfo("test.cab").FullName, cabInfo.ToString(), "CabInfo.ToString()");
701 cabInfo.CopyTo("test3.cab");
702 caughtEx = null;
703 try
704 {
705 cabInfo.CopyTo("test3.cab");
706 }
707 catch (Exception ex) { caughtEx = ex; }
708 Assert.IsInstanceOfType(caughtEx, typeof(IOException), "CabInfo.CopyTo() caught exception: " + caughtEx);
709 cabInfo.CopyTo("test3.cab", true);
710 cabInfo.MoveTo("test4.cab");
711 Assert.AreEqual<string>("test4.cab", cabInfo.Name);
712 Assert.IsTrue(cabInfo.Exists, "CabInfo.Exists()");
713 Assert.IsTrue(cabInfo.IsValid(), "CabInfo.IsValid");
714 cabInfo.Delete();
715 Assert.IsFalse(cabInfo.Exists, "!CabInfo.Exists()");
716 }
717
718 [TestMethod]
719 //[Ignore] // Requires clean environment.
720 public void CabInfoNullParams()
721 {
722 int fileCount = 10, fileSize = 1024;
723 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
724 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
725 Directory.CreateDirectory(dirA);
726 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
727 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
728 Directory.CreateDirectory(dirB);
729
730 string[] files = new string[fileCount];
731 for (int iFile = 0; iFile < fileCount; iFile++)
732 {
733 files[iFile] = "cabinfo-" + iFile + ".txt";
734 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
735 }
736
737 CabInfo cabInfo = new CabInfo("testnull.cab");
738
739 CompressionTestUtil.TestArchiveInfoNullParams(cabInfo, dirA, dirB, files);
740 }
741
742 [TestMethod]
743 public void CabInfoGetFiles()
744 {
745 IList<CabFileInfo> fileInfo;
746 CabInfo cabInfo = new CabInfo("test.cab");
747 int txtSize = 10240;
748 CompressionTestUtil.GenerateRandomFile("testinfo0.txt", 0, txtSize);
749 CompressionTestUtil.GenerateRandomFile("testinfo1.txt", 1, txtSize);
750 cabInfo.PackFiles(null, new string[] { "testinfo0.txt", "testinfo1.txt" }, null);
751
752 fileInfo = cabInfo.GetFiles();
753 Assert.IsNotNull(fileInfo);
754 Assert.AreEqual<int>(2, fileInfo.Count);
755 Assert.AreEqual<string>("testinfo0.txt", fileInfo[0].Name);
756 Assert.AreEqual<string>("testinfo1.txt", fileInfo[1].Name);
757
758 fileInfo = cabInfo.GetFiles("*.txt");
759 Assert.IsNotNull(fileInfo);
760 Assert.AreEqual<int>(2, fileInfo.Count);
761 Assert.AreEqual<string>("testinfo0.txt", fileInfo[0].Name);
762 Assert.AreEqual<string>("testinfo1.txt", fileInfo[1].Name);
763
764 fileInfo = cabInfo.GetFiles("testinfo1.txt");
765 Assert.IsNotNull(fileInfo);
766 Assert.AreEqual<int>(1, fileInfo.Count);
767 Assert.AreEqual<string>("testinfo1.txt", fileInfo[0].Name);
768 }
769
770 [TestMethod]
771 public void CabInfoCompressExtract()
772 {
773 int fileCount = 10, fileSize = 1024;
774 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
775 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
776 Directory.CreateDirectory(dirA);
777 Directory.CreateDirectory(Path.Combine(dirA, "sub"));
778 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
779 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
780 Directory.CreateDirectory(dirB);
781
782 string[] files = new string[fileCount];
783 for (int iFile = 0; iFile < fileCount; iFile++)
784 {
785 files[iFile] = "€" + iFile + ".txt";
786 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
787 }
788 CompressionTestUtil.GenerateRandomFile(Path.Combine(Path.Combine(dirA, "sub"), "€-.txt"), fileCount + 1, fileSize);
789
790 CabInfo cabInfo = new CabInfo("test.cab");
791 cabInfo.Pack(dirA);
792 cabInfo.Unpack(dirB);
793 bool directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
794 Assert.IsFalse(directoryMatch,
795 "Testing whether cabinet output directory matches input directory.");
796 Directory.Delete(dirB, true);
797 Directory.CreateDirectory(dirB);
798 cabInfo.Pack(dirA, true, CompressionLevel.Normal, null);
799 cabInfo.Unpack(dirB);
800 directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
801 Assert.IsTrue(directoryMatch,
802 "Testing whether cabinet output directory matches input directory.");
803 Directory.Delete(dirB, true);
804 Directory.Delete(Path.Combine(dirA, "sub"), true);
805 Directory.CreateDirectory(dirB);
806 cabInfo.Delete();
807
808 cabInfo.PackFiles(dirA, files, null);
809 cabInfo.UnpackFiles(files, dirB, null);
810 directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
811 Assert.IsTrue(directoryMatch,
812 "Testing whether cabinet output directory matches input directory.");
813 Directory.Delete(dirB, true);
814 Directory.CreateDirectory(dirB);
815 cabInfo.Delete();
816
817 IDictionary<string, string> testMap = new Dictionary<string, string>(files.Length);
818 for (int iFile = 0; iFile < fileCount; iFile++)
819 {
820 testMap[files[iFile] + ".key"] = files[iFile];
821 }
822 cabInfo.PackFileSet(dirA, testMap);
823 cabInfo.UnpackFileSet(testMap, dirB);
824 directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
825 Assert.IsTrue(directoryMatch,
826 "Testing whether cabinet output directory matches input directory.");
827 Directory.Delete(dirB, true);
828 Directory.CreateDirectory(dirB);
829
830 testMap.Remove(files[1] + ".key");
831 cabInfo.UnpackFileSet(testMap, dirB);
832 directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
833 Assert.IsFalse(directoryMatch,
834 "Testing whether cabinet output directory matches input directory.");
835 Directory.Delete(dirB, true);
836 Directory.CreateDirectory(dirB);
837 cabInfo.Delete();
838
839 cabInfo.PackFiles(dirA, files, null);
840 cabInfo.UnpackFile("€2.txt", Path.Combine(dirB, "test.txt"));
841 Assert.IsTrue(File.Exists(Path.Combine(dirB, "test.txt")));
842 Assert.AreEqual<int>(1, Directory.GetFiles(dirB).Length);
843 }
844
845 [TestMethod]
846 //[Ignore] // Requires clean environment.
847 public void CabFileInfoProperties()
848 {
849 CabInfo cabInfo = new CabInfo("test.cab");
850 int txtSize = 10240;
851 CompressionTestUtil.GenerateRandomFile("test00.txt", 0, txtSize);
852 CompressionTestUtil.GenerateRandomFile("test01.txt", 1, txtSize);
853 File.SetAttributes("test01.txt", FileAttributes.ReadOnly | FileAttributes.Archive);
854 DateTime testTime = File.GetLastWriteTime("test01.txt");
855 cabInfo.PackFiles(null, new string[] { "test00.txt", "test01.txt" }, null);
856 File.SetAttributes("test01.txt", FileAttributes.Archive);
857
858 CabFileInfo cfi = new CabFileInfo(cabInfo, "test01.txt");
859 Assert.AreEqual(cabInfo.FullName, cfi.CabinetName);
860 Assert.AreEqual<int>(0, ((CabFileInfo) cfi).CabinetFolderNumber);
861 Assert.AreEqual<string>(Path.Combine(cabInfo.FullName, "test01.txt"), cfi.FullName);
862 cfi = new CabFileInfo(cabInfo, "test01.txt");
863 Assert.IsTrue(cfi.Exists);
864 cfi = new CabFileInfo(cabInfo, "test01.txt");
865 Assert.AreEqual<long>(txtSize, cfi.Length);
866 cfi = new CabFileInfo(cabInfo, "test00.txt");
867 Assert.AreEqual<FileAttributes>(FileAttributes.Archive, cfi.Attributes);
868 cfi = new CabFileInfo(cabInfo, "test01.txt");
869 Assert.AreEqual<FileAttributes>(FileAttributes.ReadOnly | FileAttributes.Archive, cfi.Attributes);
870 cfi = new CabFileInfo(cabInfo, "test01.txt");
871 Assert.IsTrue((testTime - cfi.LastWriteTime).Duration() < new TimeSpan(0, 0, 5));
872 Assert.AreEqual<string>(Path.Combine(cabInfo.FullName, "test01.txt"), cfi.ToString());
873 cfi.CopyTo("testcopy.txt");
874 Assert.IsTrue(File.Exists("testCopy.txt"));
875 Assert.AreEqual<long>(cfi.Length, new FileInfo("testCopy.txt").Length);
876
877 Exception caughtEx = null;
878 try
879 {
880 cfi.CopyTo("testcopy.txt", false);
881 }
882 catch (Exception ex) { caughtEx = ex; }
883 Assert.IsInstanceOfType(caughtEx, typeof(IOException));
884 }
885
886 [TestMethod]
887 public void CabFileInfoOpenText()
888 {
889 CabInfo cabInfo = new CabInfo("test.cab");
890 int txtSize = 10240;
891 CompressionTestUtil.GenerateRandomFile("test00.txt", 0, txtSize);
892 CompressionTestUtil.GenerateRandomFile("test01.txt", 1, txtSize);
893
894 string expectedText = File.ReadAllText("test01.txt");
895
896 cabInfo.PackFiles(null, new string[] { "test00.txt", "test01.txt" }, null);
897
898 CabFileInfo cfi = new CabFileInfo(cabInfo, "test01.txt");
899 using (StreamReader cabFileReader = cfi.OpenText())
900 {
901 string text = cabFileReader.ReadToEnd();
902 Assert.AreEqual(expectedText, text);
903
904 // Check the assumption that the cab can't be deleted while a stream is open.
905 Exception caughtEx = null;
906 try
907 {
908 File.Delete(cabInfo.FullName);
909 }
910 catch (Exception ex)
911 {
912 caughtEx = ex;
913 }
914
915 Assert.IsInstanceOfType(caughtEx, typeof(IOException));
916 }
917
918 // Ensure all streams are closed after disposing of the StreamReader returned by OpenText.
919 File.Delete(cabInfo.FullName);
920 }
921
922 [TestMethod]
923 public void CabFileInfoNullParams()
924 {
925 Exception caughtEx;
926 CabInfo cabInfo = new CabInfo("test.cab");
927 int txtSize = 10240;
928 CompressionTestUtil.GenerateRandomFile("test00.txt", 0, txtSize);
929 CompressionTestUtil.GenerateRandomFile("test01.txt", 1, txtSize);
930 cabInfo.PackFiles(null, new string[] { "test00.txt", "test01.txt" }, null);
931 CabFileInfo cfi = new CabFileInfo(cabInfo, "test01.txt");
932
933 caughtEx = null;
934 try
935 {
936 new CabFileInfo(null, "test00.txt");
937 }
938 catch (Exception ex) { caughtEx = ex; }
939 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
940 caughtEx = null;
941 try
942 {
943 new CabFileInfo(cabInfo, null);
944 }
945 catch (Exception ex) { caughtEx = ex; }
946 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
947 caughtEx = null;
948 try
949 {
950 cfi.CopyTo(null);
951 }
952 catch (Exception ex) { caughtEx = ex; }
953 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
954 }
955
956 [TestMethod]
957 public void CabInfoSerialization()
958 {
959 CabInfo cabInfo = new CabInfo("testser.cab");
960 int txtSize = 10240;
961 CompressionTestUtil.GenerateRandomFile("testser00.txt", 0, txtSize);
962 CompressionTestUtil.GenerateRandomFile("testser01.txt", 1, txtSize);
963 cabInfo.PackFiles(null, new string[] { "testser00.txt", "testser01.txt" }, null);
964 ArchiveFileInfo cfi = cabInfo.GetFiles()[1];
965
966 MemoryStream memStream = new MemoryStream();
967
968 BinaryFormatter formatter = new BinaryFormatter();
969
970 memStream.Seek(0, SeekOrigin.Begin);
971 formatter.Serialize(memStream, cabInfo);
972 memStream.Seek(0, SeekOrigin.Begin);
973 CabInfo cabInfo2 = (CabInfo) formatter.Deserialize(memStream);
974 Assert.AreEqual<string>(cabInfo.FullName, cabInfo2.FullName);
975
976 memStream.Seek(0, SeekOrigin.Begin);
977 formatter.Serialize(memStream, cfi);
978 memStream.Seek(0, SeekOrigin.Begin);
979 CabFileInfo cfi2 = (CabFileInfo) formatter.Deserialize(memStream);
980 Assert.AreEqual<string>(cfi.FullName, cfi2.FullName);
981 Assert.AreEqual<long>(cfi.Length, cfi2.Length);
982
983 CabException cabEx = new CabException();
984 memStream.Seek(0, SeekOrigin.Begin);
985 formatter.Serialize(memStream, cabEx);
986 memStream.Seek(0, SeekOrigin.Begin);
987 formatter.Deserialize(memStream);
988
989 cabEx = new CabException("Test exception.", null);
990 Assert.AreEqual<string>("Test exception.", cabEx.Message);
991 }
992
993 [TestMethod]
994 public void CabFileStreamContextNullParams()
995 {
996 ArchiveFileStreamContext streamContext = null;
997 Exception caughtEx = null;
998 try
999 {
1000 streamContext = new ArchiveFileStreamContext(null);
1001 }
1002 catch (Exception ex) { caughtEx = ex; }
1003 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Passing null to constructor.");
1004 caughtEx = null;
1005 try
1006 {
1007 streamContext = new ArchiveFileStreamContext(new string[] { }, "testDir", new Dictionary<string, string>());
1008 }
1009 catch (Exception ex) { caughtEx = ex; }
1010 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Passing 0-length array to constructor.");
1011 caughtEx = null;
1012 try
1013 {
1014 streamContext = new ArchiveFileStreamContext(new string[] { "test.cab" }, null, null);
1015 }
1016 catch (Exception ex) { caughtEx = ex; }
1017 Assert.IsNull(caughtEx);
1018 }
1019
1020 [TestMethod]
1021 public void CabinetTruncateOnCreate()
1022 {
1023 CabInfo cabInfo = new CabInfo("testtruncate.cab");
1024 int txtSize = 20240;
1025 CompressionTestUtil.GenerateRandomFile("testtruncate0.txt", 0, txtSize);
1026 CompressionTestUtil.GenerateRandomFile("testtruncate1.txt", 1, txtSize);
1027 cabInfo.PackFiles(null, new string[] { "testtruncate0.txt", "testtruncate1.txt" }, null);
1028
1029 long size1 = cabInfo.Length;
1030
1031 txtSize /= 5;
1032 CompressionTestUtil.GenerateRandomFile("testtruncate2.txt", 2, txtSize);
1033 CompressionTestUtil.GenerateRandomFile("testtruncate3.txt", 3, txtSize);
1034 cabInfo.PackFiles(null, new string[] { "testtruncate2.txt", "testtruncate3.txt" }, null);
1035
1036 // The newly created cab file should be smaller than before.
1037 Assert.AreNotEqual<long>(size1, cabInfo.Length, "Checking that cabinet file got truncated when creating a smaller cab in-place.");
1038 }
1039
1040 [TestMethod]
1041 public void CabTruncatedArchive()
1042 {
1043 CabInfo cabInfo = new CabInfo("test-t.cab");
1044 CompressionTestUtil.GenerateRandomFile("cabtest-0.txt", 0, 5);
1045 CompressionTestUtil.GenerateRandomFile("cabtest-1.txt", 1, 5);
1046 cabInfo.PackFiles(null, new string[] { "cabtest-0.txt", "cabtest-1.txt" }, null);
1047
1048 CompressionTestUtil.TestTruncatedArchive(cabInfo, typeof(CabException));
1049 }
1050 private const string TEST_FILENAME_PREFIX = "\x20AC";
1051
1052 private IList<ArchiveFileInfo> RunCabinetPackUnpack(int fileCount, long fileSize)
1053 {
1054 return RunCabinetPackUnpack(fileCount, fileSize, 0, 0);
1055 }
1056 private IList<ArchiveFileInfo> RunCabinetPackUnpack(int fileCount, long fileSize,
1057 long maxFolderSize, long maxArchiveSize)
1058 {
1059 return this.RunCabinetPackUnpack(fileCount, fileSize, maxFolderSize, maxArchiveSize, CompressionLevel.Normal);
1060 }
1061 private IList<ArchiveFileInfo> RunCabinetPackUnpack(int fileCount, long fileSize,
1062 long maxFolderSize, long maxArchiveSize, CompressionLevel compLevel)
1063 {
1064 Console.WriteLine("Creating cabinet with {0} files of size {1}",
1065 fileCount, fileSize);
1066 Console.WriteLine("MaxFolderSize={0}, MaxArchiveSize={1}, CompressionLevel={2}",
1067 maxFolderSize, maxArchiveSize, compLevel);
1068
1069 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
1070 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
1071 Directory.CreateDirectory(dirA);
1072 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
1073 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
1074 Directory.CreateDirectory(dirB);
1075
1076 string[] files = new string[fileCount];
1077 for (int iFile = 0; iFile < fileCount; iFile++)
1078 {
1079 files[iFile] = TEST_FILENAME_PREFIX + iFile + ".txt";
1080 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
1081 }
1082
1083 string[] archiveNames = new string[100];
1084 for (int i = 0; i < archiveNames.Length; i++)
1085 {
1086 archiveNames[i] = String.Format("{0}-{1}{2}{3}.cab", fileCount, fileSize,
1087 (i == 0 ? "" : "-"), (i == 0 ? "" : i.ToString()));
1088 }
1089
1090 string progressTextFile = String.Format("progress_{0}-{1}.txt", fileCount, fileSize);
1091 CompressionTestUtil testUtil = new CompressionTestUtil(progressTextFile);
1092
1093 IList<ArchiveFileInfo> fileInfo;
1094 using (CabEngine cabEngine = new CabEngine())
1095 {
1096 cabEngine.CompressionLevel = compLevel;
1097
1098 File.AppendAllText(progressTextFile,
1099 "\r\n\r\n====================================================\r\nCREATE\r\n\r\n");
1100 cabEngine.Progress += testUtil.PrintArchiveProgress;
1101
1102 OptionStreamContext streamContext = new OptionStreamContext(archiveNames, dirA, null);
1103 if (maxFolderSize == 1)
1104 {
1105 streamContext.OptionHandler =
1106 delegate(string optionName, object[] parameters)
1107 {
1108 if (optionName == "nextFolder") return true;
1109 return null;
1110 };
1111 }
1112 else if (maxFolderSize > 1)
1113 {
1114 streamContext.OptionHandler =
1115 delegate(string optionName, object[] parameters)
1116 {
1117 if (optionName == "maxFolderSize") return maxFolderSize;
1118 return null;
1119 };
1120 }
1121 cabEngine.Pack(streamContext, files, maxArchiveSize);
1122
1123 IList<string> createdArchiveNames = new List<string>(archiveNames.Length);
1124 for (int i = 0; i < archiveNames.Length; i++)
1125 {
1126 if (File.Exists(archiveNames[i]))
1127 {
1128 createdArchiveNames.Add(archiveNames[i]);
1129 }
1130 else
1131 {
1132 break;
1133 }
1134 }
1135
1136 Console.WriteLine("Listing cabinet with {0} files of size {1}",
1137 fileCount, fileSize);
1138 File.AppendAllText(progressTextFile, "\r\n\r\nLIST\r\n\r\n");
1139 fileInfo = cabEngine.GetFileInfo(
1140 new ArchiveFileStreamContext(createdArchiveNames, null, null), null);
1141
1142 Assert.AreEqual<int>(fileCount, fileInfo.Count);
1143 if (fileCount > 0)
1144 {
1145 int folders = ((CabFileInfo) fileInfo[fileInfo.Count - 1]).CabinetFolderNumber + 1;
1146 if (maxFolderSize == 1)
1147 {
1148 Assert.AreEqual<int>(fileCount, folders);
1149 }
1150 }
1151
1152 Console.WriteLine("Extracting cabinet with {0} files of size {1}",
1153 fileCount, fileSize);
1154 File.AppendAllText(progressTextFile, "\r\n\r\nEXTRACT\r\n\r\n");
1155 cabEngine.Unpack(new ArchiveFileStreamContext(createdArchiveNames, dirB, null), null);
1156 }
1157
1158 bool directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
1159 Assert.IsTrue(directoryMatch,
1160 "Testing whether cabinet output directory matches input directory.");
1161
1162 return fileInfo;
1163 }
1164 }
1165}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/WixToolsetTests.Dtf.Compression.Cab.csproj b/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/WixToolsetTests.Dtf.Compression.Cab.csproj
new file mode 100644
index 00000000..636cedc6
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression.Cab/WixToolsetTests.Dtf.Compression.Cab.csproj
@@ -0,0 +1,43 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{4544158C-2D63-4146-85FF-62169280144E}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf.Cab</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.Cab</AssemblyName>
9 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
10 <CreateDocumentation>false</CreateDocumentation>
11 <SignOutput>false</SignOutput>
12 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <Compile Include="CabTest.cs" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <Reference Include="System" />
21 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
22 <Reference Include="System.Data" />
23 <Reference Include="System.Xml" />
24 </ItemGroup>
25
26 <ItemGroup>
27 <ProjectReference Include="..\..\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj">
28 <Project>{45D81DAB-0559-4836-8106-CE9987FD4AB5}</Project>
29 <Name>WixToolset.Dtf.Compression</Name>
30 </ProjectReference>
31 <ProjectReference Include="..\..\WixToolset.Dtf.Compression.Cab\WixToolset.Dtf.Compression.Cab.csproj">
32 <Project>{E56C0ED3-FA2F-4CA9-A1C0-2E796BB0BF80}</Project>
33 <Name>WixToolset.Dtf.Compression.Cab</Name>
34 </ProjectReference>
35 <ProjectReference Include="..\WixToolsetTests.Dtf.Compression\WixToolsetTests.Dtf.Compression.csproj">
36 <Project>{F045FFC1-05F9-4EA2-9F03-E1CBDB7BC4F9}</Project>
37 <Name>WixToolsetTests.Dtf.Compression</Name>
38 </ProjectReference>
39 </ItemGroup>
40
41 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
42 <Target Name="Pack" DependsOnTargets="Build" />
43</Project>
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/WixToolsetTests.Dtf.Compression.Zip.csproj b/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/WixToolsetTests.Dtf.Compression.Zip.csproj
new file mode 100644
index 00000000..d46776d8
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/WixToolsetTests.Dtf.Compression.Zip.csproj
@@ -0,0 +1,41 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{328799BB-7B03-4B28-8180-4132211FD07D}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.Zip</AssemblyName>
9 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
10 <CreateDocumentation>false</CreateDocumentation>
11 <SignOutput>false</SignOutput>
12 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <Compile Include="ZipTest.cs" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
21 <Reference Include="System" />
22 </ItemGroup>
23
24 <ItemGroup>
25 <ProjectReference Include="..\..\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj">
26 <Project>{45D81DAB-0559-4836-8106-CE9987FD4AB5}</Project>
27 <Name>WixToolset.Dtf.Compression</Name>
28 </ProjectReference>
29 <ProjectReference Include="..\..\WixToolset.Dtf.Compression.Zip\WixToolset.Dtf.Compression.Zip.csproj">
30 <Project>{E4C60A57-8AFE-4FF3-9058-ACAC6A069533}</Project>
31 <Name>WixToolset.Dtf.Compression.Zip</Name>
32 </ProjectReference>
33 <ProjectReference Include="..\WixToolsetTests.Dtf.Compression\WixToolsetTests.Dtf.Compression.csproj">
34 <Project>{F045FFC1-05F9-4EA2-9F03-E1CBDB7BC4F9}</Project>
35 <Name>WixToolsetTests.Dtf.Compression</Name>
36 </ProjectReference>
37 </ItemGroup>
38
39 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
40 <Target Name="Pack" DependsOnTargets="Build" />
41</Project>
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/ZipTest.cs b/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/ZipTest.cs
new file mode 100644
index 00000000..b264ad5b
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression.Zip/ZipTest.cs
@@ -0,0 +1,518 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Text;
8 using System.Collections.Generic;
9 using Microsoft.VisualStudio.TestTools.UnitTesting;
10 using WixToolset.Dtf.Compression;
11 using WixToolset.Dtf.Compression.Zip;
12
13 [TestClass]
14 public class ZipTest
15 {
16 public ZipTest()
17 {
18 }
19
20 [TestInitialize]
21 public void Initialize()
22 {
23 }
24
25 [TestCleanup]
26 public void Cleanup()
27 {
28 }
29
30 [TestMethod]
31 public void ZipFileCounts()
32 {
33 this.RunZipPackUnpack(0, 10, 0);
34 this.RunZipPackUnpack(0, 100000, 0);
35 this.RunZipPackUnpack(1, 10, 0);
36 this.RunZipPackUnpack(100, 10, 0);
37 }
38
39 [TestMethod]
40 [Ignore] // Takes too long to run regularly.
41 public void ZipExtremeFileCounts()
42 {
43 this.RunZipPackUnpack(66000, 10, 0);
44 }
45
46 [TestMethod]
47 public void ZipFileSizes()
48 {
49 this.RunZipPackUnpack(1, 0, 0);
50 for (int n = 1; n <= 33; n++)
51 {
52 this.RunZipPackUnpack(1, n, 0);
53 }
54 this.RunZipPackUnpack(1, 100 * 1024, 0);
55 this.RunZipPackUnpack(1, 10 * 1024 * 1024, 0);
56 }
57
58 [Timeout(36000000), TestMethod]
59 [Ignore] // Takes too long to run regularly.
60 public void ZipExtremeFileSizes()
61 {
62 //this.RunZipPackUnpack(10, 512L * 1024 * 1024, 0); // 5GB
63 this.RunZipPackUnpack(1, 5L * 1024 * 1024 * 1024, 0, CompressionLevel.None); // 5GB
64 }
65
66 [TestMethod]
67 public void ZipArchiveCounts()
68 {
69 IList<ArchiveFileInfo> fileInfo;
70 fileInfo = this.RunZipPackUnpack(10, 100 * 1024, 400 * 1024, CompressionLevel.None);
71 Assert.AreEqual<int>(2, fileInfo[fileInfo.Count - 1].ArchiveNumber,
72 "Testing whether archive spans the correct # of zip files.");
73
74 fileInfo = this.RunZipPackUnpack(2, 90 * 1024, 40 * 1024, CompressionLevel.None);
75 Assert.AreEqual<int>(2, fileInfo[fileInfo.Count - 1].ArchiveNumber,
76 "Testing whether archive spans the correct # of zip files.");
77 }
78
79 [TestMethod]
80 public void ZipProgress()
81 {
82 CompressionTestUtil.ExpectedProgress = new List<int[]>(new int[][] {
83 // StatusType, CurFile,TotalFiles,CurFolder,CurArchive,TotalArchives
84 new int[] { (int) ArchiveProgressType.StartArchive, 0, 15, 0, 0, 1 },
85 new int[] { (int) ArchiveProgressType.StartFile, 0, 15, 0, 0, 1 },
86 new int[] { (int) ArchiveProgressType.FinishFile, 0, 15, 0, 0, 1 },
87 new int[] { (int) ArchiveProgressType.StartFile, 1, 15, 0, 0, 1 },
88 new int[] { (int) ArchiveProgressType.FinishFile, 1, 15, 0, 0, 1 },
89 new int[] { (int) ArchiveProgressType.StartFile, 2, 15, 0, 0, 1 },
90 new int[] { (int) ArchiveProgressType.FinishFile, 2, 15, 0, 0, 1 },
91 new int[] { (int) ArchiveProgressType.StartFile, 3, 15, 0, 0, 1 },
92 new int[] { (int) ArchiveProgressType.FinishFile, 3, 15, 0, 0, 1 },
93 new int[] { (int) ArchiveProgressType.StartFile, 4, 15, 0, 0, 1 },
94 new int[] { (int) ArchiveProgressType.FinishFile, 4, 15, 0, 0, 1 },
95 new int[] { (int) ArchiveProgressType.StartFile, 5, 15, 0, 0, 1 },
96 new int[] { (int) ArchiveProgressType.FinishFile, 5, 15, 0, 0, 1 },
97 new int[] { (int) ArchiveProgressType.StartFile, 6, 15, 0, 0, 1 },
98 new int[] { (int) ArchiveProgressType.FinishArchive, 6, 15, 0, 0, 1 },
99 new int[] { (int) ArchiveProgressType.StartArchive, 6, 15, 0, 1, 2 },
100 new int[] { (int) ArchiveProgressType.FinishFile, 6, 15, 0, 1, 2 },
101 new int[] { (int) ArchiveProgressType.StartFile, 7, 15, 0, 1, 2 },
102 new int[] { (int) ArchiveProgressType.FinishFile, 7, 15, 0, 1, 2 },
103 new int[] { (int) ArchiveProgressType.StartFile, 8, 15, 0, 1, 2 },
104 new int[] { (int) ArchiveProgressType.FinishFile, 8, 15, 0, 1, 2 },
105 new int[] { (int) ArchiveProgressType.StartFile, 9, 15, 0, 1, 2 },
106 new int[] { (int) ArchiveProgressType.FinishFile, 9, 15, 0, 1, 2 },
107 new int[] { (int) ArchiveProgressType.StartFile, 10, 15, 0, 1, 2 },
108 new int[] { (int) ArchiveProgressType.FinishFile, 10, 15, 0, 1, 2 },
109 new int[] { (int) ArchiveProgressType.StartFile, 11, 15, 0, 1, 2 },
110 new int[] { (int) ArchiveProgressType.FinishFile, 11, 15, 0, 1, 2 },
111 new int[] { (int) ArchiveProgressType.StartFile, 12, 15, 0, 1, 2 },
112 new int[] { (int) ArchiveProgressType.FinishArchive, 12, 15, 0, 1, 2 },
113 new int[] { (int) ArchiveProgressType.StartArchive, 12, 15, 0, 2, 3 },
114 new int[] { (int) ArchiveProgressType.FinishFile, 12, 15, 0, 2, 3 },
115 new int[] { (int) ArchiveProgressType.StartFile, 13, 15, 0, 2, 3 },
116 new int[] { (int) ArchiveProgressType.FinishFile, 13, 15, 0, 2, 3 },
117 new int[] { (int) ArchiveProgressType.StartFile, 14, 15, 0, 2, 3 },
118 new int[] { (int) ArchiveProgressType.FinishFile, 14, 15, 0, 2, 3 },
119 new int[] { (int) ArchiveProgressType.FinishArchive, 14, 15, 0, 2, 3 },
120 // StatusType, CurFile,TotalFiles,CurFolder,CurArchive,TotalArchives
121 new int[] { (int) ArchiveProgressType.StartArchive, 0, 15, 0, 0, 3 },
122 new int[] { (int) ArchiveProgressType.StartFile, 0, 15, 0, 0, 3 },
123 new int[] { (int) ArchiveProgressType.FinishFile, 0, 15, 0, 0, 3 },
124 new int[] { (int) ArchiveProgressType.StartFile, 1, 15, 0, 0, 3 },
125 new int[] { (int) ArchiveProgressType.FinishFile, 1, 15, 0, 0, 3 },
126 new int[] { (int) ArchiveProgressType.StartFile, 2, 15, 0, 0, 3 },
127 new int[] { (int) ArchiveProgressType.FinishFile, 2, 15, 0, 0, 3 },
128 new int[] { (int) ArchiveProgressType.StartFile, 3, 15, 0, 0, 3 },
129 new int[] { (int) ArchiveProgressType.FinishFile, 3, 15, 0, 0, 3 },
130 new int[] { (int) ArchiveProgressType.StartFile, 4, 15, 0, 0, 3 },
131 new int[] { (int) ArchiveProgressType.FinishFile, 4, 15, 0, 0, 3 },
132 new int[] { (int) ArchiveProgressType.StartFile, 5, 15, 0, 0, 3 },
133 new int[] { (int) ArchiveProgressType.FinishFile, 5, 15, 0, 0, 3 },
134 new int[] { (int) ArchiveProgressType.StartFile, 6, 15, 0, 0, 3 },
135 new int[] { (int) ArchiveProgressType.FinishArchive, 6, 15, 0, 0, 3 },
136 new int[] { (int) ArchiveProgressType.StartArchive, 6, 15, 0, 1, 3 },
137 new int[] { (int) ArchiveProgressType.FinishFile, 6, 15, 0, 1, 3 },
138 new int[] { (int) ArchiveProgressType.StartFile, 7, 15, 0, 1, 3 },
139 new int[] { (int) ArchiveProgressType.FinishFile, 7, 15, 0, 1, 3 },
140 new int[] { (int) ArchiveProgressType.StartFile, 8, 15, 0, 1, 3 },
141 new int[] { (int) ArchiveProgressType.FinishFile, 8, 15, 0, 1, 3 },
142 new int[] { (int) ArchiveProgressType.StartFile, 9, 15, 0, 1, 3 },
143 new int[] { (int) ArchiveProgressType.FinishFile, 9, 15, 0, 1, 3 },
144 new int[] { (int) ArchiveProgressType.StartFile, 10, 15, 0, 1, 3 },
145 new int[] { (int) ArchiveProgressType.FinishFile, 10, 15, 0, 1, 3 },
146 new int[] { (int) ArchiveProgressType.StartFile, 11, 15, 0, 1, 3 },
147 new int[] { (int) ArchiveProgressType.FinishFile, 11, 15, 0, 1, 3 },
148 new int[] { (int) ArchiveProgressType.StartFile, 12, 15, 0, 1, 3 },
149 new int[] { (int) ArchiveProgressType.FinishArchive, 12, 15, 0, 1, 3 },
150 new int[] { (int) ArchiveProgressType.StartArchive, 12, 15, 0, 2, 3 },
151 new int[] { (int) ArchiveProgressType.FinishFile, 12, 15, 0, 2, 3 },
152 new int[] { (int) ArchiveProgressType.StartFile, 13, 15, 0, 2, 3 },
153 new int[] { (int) ArchiveProgressType.FinishFile, 13, 15, 0, 2, 3 },
154 new int[] { (int) ArchiveProgressType.StartFile, 14, 15, 0, 2, 3 },
155 new int[] { (int) ArchiveProgressType.FinishFile, 14, 15, 0, 2, 3 },
156 new int[] { (int) ArchiveProgressType.FinishArchive, 14, 15, 0, 2, 3 },
157 });
158 CompressionTestUtil.ExpectedProgress = null;
159
160 try
161 {
162 this.RunZipPackUnpack(15, 20 * 1024, 130 * 1024, CompressionLevel.None);
163 }
164 finally
165 {
166 CompressionTestUtil.ExpectedProgress = null;
167 }
168 }
169
170 [TestMethod]
171 //[Ignore] // Requires clean environment.
172 public void ZipArchiveSizes()
173 {
174 Console.WriteLine("Testing various values for the maxArchiveSize parameter.");
175 this.RunZipPackUnpack(5, 1024, Int64.MinValue);
176 this.RunZipPackUnpack(5, 1024, -1);
177 this.RunZipPackUnpack(2, 10, 0);
178
179 this.RunZipPackUnpack(1, 10, 1);
180 this.RunZipPackUnpack(2, 10, 2);
181 this.RunZipPackUnpack(2, 10, 3);
182 this.RunZipPackUnpack(2, 10, 4);
183 this.RunZipPackUnpack(2, 10, 5);
184 this.RunZipPackUnpack(2, 10, 6);
185 this.RunZipPackUnpack(2, 10, 7);
186 this.RunZipPackUnpack(5, 10, 8);
187 this.RunZipPackUnpack(5, 10, 9);
188 this.RunZipPackUnpack(5, 10, 10);
189 this.RunZipPackUnpack(5, 10, 11);
190 this.RunZipPackUnpack(5, 10, 12);
191
192 this.RunZipPackUnpack(5, 101, 255);
193 this.RunZipPackUnpack(5, 102, 256);
194 this.RunZipPackUnpack(5, 103, 257);
195 this.RunZipPackUnpack(5, 24000, 32768);
196 this.RunZipPackUnpack(5, 1024, Int64.MaxValue);
197 }
198
199 [TestMethod]
200 public void ZipCompLevelParam()
201 {
202 Console.WriteLine("Testing various values for the compressionLevel parameter.");
203 this.RunZipPackUnpack(5, 1024, 0, CompressionLevel.None);
204 this.RunZipPackUnpack(5, 1024, 0, CompressionLevel.Min);
205 this.RunZipPackUnpack(5, 1024, 0, CompressionLevel.Normal);
206 this.RunZipPackUnpack(5, 1024, 0, CompressionLevel.Max);
207 this.RunZipPackUnpack(5, 1024, 0, (CompressionLevel) ((int) CompressionLevel.None - 1));
208 this.RunZipPackUnpack(5, 1024, 0, (CompressionLevel) ((int) CompressionLevel.Max + 1));
209 this.RunZipPackUnpack(5, 1024, 0, (CompressionLevel) Int32.MinValue);
210 this.RunZipPackUnpack(5, 1024, 0, (CompressionLevel) Int32.MaxValue);
211 }
212
213 [TestMethod]
214 public void ZipInfoGetFiles()
215 {
216 IList<ZipFileInfo> fileInfos;
217 ZipInfo zipInfo = new ZipInfo("testgetfiles.zip");
218
219 int txtSize = 10240;
220 CompressionTestUtil.GenerateRandomFile("testinfo0.txt", 0, txtSize);
221 CompressionTestUtil.GenerateRandomFile("testinfo1.txt", 1, txtSize);
222 CompressionTestUtil.GenerateRandomFile("testinfo2.ini", 2, txtSize);
223 zipInfo.PackFiles(null, new string[] { "testinfo0.txt", "testinfo1.txt", "testinfo2.ini" }, null);
224
225 fileInfos = zipInfo.GetFiles();
226 Assert.IsNotNull(fileInfos);
227 Assert.AreEqual<int>(3, fileInfos.Count);
228 Assert.AreEqual<string>("testinfo0.txt", fileInfos[0].Name);
229 Assert.AreEqual<string>("testinfo1.txt", fileInfos[1].Name);
230 Assert.AreEqual<string>("testinfo2.ini", fileInfos[2].Name);
231
232 fileInfos = zipInfo.GetFiles("*.txt");
233 Assert.IsNotNull(fileInfos);
234 Assert.AreEqual<int>(2, fileInfos.Count);
235 Assert.AreEqual<string>("testinfo0.txt", fileInfos[0].Name);
236 Assert.AreEqual<string>("testinfo1.txt", fileInfos[1].Name);
237
238 fileInfos = zipInfo.GetFiles("testinfo1.txt");
239 Assert.IsNotNull(fileInfos);
240 Assert.AreEqual<int>(1, fileInfos.Count);
241 Assert.AreEqual<string>("testinfo1.txt", fileInfos[0].Name);
242 Assert.IsTrue(DateTime.Now - fileInfos[0].LastWriteTime < TimeSpan.FromMinutes(1),
243 "Checking ZipFileInfo.LastWriteTime is current.");
244 }
245
246 [TestMethod]
247 //[Ignore] // Requires clean environment.
248 public void ZipInfoNullParams()
249 {
250 int fileCount = 10, fileSize = 1024;
251 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
252 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
253 Directory.CreateDirectory(dirA);
254 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
255 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
256 Directory.CreateDirectory(dirB);
257
258 string[] files = new string[fileCount];
259 for (int iFile = 0; iFile < fileCount; iFile++)
260 {
261 files[iFile] = "zipinfo-" + iFile + ".txt";
262 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
263 }
264
265 ZipInfo zipInfo = new ZipInfo("testnull.zip");
266
267 CompressionTestUtil.TestArchiveInfoNullParams(zipInfo, dirA, dirB, files);
268 }
269
270 [TestMethod]
271 public void ZipFileInfoNullParams()
272 {
273 Exception caughtEx;
274 ZipInfo zipInfo = new ZipInfo("test.zip");
275 int txtSize = 10240;
276 CompressionTestUtil.GenerateRandomFile("test00.txt", 0, txtSize);
277 CompressionTestUtil.GenerateRandomFile("test01.txt", 1, txtSize);
278 zipInfo.PackFiles(null, new string[] { "test00.txt", "test01.txt" }, null);
279 ZipFileInfo zfi = new ZipFileInfo(zipInfo, "test01.txt");
280
281 caughtEx = null;
282 try
283 {
284 new ZipFileInfo(null, "test00.txt");
285 }
286 catch (Exception ex) { caughtEx = ex; }
287 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
288 caughtEx = null;
289 try
290 {
291 new ZipFileInfo(zipInfo, null);
292 }
293 catch (Exception ex) { caughtEx = ex; }
294 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
295 caughtEx = null;
296 try
297 {
298 zfi.CopyTo(null);
299 }
300 catch (Exception ex) { caughtEx = ex; }
301 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException));
302 }
303
304 [TestMethod]
305 public void ZipEngineNullParams()
306 {
307 string[] testFiles = new string[] { "test.txt" };
308 ArchiveFileStreamContext streamContext = new ArchiveFileStreamContext("test.zip", null, null);
309
310 using (ZipEngine zipEngine = new ZipEngine())
311 {
312 zipEngine.CompressionLevel = CompressionLevel.None;
313
314 CompressionTestUtil.TestCompressionEngineNullParams(zipEngine, streamContext, testFiles);
315 }
316 }
317
318 [TestMethod]
319 public void ZipBadPackStreamContexts()
320 {
321 string[] testFiles = new string[] { "test.txt" };
322 CompressionTestUtil.GenerateRandomFile(testFiles[0], 0, 20000);
323
324 using (ZipEngine zipEngine = new ZipEngine())
325 {
326 zipEngine.CompressionLevel = CompressionLevel.None;
327
328 CompressionTestUtil.TestBadPackStreamContexts(zipEngine, "test.zip", testFiles);
329 }
330 }
331
332 [TestMethod]
333 public void ZipBadUnpackStreamContexts()
334 {
335 int txtSize = 40960;
336 ZipInfo zipInfo = new ZipInfo("test2.zip");
337 CompressionTestUtil.GenerateRandomFile("ziptest-0.txt", 0, txtSize);
338 CompressionTestUtil.GenerateRandomFile("ziptest-1.txt", 1, txtSize);
339 zipInfo.PackFiles(null, new string[] { "ziptest-0.txt", "ziptest-1.txt" }, null);
340
341 using (ZipEngine zipEngine = new ZipEngine())
342 {
343 CompressionTestUtil.TestBadUnpackStreamContexts(zipEngine, "test2.zip");
344 }
345 }
346
347 [TestMethod]
348 [Ignore] // Failed on build server, need to investigate.
349 public void ZipTruncatedArchive()
350 {
351 ZipInfo zipInfo = new ZipInfo("test-t.zip");
352 CompressionTestUtil.GenerateRandomFile("ziptest-0.txt", 0, 5);
353 CompressionTestUtil.GenerateRandomFile("ziptest-1.txt", 1, 5);
354 zipInfo.PackFiles(null, new string[] { "ziptest-0.txt", "ziptest-1.txt" }, null);
355
356 CompressionTestUtil.TestTruncatedArchive(zipInfo, typeof(ZipException));
357 }
358
359 /*
360 [TestMethod]
361 public void ZipUnpack()
362 {
363 IList<ZipFileInfo> fileInfos;
364 foreach (FileInfo zipFile in new DirectoryInfo("D:\\temp").GetFiles("*.zip"))
365 {
366 Console.WriteLine("=====================================================");
367 Console.WriteLine(zipFile.FullName);
368 Console.WriteLine("=====================================================");
369 ZipInfo zipTest = new ZipInfo(zipFile.FullName);
370 fileInfos = zipTest.GetFiles();
371 Assert.AreNotEqual<int>(0, fileInfos.Count);
372 foreach (ArchiveFileInfo file in fileInfos)
373 {
374 Console.WriteLine("{0}\t{1}\t{2}", Path.Combine(file.Path, file.Name), file.Length, file.LastWriteTime);
375 }
376
377 Directory.CreateDirectory(Path.GetFileNameWithoutExtension(zipFile.Name));
378 zipTest.Unpack(Path.GetFileNameWithoutExtension(zipFile.Name));
379 }
380 }
381 */
382
383 /*
384 [TestMethod]
385 public void ZipUnpackSelfExtractor()
386 {
387 ZipInfo zipTest = new ZipInfo(@"C:\temp\testzip.exe");
388 IList<ZipFileInfo> fileInfos = zipTest.GetFiles();
389 Assert.AreNotEqual<int>(0, fileInfos.Count);
390 foreach (ArchiveFileInfo file in fileInfos)
391 {
392 Console.WriteLine("{0}\t{1}\t{2}", Path.Combine(file.Path, file.Name), file.Length, file.LastWriteTime);
393 }
394
395 string extractDir = Path.GetFileNameWithoutExtension(zipTest.Name);
396 Directory.CreateDirectory(extractDir);
397 zipTest.Unpack(extractDir);
398 }
399 */
400
401 private const string TEST_FILENAME_PREFIX = "\x20AC";
402
403 private IList<ArchiveFileInfo> RunZipPackUnpack(int fileCount, long fileSize,
404 long maxArchiveSize)
405 {
406 return this.RunZipPackUnpack(fileCount, fileSize, maxArchiveSize, CompressionLevel.Normal);
407 }
408
409 private IList<ArchiveFileInfo> RunZipPackUnpack(int fileCount, long fileSize,
410 long maxArchiveSize, CompressionLevel compLevel)
411 {
412 Console.WriteLine("Creating zip archive with {0} files of size {1}",
413 fileCount, fileSize);
414 Console.WriteLine("MaxArchiveSize={0}, CompressionLevel={1}", maxArchiveSize, compLevel);
415
416 string dirA = String.Format("{0}-{1}-A", fileCount, fileSize);
417 if (Directory.Exists(dirA)) Directory.Delete(dirA, true);
418 Directory.CreateDirectory(dirA);
419 string dirB = String.Format("{0}-{1}-B", fileCount, fileSize);
420 if (Directory.Exists(dirB)) Directory.Delete(dirB, true);
421 Directory.CreateDirectory(dirB);
422
423 string[] files = new string[fileCount];
424 for (int iFile = 0; iFile < fileCount; iFile++)
425 {
426 files[iFile] = TEST_FILENAME_PREFIX + iFile + ".txt";
427 CompressionTestUtil.GenerateRandomFile(Path.Combine(dirA, files[iFile]), iFile, fileSize);
428 }
429
430 string[] archiveNames = new string[1000];
431 for (int i = 0; i < archiveNames.Length; i++)
432 {
433 if (i < 100)
434 {
435 archiveNames[i] = String.Format(
436 (i == 0 ? "{0}-{1}.zip" : "{0}-{1}.z{2:d02}"),
437 fileCount, fileSize, i);
438 }
439 else
440 {
441 archiveNames[i] = String.Format(
442 "{0}-{1}.{2:d03}", fileCount, fileSize, i);
443 }
444 }
445
446 string progressTextFile = String.Format("progress_{0}-{1}.txt", fileCount, fileSize);
447 CompressionTestUtil testUtil = new CompressionTestUtil(progressTextFile);
448
449 IList<ArchiveFileInfo> fileInfo;
450 using (ZipEngine zipEngine = new ZipEngine())
451 {
452 zipEngine.CompressionLevel = compLevel;
453
454 File.AppendAllText(progressTextFile,
455 "\r\n\r\n====================================================\r\nCREATE\r\n\r\n");
456 zipEngine.Progress += testUtil.PrintArchiveProgress;
457
458 OptionStreamContext streamContext = new OptionStreamContext(archiveNames, dirA, null);
459 streamContext.OptionHandler =
460 delegate(string optionName, object[] parameters)
461 {
462 // For testing purposes, force zip64 for only moderately large files.
463 switch (optionName)
464 {
465 case "forceZip64":
466 return fileSize > UInt16.MaxValue;
467 default:
468 return null;
469 }
470 };
471
472 zipEngine.Pack(streamContext, files, maxArchiveSize);
473
474 string checkArchiveName = archiveNames[0];
475 if (File.Exists(archiveNames[1])) checkArchiveName = archiveNames[1];
476 using (Stream archiveStream = File.OpenRead(checkArchiveName))
477 {
478 bool isArchive = zipEngine.IsArchive(archiveStream);
479 Assert.IsTrue(isArchive, "Checking that created archive appears valid.");
480 }
481
482 IList<string> createdArchiveNames = new List<string>(archiveNames.Length);
483 for (int i = 0; i < archiveNames.Length; i++)
484 {
485 if (File.Exists(archiveNames[i]))
486 {
487 createdArchiveNames.Add(archiveNames[i]);
488 }
489 else
490 {
491 break;
492 }
493 }
494
495 Assert.AreNotEqual<int>(0, createdArchiveNames.Count);
496
497 Console.WriteLine("Listing zip archive with {0} files of size {1}",
498 fileCount, fileSize);
499 File.AppendAllText(progressTextFile, "\r\n\r\nLIST\r\n\r\n");
500 fileInfo = zipEngine.GetFileInfo(
501 new ArchiveFileStreamContext(createdArchiveNames, null, null), null);
502
503 Assert.AreEqual<int>(fileCount, fileInfo.Count);
504
505 Console.WriteLine("Extracting zip archive with {0} files of size {1}",
506 fileCount, fileSize);
507 File.AppendAllText(progressTextFile, "\r\n\r\nEXTRACT\r\n\r\n");
508 zipEngine.Unpack(new ArchiveFileStreamContext(createdArchiveNames, dirB, null), null);
509 }
510
511 bool directoryMatch = CompressionTestUtil.CompareDirectories(dirA, dirB);
512 Assert.IsTrue(directoryMatch,
513 "Testing whether zip output directory matches input directory.");
514
515 return fileInfo;
516 }
517 }
518}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression/CompressionTestUtil.cs b/src/dtf/test/WixToolsetTests.Dtf.Compression/CompressionTestUtil.cs
new file mode 100644
index 00000000..e7a5373d
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression/CompressionTestUtil.cs
@@ -0,0 +1,649 @@
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
3using System;
4using System.IO;
5using System.Text;
6using System.Collections.Generic;
7using System.Security.Cryptography;
8using Microsoft.VisualStudio.TestTools.UnitTesting;
9using WixToolset.Dtf.Compression;
10
11namespace WixToolset.Dtf.Test
12{
13 public class CompressionTestUtil
14 {
15 private static MD5 md5 = new MD5CryptoServiceProvider();
16
17 private string progressTextFile;
18
19 public CompressionTestUtil(string progressTextFile)
20 {
21 this.progressTextFile = progressTextFile;
22 }
23
24 public static IList<int[]> ExpectedProgress
25 {
26 get { return CompressionTestUtil.expectedProgress; }
27 set { CompressionTestUtil.expectedProgress = value; }
28 }
29 private static IList<int[]> expectedProgress;
30
31 public void PrintArchiveProgress(object source, ArchiveProgressEventArgs e)
32 {
33 switch (e.ProgressType)
34 {
35 case ArchiveProgressType.StartFile:
36 {
37 Console.WriteLine("StartFile: {0}", e.CurrentFileName);
38 } break;
39 case ArchiveProgressType.FinishFile:
40 {
41 Console.WriteLine("FinishFile: {0}", e.CurrentFileName);
42 } break;
43 case ArchiveProgressType.StartArchive:
44 {
45 Console.WriteLine("StartArchive: {0} : {1}", e.CurrentArchiveNumber, e.CurrentArchiveName);
46 } break;
47 case ArchiveProgressType.FinishArchive:
48 {
49 Console.WriteLine("FinishArchive: {0} : {1}", e.CurrentArchiveNumber, e.CurrentArchiveName);
50 } break;
51 }
52
53 File.AppendAllText(this.progressTextFile, e.ToString().Replace("\n", Environment.NewLine));
54
55 if (CompressionTestUtil.expectedProgress != null &&
56 e.ProgressType != ArchiveProgressType.PartialFile &&
57 e.ProgressType != ArchiveProgressType.PartialArchive)
58 {
59 Assert.AreNotEqual<int>(0, CompressionTestUtil.expectedProgress.Count);
60 int[] expected = CompressionTestUtil.expectedProgress[0];
61 CompressionTestUtil.expectedProgress.RemoveAt(0);
62 Assert.AreEqual<ArchiveProgressType>((ArchiveProgressType) expected[0], e.ProgressType, "Checking ProgressType.");
63 Assert.AreEqual<int>(expected[1], e.CurrentFileNumber, "Checking CurrentFileNumber.");
64 Assert.AreEqual<int>(expected[2], e.TotalFiles, "Checking TotalFiles.");
65 Assert.AreEqual<int>(expected[4], e.CurrentArchiveNumber, "Checking CurrentArchiveNumber.");
66 Assert.AreEqual<int>(expected[5], e.TotalArchives, "Checking TotalArchives.");
67 }
68 }
69
70 public static bool CompareDirectories(string dirA, string dirB)
71 {
72 bool difference = false;
73 Console.WriteLine("Comparing directories {0}, {1}", dirA, dirB);
74
75 string[] filesA = Directory.GetFiles(dirA);
76 string[] filesB = Directory.GetFiles(dirB);
77 for (int iA = 0; iA < filesA.Length; iA++)
78 {
79 filesA[iA] = Path.GetFileName(filesA[iA]);
80 }
81 for (int iB = 0; iB < filesB.Length; iB++)
82 {
83 filesB[iB] = Path.GetFileName(filesB[iB]);
84 }
85 Array.Sort(filesA);
86 Array.Sort(filesB);
87
88 for (int iA = 0, iB = 0; iA < filesA.Length || iB < filesB.Length; )
89 {
90 int comp;
91 if (iA == filesA.Length)
92 {
93 comp = 1;
94 }
95 else if (iB == filesB.Length)
96 {
97 comp = -1;
98 }
99 else
100 {
101 comp = String.Compare(filesA[iA], filesB[iB]);
102 }
103 if (comp < 0)
104 {
105 Console.WriteLine("< " + filesA[iA]);
106 difference = true;
107 iA++;
108 }
109 else if (comp > 0)
110 {
111 Console.WriteLine("> " + filesB[iB]);
112 difference = true;
113 iB++;
114 }
115 else
116 {
117 string fileA = Path.Combine(dirA, filesA[iA]);
118 string fileB = Path.Combine(dirB, filesB[iB]);
119
120 byte[] hashA;
121 byte[] hashB;
122
123 lock (CompressionTestUtil.md5)
124 {
125 using (Stream fileAStream = File.OpenRead(fileA))
126 {
127 hashA = CompressionTestUtil.md5.ComputeHash(fileAStream);
128 }
129 using (Stream fileBStream = File.OpenRead(fileB))
130 {
131 hashB = CompressionTestUtil.md5.ComputeHash(fileBStream);
132 }
133 }
134
135 for (int i = 0; i < hashA.Length; i++)
136 {
137 if (hashA[i] != hashB[i])
138 {
139 Console.WriteLine("~ " + filesA[iA]);
140 difference = true;
141 break;
142 }
143 }
144
145 iA++;
146 iB++;
147 }
148 }
149
150 string[] dirsA = Directory.GetDirectories(dirA);
151 string[] dirsB = Directory.GetDirectories(dirB);
152 for (int iA = 0; iA < dirsA.Length; iA++)
153 {
154 dirsA[iA] = Path.GetFileName(dirsA[iA]);
155 }
156 for (int iB = 0; iB < dirsB.Length; iB++)
157 {
158 dirsB[iB] = Path.GetFileName(dirsB[iB]);
159 }
160 Array.Sort(dirsA);
161 Array.Sort(dirsB);
162
163 for (int iA = 0, iB = 0; iA < dirsA.Length || iB < dirsB.Length; )
164 {
165 int comp;
166 if (iA == dirsA.Length)
167 {
168 comp = 1;
169 }
170 else if (iB == dirsB.Length)
171 {
172 comp = -1;
173 }
174 else
175 {
176 comp = String.Compare(dirsA[iA], dirsB[iB]);
177 }
178 if (comp < 0)
179 {
180 Console.WriteLine("< {0}\\", dirsA[iA]);
181 difference = true;
182 iA++;
183 }
184 else if (comp > 0)
185 {
186 Console.WriteLine("> {1}\\", dirsB[iB]);
187 difference = true;
188 iB++;
189 }
190 else
191 {
192 string subDirA = Path.Combine(dirA, dirsA[iA]);
193 string subDirB = Path.Combine(dirB, dirsB[iB]);
194 if (!CompressionTestUtil.CompareDirectories(subDirA, subDirB))
195 {
196 difference = true;
197 }
198 iA++;
199 iB++;
200 }
201 }
202
203 return !difference;
204 }
205
206
207 public static void GenerateRandomFile(string path, int seed, long size)
208 {
209 Console.WriteLine("Generating random file {0} (seed={1}, size={2})",
210 path, seed, size);
211 Random random = new Random(seed);
212 bool easy = random.Next(2) == 1;
213 int chunk = 1024 * random.Next(1, 100);
214 using (TextWriter tw = new StreamWriter(
215 File.Create(path, 4096), Encoding.ASCII))
216 {
217 for (long count = 0; count < size; count++)
218 {
219 char c = (char) (easy ? random.Next('a', 'b' + 1)
220 : random.Next(32, 127));
221 tw.Write(c);
222 if (--chunk == 0)
223 {
224 chunk = 1024 * random.Next(1, 101);
225 easy = random.Next(2) == 1;
226 }
227 }
228 }
229 }
230
231 public static void TestArchiveInfoNullParams(
232 ArchiveInfo archiveInfo,
233 string dirA,
234 string dirB,
235 string[] files)
236 {
237 Exception caughtEx = null;
238 try
239 {
240 archiveInfo.PackFiles(null, null, files);
241 }
242 catch (Exception ex) { caughtEx = ex; }
243 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
244 caughtEx = null;
245 try
246 {
247 archiveInfo.PackFiles(null, files, new string[] { });
248 }
249 catch (Exception ex) { caughtEx = ex; }
250 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentOutOfRangeException), "Caught exception: " + caughtEx);
251 caughtEx = null;
252 try
253 {
254 archiveInfo.PackFileSet(dirA, null);
255 }
256 catch (Exception ex) { caughtEx = ex; }
257 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
258 caughtEx = null;
259 try
260 {
261 archiveInfo.PackFiles(null, files, files);
262 }
263 catch (Exception ex) { caughtEx = ex; }
264 Assert.IsInstanceOfType(caughtEx, typeof(FileNotFoundException), "Caught exception: " + caughtEx);
265 caughtEx = null;
266 try
267 {
268 archiveInfo.PackFiles(dirA, null, files);
269 }
270 catch (Exception ex) { caughtEx = ex; }
271 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
272 caughtEx = null;
273 try
274 {
275 archiveInfo.PackFiles(dirA, files, null);
276 }
277 catch (Exception ex) { caughtEx = ex; }
278 Assert.IsNull(caughtEx, "Caught exception: " + caughtEx);
279
280 caughtEx = null;
281 try
282 {
283 archiveInfo.CopyTo(null);
284 }
285 catch (Exception ex) { caughtEx = ex; }
286 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
287 caughtEx = null;
288 try
289 {
290 archiveInfo.CopyTo(null, true);
291 }
292 catch (Exception ex) { caughtEx = ex; }
293 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
294 caughtEx = null;
295 try
296 {
297 archiveInfo.MoveTo(null);
298 }
299 catch (Exception ex) { caughtEx = ex; }
300 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
301 caughtEx = null;
302 try
303 {
304 archiveInfo.GetFiles(null);
305 }
306 catch (Exception ex) { caughtEx = ex; }
307 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
308 caughtEx = null;
309 try
310 {
311 archiveInfo.UnpackFile(null, "test.txt");
312 }
313 catch (Exception ex) { caughtEx = ex; }
314 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
315 caughtEx = null;
316 try
317 {
318 archiveInfo.UnpackFile("test.txt", null);
319 }
320 catch (Exception ex) { caughtEx = ex; }
321 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
322 caughtEx = null;
323 try
324 {
325 archiveInfo.UnpackFiles(null, dirB, files);
326 }
327 catch (Exception ex) { caughtEx = ex; }
328 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
329 caughtEx = null;
330 try
331 {
332 archiveInfo.UnpackFiles(files, null, null);
333 }
334 catch (Exception ex) { caughtEx = ex; }
335 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
336 caughtEx = null;
337 try
338 {
339 archiveInfo.UnpackFiles(files, null, files);
340 }
341 catch (Exception ex) { caughtEx = ex; }
342 Assert.IsNull(caughtEx, "Caught exception: " + caughtEx);
343 caughtEx = null;
344 try
345 {
346 archiveInfo.UnpackFiles(files, dirB, null);
347 }
348 catch (Exception ex) { caughtEx = ex; }
349 Assert.IsNull(caughtEx, "Caught exception: " + caughtEx);
350 caughtEx = null;
351 try
352 {
353 archiveInfo.UnpackFiles(files, dirB, new string[] { });
354 }
355 catch (Exception ex) { caughtEx = ex; }
356 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentOutOfRangeException), "Caught exception: " + caughtEx);
357 caughtEx = null;
358 try
359 {
360 archiveInfo.UnpackFileSet(null, dirB);
361 }
362 catch (Exception ex) { caughtEx = ex; }
363 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
364 }
365
366 public static void TestCompressionEngineNullParams(
367 CompressionEngine engine,
368 ArchiveFileStreamContext streamContext,
369 string[] testFiles)
370 {
371 Exception caughtEx;
372
373 Console.WriteLine("Testing null streamContext.");
374 caughtEx = null;
375 try
376 {
377 engine.Pack(null, testFiles);
378 }
379 catch (Exception ex) { caughtEx = ex; }
380 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
381 caughtEx = null;
382 try
383 {
384 engine.Pack(null, testFiles, 0);
385 }
386 catch (Exception ex) { caughtEx = ex; }
387 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
388
389 Console.WriteLine("Testing null files.");
390 caughtEx = null;
391 try
392 {
393 engine.Pack(streamContext, null);
394 }
395 catch (Exception ex) { caughtEx = ex; }
396 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
397
398 Console.WriteLine("Testing null files.");
399 caughtEx = null;
400 try
401 {
402 engine.Pack(streamContext, null, 0);
403 }
404 catch (Exception ex) { caughtEx = ex; }
405 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
406
407
408 Console.WriteLine("Testing null stream.");
409 caughtEx = null;
410 try
411 {
412 engine.IsArchive(null);
413 }
414 catch (Exception ex) { caughtEx = ex; }
415 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
416 caughtEx = null;
417 try
418 {
419 engine.FindArchiveOffset(null);
420 }
421 catch (Exception ex) { caughtEx = ex; }
422 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
423 caughtEx = null;
424 try
425 {
426 engine.GetFiles(null);
427 }
428 catch (Exception ex) { caughtEx = ex; }
429 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
430 caughtEx = null;
431 try
432 {
433 engine.GetFileInfo(null);
434 }
435 catch (Exception ex) { caughtEx = ex; }
436 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
437 caughtEx = null;
438 try
439 {
440 engine.Unpack(null, "testUnpack.txt");
441 }
442 catch (Exception ex) { caughtEx = ex; }
443 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
444 Console.WriteLine("Testing null streamContext.");
445 caughtEx = null;
446 try
447 {
448 engine.GetFiles(null, null);
449 }
450 catch (Exception ex) { caughtEx = ex; }
451 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
452 caughtEx = null;
453 try
454 {
455 engine.GetFileInfo(null, null);
456 }
457 catch (Exception ex) { caughtEx = ex; }
458 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
459 caughtEx = null;
460 try
461 {
462 engine.Unpack((IUnpackStreamContext) null, null);
463 }
464 catch (Exception ex) { caughtEx = ex; }
465 Assert.IsInstanceOfType(caughtEx, typeof(ArgumentNullException), "Caught exception: " + caughtEx);
466 }
467
468 public static void TestBadPackStreamContexts(
469 CompressionEngine engine, string archiveName, string[] testFiles)
470 {
471 Exception caughtEx;
472
473 Console.WriteLine("Testing streamContext that returns null from GetName.");
474 caughtEx = null;
475 try
476 {
477 engine.Pack(
478 new MisbehavingStreamContext(archiveName, null, null, false, false, true, true, true, true),
479 testFiles);
480 }
481 catch (Exception ex) { caughtEx = ex; }
482 Assert.IsTrue(caughtEx is FileNotFoundException, "Caught exception: " + caughtEx);
483 Console.WriteLine("Testing streamContext that returns null from OpenArchive.");
484 caughtEx = null;
485 try
486 {
487 engine.Pack(
488 new MisbehavingStreamContext(archiveName, null, null, false, true, false, true, true, true),
489 testFiles);
490 }
491 catch (Exception ex) { caughtEx = ex; }
492 Assert.IsTrue(caughtEx is FileNotFoundException, "Caught exception: " + caughtEx);
493 Console.WriteLine("Testing streamContext that returns null from OpenFile.");
494 caughtEx = null;
495 try
496 {
497 engine.Pack(
498 new MisbehavingStreamContext(archiveName, null, null, false, true, true, true, false, true),
499 testFiles);
500 }
501 catch (Exception ex) { caughtEx = ex; }
502 Assert.IsNull(caughtEx, "Caught exception: " + caughtEx);
503 Console.WriteLine("Testing streamContext that throws on GetName.");
504 caughtEx = null;
505 try
506 {
507 engine.Pack(
508 new MisbehavingStreamContext(archiveName, null, null, true, false, true, true, true, true),
509 testFiles);
510 }
511 catch (Exception ex) { caughtEx = ex; }
512 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
513 Console.WriteLine("Testing streamContext that throws on OpenArchive.");
514 caughtEx = null;
515 try
516 {
517 engine.Pack(
518 new MisbehavingStreamContext(archiveName, null, null, true, true, false, true, true, true),
519 testFiles);
520 }
521 catch (Exception ex) { caughtEx = ex; }
522 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
523 Console.WriteLine("Testing streamContext that throws on CloseArchive.");
524 caughtEx = null;
525 try
526 {
527 engine.Pack(
528 new MisbehavingStreamContext(archiveName, null, null, true, true, true, false, true, true),
529 testFiles);
530 }
531 catch (Exception ex) { caughtEx = ex; }
532 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
533 Console.WriteLine("Testing streamContext that throws on OpenFile.");
534 caughtEx = null;
535 try
536 {
537 engine.Pack(
538 new MisbehavingStreamContext(archiveName, null, null, true, true, true, true, false, true),
539 testFiles);
540 }
541 catch (Exception ex) { caughtEx = ex; }
542 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
543 Console.WriteLine("Testing streamContext that throws on CloseFile.");
544 caughtEx = null;
545 try
546 {
547 engine.Pack(
548 new MisbehavingStreamContext(archiveName, null, null, true, true, true, true, true, false),
549 testFiles);
550 }
551 catch (Exception ex) { caughtEx = ex; }
552 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
553 }
554
555 public static void TestBadUnpackStreamContexts(
556 CompressionEngine engine, string archiveName)
557 {
558 Exception caughtEx;
559
560 Console.WriteLine("Testing streamContext that returns null from OpenArchive.");
561 caughtEx = null;
562 try
563 {
564 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, false, true, false, true, true, true), null);
565 }
566 catch (Exception ex) { caughtEx = ex; }
567 Assert.IsInstanceOfType(caughtEx, typeof(FileNotFoundException), "Caught exception: " + caughtEx);
568 Console.WriteLine("Testing streamContext that returns null from OpenFile.");
569 caughtEx = null;
570 try
571 {
572 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, false, true, true, true, false, true), null);
573 }
574 catch (Exception ex) { caughtEx = ex; }
575 Assert.IsNull(caughtEx, "Caught exception: " + caughtEx);
576 Console.WriteLine("Testing streamContext that throws on OpenArchive.");
577 caughtEx = null;
578 try
579 {
580 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, true, true, false, true, true, true), null);
581 }
582 catch (Exception ex) { caughtEx = ex; }
583 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
584 Console.WriteLine("Testing streamContext that throws on CloseArchive.");
585 caughtEx = null;
586 try
587 {
588 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, true, true, true, false, true, true), null);
589 }
590 catch (Exception ex) { caughtEx = ex; }
591 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
592 Console.WriteLine("Testing streamContext that throws on OpenFile.");
593 caughtEx = null;
594 try
595 {
596 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, true, true, true, true, false, true), null);
597 }
598 catch (Exception ex) { caughtEx = ex; }
599 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
600 Console.WriteLine("Testing streamContext that throws on CloseFile.");
601 caughtEx = null;
602 try
603 {
604 engine.Unpack(new MisbehavingStreamContext(archiveName, null, null, true, true, true, true, true, false), null);
605 }
606 catch (Exception ex) { caughtEx = ex; }
607 Assert.IsTrue(caughtEx != null && caughtEx.Message == MisbehavingStreamContext.EXCEPTION, "Caught exception: " + caughtEx);
608 }
609
610 public static void TestTruncatedArchive(
611 ArchiveInfo archiveInfo, Type expectedExceptionType)
612 {
613 for (long len = archiveInfo.Length - 1; len >= 0; len--)
614 {
615 string testArchive = String.Format("{0}.{1:d06}",
616 archiveInfo.FullName, len);
617 if (File.Exists(testArchive))
618 {
619 File.Delete(testArchive);
620 }
621
622 archiveInfo.CopyTo(testArchive);
623 using (FileStream truncateStream =
624 File.Open(testArchive, FileMode.Open, FileAccess.ReadWrite))
625 {
626 truncateStream.SetLength(len);
627 }
628
629 ArchiveInfo testArchiveInfo = (ArchiveInfo) archiveInfo.GetType()
630 .GetConstructor(new Type[] { typeof(string) }).Invoke(new object[] { testArchive });
631
632 Exception caughtEx = null;
633 try
634 {
635 testArchiveInfo.GetFiles();
636 }
637 catch (Exception ex) { caughtEx = ex; }
638 File.Delete(testArchive);
639
640 if (caughtEx != null)
641 {
642 Assert.IsInstanceOfType(caughtEx, expectedExceptionType,
643 String.Format("Caught exception listing archive truncated to {0}/{1} bytes",
644 len, archiveInfo.Length));
645 }
646 }
647 }
648 }
649}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression/MisbehavingStreamContext.cs b/src/dtf/test/WixToolsetTests.Dtf.Compression/MisbehavingStreamContext.cs
new file mode 100644
index 00000000..2531f3bc
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression/MisbehavingStreamContext.cs
@@ -0,0 +1,202 @@
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
3using System;
4using System.IO;
5using System.Collections.Generic;
6using WixToolset.Dtf.Compression;
7
8namespace WixToolset.Dtf.Test
9{
10 public class MisbehavingStreamContext : ArchiveFileStreamContext
11 {
12 public const string EXCEPTION = "Test exception.";
13
14 private bool throwEx;
15 private bool getName;
16 private bool openArchive;
17 private bool closeArchive;
18 private bool openFile;
19 private bool closeFile;
20 private int closeFileCount;
21
22 public MisbehavingStreamContext(
23 string cabinetFile,
24 string directory,
25 IDictionary<string, string> files,
26 bool throwEx,
27 bool getName,
28 bool openArchive,
29 bool closeArchive,
30 bool openFile,
31 bool closeFile)
32 : base(cabinetFile, directory, files)
33 {
34 this.throwEx = throwEx;
35 this.getName = getName;
36 this.openArchive = openArchive;
37 this.closeArchive = closeArchive;
38 this.openFile = openFile;
39 this.closeFile = closeFile;
40 }
41
42 public override string GetArchiveName(int archiveNumber)
43 {
44 if (!this.getName)
45 {
46 if (throwEx)
47 {
48 throw new Exception(EXCEPTION);
49 }
50 else
51 {
52 return null;
53 }
54 }
55 return base.GetArchiveName(archiveNumber);
56 }
57
58 public override Stream OpenArchiveWriteStream(
59 int archiveNumber,
60 string archiveName,
61 bool truncate,
62 CompressionEngine compressionEngine)
63 {
64 if (!this.openArchive)
65 {
66 if (throwEx)
67 {
68 throw new Exception(EXCEPTION);
69 }
70 else
71 {
72 return null;
73 }
74 }
75 return base.OpenArchiveWriteStream(
76 archiveNumber, archiveName, truncate, compressionEngine);
77 }
78
79 public override void CloseArchiveWriteStream(
80 int archiveNumber,
81 string archiveName,
82 Stream stream)
83 {
84 if (!this.closeArchive)
85 {
86 if (throwEx)
87 {
88 this.closeArchive = true;
89 throw new Exception(EXCEPTION);
90 }
91 return;
92 }
93 base.CloseArchiveWriteStream(archiveNumber, archiveName, stream);
94 }
95
96 public override Stream OpenFileReadStream(
97 string path,
98 out FileAttributes attributes,
99 out DateTime lastWriteTime)
100 {
101 if (!this.openFile)
102 {
103 if (throwEx)
104 {
105 throw new Exception(EXCEPTION);
106 }
107 else
108 {
109 attributes = FileAttributes.Normal;
110 lastWriteTime = DateTime.MinValue;
111 return null;
112 }
113 }
114 return base.OpenFileReadStream(path, out attributes, out lastWriteTime);
115 }
116
117 public override void CloseFileReadStream(string path, Stream stream)
118 {
119 if (!this.closeFile && ++closeFileCount == 2)
120 {
121 if (throwEx)
122 {
123 throw new Exception(EXCEPTION);
124 }
125 return;
126 }
127 base.CloseFileReadStream(path, stream);
128 }
129
130 public override Stream OpenArchiveReadStream(
131 int archiveNumber,
132 string archiveName,
133 CompressionEngine compressionEngine)
134 {
135 if (!this.openArchive)
136 {
137 if (throwEx)
138 {
139 throw new Exception(EXCEPTION);
140 }
141 else
142 {
143 return null;
144 }
145 }
146 return base.OpenArchiveReadStream(archiveNumber, archiveName, compressionEngine);
147 }
148
149 public override void CloseArchiveReadStream(
150 int archiveNumber,
151 string archiveName,
152 Stream stream)
153 {
154 if (!this.closeArchive)
155 {
156 if (throwEx)
157 {
158 this.closeArchive = true;
159 throw new Exception(EXCEPTION);
160 }
161 return;
162 }
163 base.CloseArchiveReadStream(archiveNumber, archiveName, stream);
164 }
165
166 public override Stream OpenFileWriteStream(
167 string path,
168 long fileSize,
169 DateTime lastWriteTime)
170 {
171 if (!this.openFile)
172 {
173 if (throwEx)
174 {
175 throw new Exception(EXCEPTION);
176 }
177 else
178 {
179 return null;
180 }
181 }
182 return base.OpenFileWriteStream(path, fileSize, lastWriteTime);
183 }
184
185 public override void CloseFileWriteStream(
186 string path,
187 Stream stream,
188 FileAttributes attributes,
189 DateTime lastWriteTime)
190 {
191 if (!this.closeFile && ++closeFileCount == 2)
192 {
193 if (throwEx)
194 {
195 throw new Exception(EXCEPTION);
196 }
197 return;
198 }
199 base.CloseFileWriteStream(path, stream, attributes, lastWriteTime);
200 }
201 }
202}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression/OptionStreamContext.cs b/src/dtf/test/WixToolsetTests.Dtf.Compression/OptionStreamContext.cs
new file mode 100644
index 00000000..98354d97
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression/OptionStreamContext.cs
@@ -0,0 +1,42 @@
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
3using System;
4using System.Collections.Generic;
5using WixToolset.Dtf.Compression;
6
7namespace WixToolset.Dtf.Test
8{
9 public class OptionStreamContext : ArchiveFileStreamContext
10 {
11 private PackOptionHandler packOptionHandler;
12
13 public OptionStreamContext(IList<string> archiveFiles, string directory, IDictionary<string, string> files)
14 : base(archiveFiles, directory, files)
15 {
16 }
17
18 public delegate object PackOptionHandler(string optionName, object[] parameters);
19
20 public PackOptionHandler OptionHandler
21 {
22 get
23 {
24 return this.packOptionHandler;
25 }
26 set
27 {
28 this.packOptionHandler = value;
29 }
30 }
31
32 public override object GetOption(string optionName, object[] parameters)
33 {
34 if (this.OptionHandler == null)
35 {
36 return null;
37 }
38
39 return this.OptionHandler(optionName, parameters);
40 }
41 }
42}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.Compression/WixToolsetTests.Dtf.Compression.csproj b/src/dtf/test/WixToolsetTests.Dtf.Compression/WixToolsetTests.Dtf.Compression.csproj
new file mode 100644
index 00000000..628d36c5
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.Compression/WixToolsetTests.Dtf.Compression.csproj
@@ -0,0 +1,36 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{F045FFC1-05F9-4EA2-9F03-E1CBDB7BC4F9}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.Compression</AssemblyName>
9 <CreateDocumentation>false</CreateDocumentation>
10 <SignOutput>false</SignOutput>
11 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Compile Include="CompressionTestUtil.cs" />
16 <Compile Include="MisbehavingStreamContext.cs" />
17 <Compile Include="OptionStreamContext.cs" />
18 </ItemGroup>
19
20 <ItemGroup>
21 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
22 <Reference Include="System" />
23 <Reference Include="System.Data" />
24 <Reference Include="System.Xml" />
25 </ItemGroup>
26
27 <ItemGroup>
28 <ProjectReference Include="..\..\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj">
29 <Project>{45D81DAB-0559-4836-8106-CE9987FD4AB5}</Project>
30 <Name>WixToolset.Dtf.Compression</Name>
31 </ProjectReference>
32 </ItemGroup>
33
34 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
35 <Target Name="Pack" DependsOnTargets="Build" />
36</Project>
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/CustomActionTest.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/CustomActionTest.cs
new file mode 100644
index 00000000..bf843024
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/CustomActionTest.cs
@@ -0,0 +1,206 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Text;
8 using System.Collections.Generic;
9 using Microsoft.VisualStudio.TestTools.UnitTesting;
10 using WixToolset.Dtf.WindowsInstaller;
11
12 [TestClass]
13 public class CustomActionTest
14 {
15 public CustomActionTest()
16 {
17 }
18
19 [TestMethod]
20 [Ignore] // Currently fails.
21 public void CustomActionTest1()
22 {
23 InstallLogModes logEverything =
24 InstallLogModes.FatalExit |
25 InstallLogModes.Error |
26 InstallLogModes.Warning |
27 InstallLogModes.User |
28 InstallLogModes.Info |
29 InstallLogModes.ResolveSource |
30 InstallLogModes.OutOfDiskSpace |
31 InstallLogModes.ActionStart |
32 InstallLogModes.ActionData |
33 InstallLogModes.CommonData |
34 InstallLogModes.Progress |
35 InstallLogModes.Initialize |
36 InstallLogModes.Terminate |
37 InstallLogModes.ShowDialog;
38
39 Installer.SetInternalUI(InstallUIOptions.Silent);
40 ExternalUIHandler prevHandler = Installer.SetExternalUI(
41 WindowsInstallerTest.ExternalUILogger, logEverything);
42
43 try
44 {
45 string[] customActions = new string[] { "SampleCA1", "SampleCA2" };
46 #if DEBUG
47 string caDir = @"..\..\..\..\..\build\debug\x86\";
48 #else
49 string caDir = @"..\..\..\..\..\build\ship\x86\";
50 #endif
51 caDir = Path.GetFullPath(caDir);
52 string caFile = "WixToolset.Dtf.Samples.ManagedCA.dll";
53 string caProduct = "CustomActionTest.msi";
54
55 this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, false);
56
57 Exception caughtEx = null;
58 try
59 {
60 Installer.InstallProduct(caProduct, String.Empty);
61 }
62 catch (Exception ex) { caughtEx = ex; }
63 Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException),
64 "Exception thrown while installing product: " + caughtEx);
65
66 string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
67 string arch2 = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432");
68 if (arch == "AMD64" || arch2 == "AMD64")
69 {
70 caDir = caDir.Replace("x86", "x64");
71
72 this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, true);
73
74 caughtEx = null;
75 try
76 {
77 Installer.InstallProduct(caProduct, String.Empty);
78 }
79 catch (Exception ex) { caughtEx = ex; }
80 Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException),
81 "Exception thrown while installing 64bit product: " + caughtEx);
82 }
83 }
84 finally
85 {
86 Installer.SetExternalUI(prevHandler, InstallLogModes.None);
87 }
88 }
89
90 private void CreateCustomActionProduct(
91 string msiFile, string customActionFile, IList<string> customActions, bool sixtyFourBit)
92 {
93 using (Database db = new Database(msiFile, DatabaseOpenMode.CreateDirect))
94 {
95 WindowsInstallerUtils.InitializeProductDatabase(db, sixtyFourBit);
96 WindowsInstallerUtils.CreateTestProduct(db);
97
98 if (!File.Exists(customActionFile))
99 throw new FileNotFoundException(customActionFile);
100
101 using (Record binRec = new Record(2))
102 {
103 binRec[1] = Path.GetFileName(customActionFile);
104 binRec.SetStream(2, customActionFile);
105
106 db.Execute("INSERT INTO `Binary` (`Name`, `Data`) VALUES (?, ?)", binRec);
107 }
108
109 using (Record binRec2 = new Record(2))
110 {
111 binRec2[1] = "TestData";
112 binRec2.SetStream(2, new MemoryStream(Encoding.UTF8.GetBytes("This is a test data stream.")));
113
114 db.Execute("INSERT INTO `Binary` (`Name`, `Data`) VALUES (?, ?)", binRec2);
115 }
116
117 for (int i = 0; i < customActions.Count; i++)
118 {
119 db.Execute(
120 "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('{0}', 1, '{1}', '{2}')",
121 customActions[i],
122 Path.GetFileName(customActionFile),
123 customActions[i]);
124 db.Execute(
125 "INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) VALUES ('{0}', '', {1})",
126 customActions[i],
127 101 + i);
128 }
129
130 db.Execute("INSERT INTO `Property` (`Property`, `Value`) VALUES ('SampleCATest', 'TestValue')");
131
132 db.Commit();
133 }
134 }
135
136 [TestMethod]
137 public void CustomActionData()
138 {
139 string dataString = "Key1=Value1;Key2=;Key3;Key4=Value=4;Key5";
140 string dataString2 = "Key1=;Key2=Value2;Key3;Key4;Key6=Value;;6=6;Key7=Value7";
141
142 CustomActionData data = new CustomActionData(dataString);
143 Assert.AreEqual<string>(dataString, data.ToString());
144
145 data["Key1"] = String.Empty;
146 data["Key2"] = "Value2";
147 data["Key4"] = null;
148 data.Remove("Key5");
149 data["Key6"] = "Value;6=6";
150 data["Key7"] = "Value7";
151
152 Assert.AreEqual<string>(dataString2, data.ToString());
153
154 MyDataClass myData = new MyDataClass();
155 myData.Member1 = "test1";
156 myData.Member2 = "test2";
157 data.AddObject("MyData", myData);
158
159 string myDataString = data.ToString();
160 CustomActionData data2 = new CustomActionData(myDataString);
161
162 MyDataClass myData2 = data2.GetObject<MyDataClass>("MyData");
163 Assert.AreEqual<MyDataClass>(myData, myData2);
164
165 List<string> myComplexDataObject = new List<string>();
166 myComplexDataObject.Add("CValue1");
167 myComplexDataObject.Add("CValue2");
168 myComplexDataObject.Add("CValue3");
169
170 CustomActionData myComplexData = new CustomActionData();
171 myComplexData.AddObject("MyComplexData", myComplexDataObject);
172 myComplexData.AddObject("NestedData", data);
173 string myComplexDataString = myComplexData.ToString();
174
175 CustomActionData myComplexData2 = new CustomActionData(myComplexDataString);
176 List<string> myComplexDataObject2 = myComplexData2.GetObject<List<string>>("MyComplexData");
177
178 Assert.AreEqual<int>(myComplexDataObject.Count, myComplexDataObject2.Count);
179 for (int i = 0; i < myComplexDataObject.Count; i++)
180 {
181 Assert.AreEqual<string>(myComplexDataObject[i], myComplexDataObject2[i]);
182 }
183
184 data2 = myComplexData2.GetObject<CustomActionData>("NestedData");
185 Assert.AreEqual<string>(data.ToString(), data2.ToString());
186 }
187
188 public class MyDataClass
189 {
190 public string Member1;
191 public string Member2;
192
193 public override bool Equals(object obj)
194 {
195 MyDataClass other = obj as MyDataClass;
196 return other != null && this.Member1 == other.Member1 && this.Member2 == other.Member2;
197 }
198
199 public override int GetHashCode()
200 {
201 return (this.Member1 != null ? this.Member1.GetHashCode() : 0) ^
202 (this.Member2 != null ? this.Member2.GetHashCode() : 0);
203 }
204 }
205 }
206}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/WixToolsetTests.Dtf.WindowsInstaller.CustomActions.csproj b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/WixToolsetTests.Dtf.WindowsInstaller.CustomActions.csproj
new file mode 100644
index 00000000..a2f45fde
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.CustomActions/WixToolsetTests.Dtf.WindowsInstaller.CustomActions.csproj
@@ -0,0 +1,32 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{137D376B-989F-4FEA-9A67-01D8D38CA0DE}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.WindowsInstaller.CustomActions</AssemblyName>
9 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
10 <CreateDocumentation>false</CreateDocumentation>
11 <SignOutput>false</SignOutput>
12 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <Compile Include="CustomActionTest.cs" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
21 <Reference Include="System" />
22 <Reference Include="System.Windows.Forms" />
23 <Reference Include="$(OutputPath)\WixToolset.Dtf.WindowsInstaller.dll" />
24 <ProjectReference Include="..\WixToolsetTests.Dtf.WindowsInstaller\WixToolsetTests.Dtf.WindowsInstaller.csproj">
25 <Project>{16F5202F-9276-4166-975C-C9654BAF8012}</Project>
26 <Name>WixToolsetTests.Dtf.WindowsInstaller</Name>
27 </ProjectReference>
28 </ItemGroup>
29
30 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
31 <Target Name="Pack" DependsOnTargets="Build" />
32</Project>
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/LinqTest.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/LinqTest.cs
new file mode 100644
index 00000000..7776a1c3
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/LinqTest.cs
@@ -0,0 +1,509 @@
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
3using System;
4using System.Text;
5using System.Collections;
6using System.Collections.Generic;
7using System.Linq;
8using System.Linq.Expressions;
9using Microsoft.VisualStudio.TestTools.UnitTesting;
10using WixToolset.Dtf.WindowsInstaller;
11using WixToolset.Dtf.WindowsInstaller.Linq;
12
13namespace WixToolset.Dtf.Test
14{
15 [TestClass]
16 public class LinqTest
17 {
18 private void InitLinqTestDatabase(QDatabase db)
19 {
20 WindowsInstallerUtils.InitializeProductDatabase(db);
21 WindowsInstallerUtils.CreateTestProduct(db);
22
23 db.Execute(
24 "INSERT INTO `Feature` (`Feature`, `Title`, `Description`, `Level`, `Attributes`) VALUES ('{0}', '{1}', '{2}', {3}, {4})",
25 "TestFeature2",
26 "Test Feature 2",
27 "Test Feature 2 Description",
28 1,
29 (int) FeatureAttributes.None);
30
31 WindowsInstallerUtils.AddRegistryComponent(
32 db, "TestFeature2", "MyTestRegComp",
33 Guid.NewGuid().ToString("B"),
34 "SOFTWARE\\Microsoft\\DTF\\Test",
35 "MyTestRegComp", "test");
36 WindowsInstallerUtils.AddRegistryComponent(
37 db, "TestFeature2", "MyTestRegComp2",
38 Guid.NewGuid().ToString("B"),
39 "SOFTWARE\\Microsoft\\DTF\\Test",
40 "MyTestRegComp2", "test2");
41 WindowsInstallerUtils.AddRegistryComponent(
42 db, "TestFeature2", "excludeComp",
43 Guid.NewGuid().ToString("B"),
44 "SOFTWARE\\Microsoft\\DTF\\Test",
45 "MyTestRegComp3", "test3");
46
47 db.Commit();
48
49 db.Log = Console.Out;
50 }
51
52 [TestMethod]
53 public void LinqSimple()
54 {
55 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
56 {
57 this.InitLinqTestDatabase(db);
58
59 var comps = from c in db.Components
60 select c;
61
62 int count = 0;
63 foreach (var c in comps)
64 {
65 Console.WriteLine(c);
66 count++;
67 }
68
69 Assert.AreEqual<int>(4, count);
70 }
71 }
72
73 [TestMethod]
74 public void LinqWhereNull()
75 {
76 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
77 {
78 this.InitLinqTestDatabase(db);
79
80 var features = from f in db.Features
81 where f.Description != null
82 select f;
83
84 int count = 0;
85 foreach (var f in features)
86 {
87 Console.WriteLine(f);
88 Assert.AreEqual<string>("TestFeature2", f.Feature);
89 count++;
90 }
91
92 Assert.AreEqual<int>(1, count);
93
94 var features2 = from f in db.Features
95 where f.Description == null
96 select f;
97
98 count = 0;
99 foreach (var f in features2)
100 {
101 Console.WriteLine(f);
102 Assert.AreEqual<string>("TestFeature1", f.Feature);
103 count++;
104 }
105
106 Assert.AreEqual<int>(1, count);
107 }
108 }
109
110 [TestMethod]
111 public void LinqWhereOperators()
112 {
113 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
114 {
115 this.InitLinqTestDatabase(db);
116
117 for (int i = 0; i < 100; i++)
118 {
119 var newFile = db.Files.NewRecord();
120 newFile.File = "TestFile" + i;
121 newFile.Component_ = "TestComponent";
122 newFile.FileName = "TestFile" + i + ".txt";
123 newFile.FileSize = i % 10;
124 newFile.Sequence = i;
125 newFile.Insert();
126 }
127
128 var files1 = from f in db.Files where f.Sequence < 40 select f;
129 Assert.AreEqual<int>(40, files1.AsEnumerable().Count());
130
131 var files2 = from f in db.Files where f.Sequence <= 40 select f;
132 Assert.AreEqual<int>(41, files2.AsEnumerable().Count());
133
134 var files3 = from f in db.Files where f.Sequence > 40 select f;
135 Assert.AreEqual<int>(59, files3.AsEnumerable().Count());
136
137 var files4 = from f in db.Files where f.Sequence >= 40 select f;
138 Assert.AreEqual<int>(60, files4.AsEnumerable().Count());
139
140 var files5 = from f in db.Files where 40 < f.Sequence select f;
141 Assert.AreEqual<int>(59, files5.AsEnumerable().Count());
142
143 var files6 = from f in db.Files where 40 <= f.Sequence select f;
144 Assert.AreEqual<int>(60, files6.AsEnumerable().Count());
145
146 var files7 = from f in db.Files where 40 > f.Sequence select f;
147 Assert.AreEqual<int>(40, files7.AsEnumerable().Count());
148
149 var files8 = from f in db.Files where 40 >= f.Sequence select f;
150 Assert.AreEqual<int>(41, files8.AsEnumerable().Count());
151
152 var files9 = from f in db.Files where f.Sequence == 40 select f;
153 Assert.AreEqual<int>(40, files9.AsEnumerable().First().Sequence);
154
155 var files10 = from f in db.Files where f.Sequence != 40 select f;
156 Assert.AreEqual<int>(99, files10.AsEnumerable().Count());
157
158 var files11 = from f in db.Files where 40 == f.Sequence select f;
159 Assert.AreEqual<int>(40, files11.AsEnumerable().First().Sequence);
160
161 var files12 = from f in db.Files where 40 != f.Sequence select f;
162 Assert.AreEqual<int>(99, files12.AsEnumerable().Count());
163 }
164 }
165
166 [TestMethod]
167 public void LinqShapeSelect()
168 {
169 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
170 {
171 this.InitLinqTestDatabase(db);
172
173 Console.WriteLine("Running LINQ query 1.");
174 var features1 = from f in db.Features
175 select new { Name = f.Feature,
176 Desc = f.Description };
177
178 int count = 0;
179 foreach (var f in features1)
180 {
181 Console.WriteLine(f);
182 count++;
183 }
184
185 Assert.AreEqual<int>(2, count);
186
187 Console.WriteLine();
188 Console.WriteLine("Running LINQ query 2.");
189 var features2 = from f in db.Features
190 where f.Description != null
191 select new { Name = f.Feature,
192 Desc = f.Description.ToLower() };
193
194 count = 0;
195 foreach (var f in features2)
196 {
197 Console.WriteLine(f);
198 Assert.AreEqual<string>("TestFeature2", f.Name);
199 count++;
200 }
201
202 Assert.AreEqual<int>(1, count);
203 }
204 }
205
206 [TestMethod]
207 public void LinqUpdateNullableString()
208 {
209 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
210 {
211 this.InitLinqTestDatabase(db);
212
213 string newDescription = "New updated feature description.";
214
215 var features = from f in db.Features
216 where f.Description != null
217 select f;
218
219 int count = 0;
220 foreach (var f in features)
221 {
222 Console.WriteLine(f);
223 Assert.AreEqual<string>("TestFeature2", f.Feature);
224 f.Description = newDescription;
225 count++;
226 }
227
228 Assert.AreEqual<int>(1, count);
229
230 var features2 = from f in db.Features
231 where f.Description == newDescription
232 select f;
233 count = 0;
234 foreach (var f in features2)
235 {
236 Console.WriteLine(f);
237 Assert.AreEqual<string>("TestFeature2", f.Feature);
238 f.Description = null;
239 count++;
240 }
241
242 Assert.AreEqual<int>(1, count);
243
244 var features3 = from f in db.Features
245 where f.Description == null
246 select f.Feature;
247 count = 0;
248 foreach (var f in features3)
249 {
250 Console.WriteLine(f);
251 count++;
252 }
253
254 Assert.AreEqual<int>(2, count);
255
256 db.Commit();
257 }
258 }
259
260 [TestMethod]
261 public void LinqInsertDelete()
262 {
263 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
264 {
265 this.InitLinqTestDatabase(db);
266
267 var newProp = db.Properties.NewRecord();
268 newProp.Property = "TestNewProp1";
269 newProp.Value = "TestNewValue";
270 newProp.Insert();
271
272 string prop = (from p in db.Properties
273 where p.Property == "TestNewProp1"
274 select p.Value).AsEnumerable().First();
275 Assert.AreEqual<string>("TestNewValue", prop);
276
277 newProp.Delete();
278
279 int propCount = (from p in db.Properties
280 where p.Property == "TestNewProp1"
281 select p.Value).AsEnumerable().Count();
282 Assert.AreEqual<int>(0, propCount);
283
284 db.Commit();
285 }
286 }
287
288 [TestMethod]
289 public void LinqQueryQRecord()
290 {
291 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
292 {
293 this.InitLinqTestDatabase(db);
294
295 var installFilesSeq = (from a in db["InstallExecuteSequence"]
296 where a["Action"] == "InstallFiles"
297 select a["Sequence"]).AsEnumerable().First();
298 Assert.AreEqual<string>("4000", installFilesSeq);
299 }
300 }
301
302 [TestMethod]
303 public void LinqOrderBy()
304 {
305 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
306 {
307 this.InitLinqTestDatabase(db);
308
309 var actions = from a in db.InstallExecuteSequences
310 orderby a.Sequence
311 select a.Action;
312 foreach (var a in actions)
313 {
314 Console.WriteLine(a);
315 }
316
317 var files = from f in db.Files
318 orderby f.FileSize, f["Sequence"]
319 where f.Attributes == FileAttributes.None
320 select f;
321
322 foreach (var f in files)
323 {
324 Console.WriteLine(f);
325 }
326 }
327 }
328
329 [TestMethod]
330 public void LinqTwoWayJoin()
331 {
332 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
333 {
334 this.InitLinqTestDatabase(db);
335 int count;
336
337 var regs = from r in db.Registries
338 join c in db["Component"] on r.Component_ equals c["Component"]
339 where c["Component"] == "MyTestRegComp" &&
340 r.Root == RegistryRoot.UserOrMachine
341 select new { Reg = r.Registry, Dir = c["Directory_"] };
342
343 count = 0;
344 foreach (var r in regs)
345 {
346 Console.WriteLine(r);
347 count++;
348 }
349 Assert.AreEqual<int>(1, count);
350
351 var regs2 = from r in db.Registries
352 join c in db.Components on r.Component_ equals c.Component
353 where c.Component == "MyTestRegComp" &&
354 r.Root == RegistryRoot.UserOrMachine
355 select new { Reg = r, Dir = c.Directory_ };
356
357 count = 0;
358 foreach (var r in regs2)
359 {
360 Assert.IsNotNull(r.Reg.Registry);
361 Console.WriteLine(r);
362 count++;
363 }
364 Assert.AreEqual<int>(1, count);
365
366 var regs3 = from r in db.Registries
367 join c in db.Components on r.Component_ equals c.Component
368 where c.Component == "MyTestRegComp" &&
369 r.Root == RegistryRoot.UserOrMachine
370 select r;
371
372 count = 0;
373 foreach (var r in regs3)
374 {
375 Assert.IsNotNull(r.Registry);
376 Console.WriteLine(r);
377 count++;
378 }
379 Assert.AreEqual<int>(1, count);
380
381 }
382 }
383
384 [TestMethod]
385 public void LinqFourWayJoin()
386 {
387 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
388 {
389 this.InitLinqTestDatabase(db);
390 int count;
391
392 IList<string> pretest = db.ExecuteStringQuery(
393 "SELECT `Feature`.`Feature` " +
394 "FROM `Feature`, `FeatureComponents`, `Component`, `Registry` " +
395 "WHERE `Feature`.`Feature` = `FeatureComponents`.`Feature_` " +
396 "AND `FeatureComponents`.`Component_` = `Component`.`Component` " +
397 "AND `Component`.`Component` = `Registry`.`Component_` " +
398 "AND (`Registry`.`Registry` = 'MyTestRegCompReg1')");
399 Assert.AreEqual<int>(1, pretest.Count);
400
401 var features = from f in db.Features
402 join fc in db.FeatureComponents on f.Feature equals fc.Feature_
403 join c in db.Components on fc.Component_ equals c.Component
404 join r in db.Registries on c.Component equals r.Component_
405 where r.Registry == "MyTestRegCompReg1"
406 select f.Feature;
407
408 count = 0;
409 foreach (var featureName in features)
410 {
411 Console.WriteLine(featureName);
412 count++;
413 }
414 Assert.AreEqual<int>(1, count);
415
416 }
417 }
418
419 [TestMethod]
420 public void EnumTable()
421 {
422 using (QDatabase db = new QDatabase("testlinq.msi", DatabaseOpenMode.Create))
423 {
424 this.InitLinqTestDatabase(db);
425 int count = 0;
426 foreach (var comp in db.Components)
427 {
428 Console.WriteLine(comp);
429 count++;
430 }
431 Assert.AreNotEqual<int>(0, count);
432 }
433 }
434
435 [TestMethod]
436 public void DatabaseAsQueryable()
437 {
438 using (Database db = new Database("testlinq.msi", DatabaseOpenMode.Create))
439 {
440 WindowsInstallerUtils.InitializeProductDatabase(db);
441 WindowsInstallerUtils.CreateTestProduct(db);
442
443 var comps = from c in db.AsQueryable().Components
444 select c;
445
446 int count = 0;
447 foreach (var c in comps)
448 {
449 Console.WriteLine(c);
450 count++;
451 }
452
453 Assert.AreEqual<int>(1, count);
454 }
455 }
456
457 [TestMethod]
458 public void EnumProducts()
459 {
460 var products = from p in ProductInstallation.AllProducts
461 where p.Publisher == ".NET Foundation"
462 select new { Name = p.ProductName,
463 Ver = p.ProductVersion,
464 Company = p.Publisher,
465 InstallDate = p.InstallDate,
466 PackageCode = p.AdvertisedPackageCode };
467
468 foreach (var p in products)
469 {
470 Console.WriteLine(p);
471 Assert.IsTrue(p.Company == ".NET Foundation");
472 }
473 }
474
475 [TestMethod]
476 public void EnumFeatures()
477 {
478 foreach (var p in ProductInstallation.AllProducts)
479 {
480 Console.WriteLine(p.ProductName);
481
482 foreach (var f in p.Features)
483 {
484 Console.WriteLine("\t" + f.FeatureName);
485 }
486 }
487 }
488
489 [TestMethod]
490 public void EnumComponents()
491 {
492 var comps = from c in ComponentInstallation.AllComponents
493 where c.State == InstallState.Local &&
494 c.Product.Publisher == ".NET Foundation"
495 select c.Path;
496
497 int count = 0;
498 foreach (var c in comps)
499 {
500 if (++count == 100) break;
501
502 Console.WriteLine(c);
503 }
504
505 Assert.AreEqual<int>(100, count);
506 }
507 }
508
509}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/WixToolsetTests.Dtf.WindowsInstaller.Linq.csproj b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/WixToolsetTests.Dtf.WindowsInstaller.Linq.csproj
new file mode 100644
index 00000000..c34494b7
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller.Linq/WixToolsetTests.Dtf.WindowsInstaller.Linq.csproj
@@ -0,0 +1,42 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{4F55F9B8-D8B6-41EB-8796-221B4CD98324}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.Linq</AssemblyName>
9 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
10 <CreateDocumentation>false</CreateDocumentation>
11 <SignOutput>false</SignOutput>
12 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <Compile Include="LinqTest.cs" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
21 <Reference Include="System" />
22 <Reference Include="System.Core" />
23 </ItemGroup>
24
25 <ItemGroup>
26 <ProjectReference Include="..\..\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj">
27 <Project>{85225597-5121-4361-8332-4E3246D5BBF5}</Project>
28 <Name>WixToolset.Dtf.WindowsInstaller</Name>
29 </ProjectReference>
30 <ProjectReference Include="..\..\WixToolset.Dtf.WindowsInstaller.Linq\WixToolset.Dtf.WindowsInstaller.Linq.csproj">
31 <Project>{7E66313B-C6D4-4729-8422-4D1474E0E6F7}</Project>
32 <Name>WixToolset.Dtf.WindowsInstaller.Linq</Name>
33 </ProjectReference>
34 <ProjectReference Include="..\WixToolsetTests.Dtf.WindowsInstaller\WixToolsetTests.Dtf.WindowsInstaller.csproj">
35 <Project>{16F5202F-9276-4166-975C-C9654BAF8012}</Project>
36 <Name>WixToolsetTests.Dtf.WindowsInstaller</Name>
37 </ProjectReference>
38 </ItemGroup>
39
40 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
41 <Target Name="Pack" DependsOnTargets="Build" />
42</Project> \ No newline at end of file
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/EmbeddedExternalUI.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/EmbeddedExternalUI.cs
new file mode 100644
index 00000000..b0fc00a8
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/EmbeddedExternalUI.cs
@@ -0,0 +1,173 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Reflection;
8 using System.Windows.Forms;
9 using System.Globalization;
10 using System.Collections.Generic;
11 using Microsoft.VisualStudio.TestTools.UnitTesting;
12 using WixToolset.Dtf.WindowsInstaller;
13 using View = WixToolset.Dtf.WindowsInstaller.View;
14
15 [TestClass]
16 public class EmbeddedExternalUI
17 {
18 const InstallLogModes TestLogModes =
19 InstallLogModes.FatalExit |
20 InstallLogModes.Error |
21 InstallLogModes.Warning |
22 InstallLogModes.User |
23 InstallLogModes.Info |
24 InstallLogModes.ResolveSource |
25 InstallLogModes.OutOfDiskSpace |
26 InstallLogModes.ActionStart |
27 InstallLogModes.ActionData |
28 InstallLogModes.CommonData;
29
30#if DEBUG
31 const string EmbeddedUISampleBinDir = @"..\..\build\debug\";
32#else
33 const string EmbeddedUISampleBinDir = @"..\..\build\release\";
34#endif
35
36 [TestMethod]
37 [Ignore] // Requires elevation.
38 public void EmbeddedUISingleInstall()
39 {
40 string dbFile = "EmbeddedUISingleInstall.msi";
41 string productCode;
42
43 string uiDir = Path.GetFullPath(EmbeddedExternalUI.EmbeddedUISampleBinDir);
44 string uiFile = "WixToolset.Dtf.Samples.EmbeddedUI.dll";
45
46 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
47 {
48 WindowsInstallerUtils.InitializeProductDatabase(db);
49 WindowsInstallerUtils.CreateTestProduct(db);
50
51 productCode = db.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];
52
53 using (Record uiRec = new Record(5))
54 {
55 uiRec[1] = "TestEmbeddedUI";
56 uiRec[2] = Path.GetFileNameWithoutExtension(uiFile) + ".Wrapper.dll";
57 uiRec[3] = 1;
58 uiRec[4] = (int) (
59 EmbeddedExternalUI.TestLogModes |
60 InstallLogModes.Progress |
61 InstallLogModes.Initialize |
62 InstallLogModes.Terminate |
63 InstallLogModes.ShowDialog);
64 uiRec.SetStream(5, Path.Combine(uiDir, uiFile));
65 db.Execute(db.Tables["MsiEmbeddedUI"].SqlInsertString, uiRec);
66 }
67
68 db.Commit();
69 }
70
71 Installer.SetInternalUI(InstallUIOptions.Full);
72
73 ProductInstallation installation = new ProductInstallation(productCode);
74 Assert.IsFalse(installation.IsInstalled, "Checking that product is not installed before starting.");
75
76 Exception caughtEx = null;
77 try
78 {
79 Installer.EnableLog(EmbeddedExternalUI.TestLogModes, "install.log");
80 Installer.InstallProduct(dbFile, String.Empty);
81 }
82 catch (Exception ex) { caughtEx = ex; }
83 Assert.IsNull(caughtEx, "Exception thrown while installing product: " + caughtEx);
84
85 Assert.IsTrue(installation.IsInstalled, "Checking that product is installed.");
86 Console.WriteLine();
87 Console.WriteLine();
88 Console.WriteLine();
89 Console.WriteLine("===================================================================");
90 Console.WriteLine();
91 Console.WriteLine();
92 Console.WriteLine();
93
94 try
95 {
96 Installer.EnableLog(EmbeddedExternalUI.TestLogModes, "uninstall.log");
97 Installer.InstallProduct(dbFile, "REMOVE=All");
98 }
99 catch (Exception ex) { caughtEx = ex; }
100 Assert.IsNull(caughtEx, "Exception thrown while uninstalling product: " + caughtEx);
101 }
102
103 // This test does not pass if run normally.
104 // It only passes when a failure is injected into the EmbeddedUI launcher.
105 ////[TestMethod]
106 public void EmbeddedUIInitializeFails()
107 {
108 string dbFile = "EmbeddedUIInitializeFails.msi";
109 string productCode;
110
111 string uiDir = Path.GetFullPath(EmbeddedExternalUI.EmbeddedUISampleBinDir);
112 string uiFile = "WixToolset.Dtf.Samples.EmbeddedUI.dll";
113
114 // A number that will be used to check whether a type 19 CA runs.
115 const string magicNumber = "3.14159265358979323846264338327950";
116
117 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
118 {
119 WindowsInstallerUtils.InitializeProductDatabase(db);
120 WindowsInstallerUtils.CreateTestProduct(db);
121
122 const string failureActionName = "EmbeddedUIInitializeFails";
123 db.Execute("INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) " +
124 "VALUES ('{0}', 19, '', 'Logging magic number: {1}')", failureActionName, magicNumber);
125
126 // This type 19 CA (launch condition) is given a condition of 'UILevel = 3' so that it only runs if the
127 // installation is running in BASIC UI mode, which is what we expect if the EmbeddedUI fails to initialize.
128 db.Execute("INSERT INTO `InstallExecuteSequence` (`Action`, `Condition`, `Sequence`) " +
129 "VALUES ('{0}', 'UILevel = 3', 1)", failureActionName);
130
131 productCode = db.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];
132
133 using (Record uiRec = new Record(5))
134 {
135 uiRec[1] = "TestEmbeddedUI";
136 uiRec[2] = Path.GetFileNameWithoutExtension(uiFile) + ".Wrapper.dll";
137 uiRec[3] = 1;
138 uiRec[4] = (int)(
139 EmbeddedExternalUI.TestLogModes |
140 InstallLogModes.Progress |
141 InstallLogModes.Initialize |
142 InstallLogModes.Terminate |
143 InstallLogModes.ShowDialog);
144 uiRec.SetStream(5, Path.Combine(uiDir, uiFile));
145 db.Execute(db.Tables["MsiEmbeddedUI"].SqlInsertString, uiRec);
146 }
147
148 db.Commit();
149 }
150
151 Installer.SetInternalUI(InstallUIOptions.Full);
152
153 ProductInstallation installation = new ProductInstallation(productCode);
154 Assert.IsFalse(installation.IsInstalled, "Checking that product is not installed before starting.");
155
156 string logFile = "install.log";
157 Exception caughtEx = null;
158 try
159 {
160 Installer.EnableLog(EmbeddedExternalUI.TestLogModes, logFile);
161 Installer.InstallProduct(dbFile, String.Empty);
162 }
163 catch (Exception ex) { caughtEx = ex; }
164 Assert.IsInstanceOfType(caughtEx, typeof(InstallerException),
165 "Excpected InstallerException installing product; caught: " + caughtEx);
166
167 Assert.IsFalse(installation.IsInstalled, "Checking that product is not installed.");
168
169 string logText = File.ReadAllText(logFile);
170 Assert.IsTrue(logText.Contains(magicNumber), "Checking that the type 19 custom action ran.");
171 }
172 }
173}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/Schema.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/Schema.cs
new file mode 100644
index 00000000..26c172c9
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/Schema.cs
@@ -0,0 +1,238 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Collections.Generic;
8 using System.Text;
9 using WixToolset.Dtf.WindowsInstaller;
10
11 public static class Schema
12 {
13 public static IList<TableInfo> Tables
14 {
15 get
16 {
17 return new TableInfo[]
18 {
19 Binary,
20 Component,
21 CustomAction,
22 Directory,
23 EmbeddedUI,
24 Feature,
25 FeatureComponents,
26 File,
27 InstallExecuteSequence,
28 Media,
29 Property,
30 Registry
31 };
32 }
33 }
34
35 #region Table data
36
37 public static TableInfo Binary { get { return new TableInfo(
38 "Binary",
39 new ColumnInfo[]
40 {
41 new ColumnInfo("Name", typeof(String), 72, true),
42 new ColumnInfo("Data", typeof(Stream), 0, true),
43 },
44 new string[] { "Name" });
45 } }
46
47 public static TableInfo Component { get { return new TableInfo(
48 "Component",
49 new ColumnInfo[]
50 {
51 new ColumnInfo("Component", typeof(String), 72, true),
52 new ColumnInfo("ComponentId", typeof(String), 38, false),
53 new ColumnInfo("Directory_", typeof(String), 72, true),
54 new ColumnInfo("Attributes", typeof(Int16), 2, true),
55 new ColumnInfo("Condition", typeof(String), 255, false),
56 new ColumnInfo("KeyPath", typeof(String), 72, false),
57 },
58 new string[] { "Component" });
59 } }
60
61 public static TableInfo CustomAction { get { return new TableInfo(
62 "CustomAction",
63 new ColumnInfo[]
64 {
65 new ColumnInfo("Action", typeof(String), 72, true),
66 new ColumnInfo("Type", typeof(Int16), 2, true),
67 new ColumnInfo("Source", typeof(String), 64, false),
68 new ColumnInfo("Target", typeof(String), 255, false),
69 },
70 new string[] { "Action" });
71 } }
72
73 public static TableInfo Directory { get { return new TableInfo(
74 "Directory",
75 new ColumnInfo[]
76 {
77 new ColumnInfo("Directory", typeof(String), 72, true),
78 new ColumnInfo("Directory_Parent", typeof(String), 72, false),
79 new ColumnInfo("DefaultDir", typeof(String), 255, true, false, true),
80 },
81 new string[] { "Directory" });
82 } }
83
84 public static TableInfo EmbeddedUI { get { return new TableInfo(
85 "MsiEmbeddedUI",
86 new ColumnInfo[]
87 {
88 new ColumnInfo("MsiEmbeddedUI", typeof(String), 72, true),
89 new ColumnInfo("FileName", typeof(String), 72, true),
90 new ColumnInfo("Attributes", typeof(Int16), 2, true),
91 new ColumnInfo("MessageFilter", typeof(Int32), 4, false),
92 new ColumnInfo("Data", typeof(Stream), 0, true),
93 },
94 new string[] { "MsiEmbeddedUI" });
95 } }
96
97 public static TableInfo Feature { get { return new TableInfo(
98 "Feature",
99 new ColumnInfo[]
100 {
101 new ColumnInfo("Feature", typeof(String), 38, true),
102 new ColumnInfo("Feature_Parent", typeof(String), 38, false),
103 new ColumnInfo("Title", typeof(String), 64, false, false, true),
104 new ColumnInfo("Description", typeof(String), 64, false, false, true),
105 new ColumnInfo("Display", typeof(Int16), 2, false),
106 new ColumnInfo("Level", typeof(Int16), 2, true),
107 new ColumnInfo("Directory_", typeof(String), 72, false),
108 new ColumnInfo("Attributes", typeof(Int16), 2, true),
109 },
110 new string[] { "Feature" });
111 } }
112
113 public static TableInfo FeatureComponents { get { return new TableInfo(
114 "FeatureComponents",
115 new ColumnInfo[]
116 {
117 new ColumnInfo("Feature_", typeof(String), 38, true),
118 new ColumnInfo("Component_", typeof(String), 72, true),
119 },
120 new string[] { "Feature_", "Component_" });
121 } }
122
123 public static TableInfo File { get { return new TableInfo(
124 "File",
125 new ColumnInfo[]
126 {
127 new ColumnInfo("File", typeof(String), 72, true),
128 new ColumnInfo("Component_", typeof(String), 72, true),
129 new ColumnInfo("FileName", typeof(String), 255, true, false, true),
130 new ColumnInfo("FileSize", typeof(Int32), 4, true),
131 new ColumnInfo("Version", typeof(String), 72, false),
132 new ColumnInfo("Language", typeof(String), 20, false),
133 new ColumnInfo("Attributes", typeof(Int16), 2, false),
134 new ColumnInfo("Sequence", typeof(Int16), 2, true),
135 },
136 new string[] { "File" });
137 } }
138
139 public static TableInfo InstallExecuteSequence { get { return new TableInfo(
140 "InstallExecuteSequence",
141 new ColumnInfo[]
142 {
143 new ColumnInfo("Action", typeof(String), 72, true),
144 new ColumnInfo("Condition", typeof(String), 255, false),
145 new ColumnInfo("Sequence", typeof(Int16), 2, true),
146 },
147 new string[] { "Action" });
148 } }
149
150 public static TableInfo Media { get { return new TableInfo(
151 "Media",
152 new ColumnInfo[]
153 {
154 new ColumnInfo("DiskId", typeof(Int16), 2, true),
155 new ColumnInfo("LastSequence", typeof(Int16), 2, true),
156 new ColumnInfo("DiskPrompt", typeof(String), 64, false, false, true),
157 new ColumnInfo("Cabinet", typeof(String), 255, false),
158 new ColumnInfo("VolumeLabel", typeof(String), 32, false),
159 new ColumnInfo("Source", typeof(String), 32, false),
160 },
161 new string[] { "DiskId" });
162 } }
163
164 public static TableInfo Property { get { return new TableInfo(
165 "Property",
166 new ColumnInfo[]
167 {
168 new ColumnInfo("Property", typeof(String), 72, true),
169 new ColumnInfo("Value", typeof(String), 255, true),
170 },
171 new string[] { "Property" });
172 } }
173
174 public static TableInfo Registry { get { return new TableInfo(
175 "Registry",
176 new ColumnInfo[]
177 {
178 new ColumnInfo("Registry", typeof(String), 72, true),
179 new ColumnInfo("Root", typeof(Int16), 2, true),
180 new ColumnInfo("Key", typeof(String), 255, true, false, true),
181 new ColumnInfo("Name", typeof(String), 255, false, false, true),
182 new ColumnInfo("Value", typeof(String), 0, false, false, true),
183 new ColumnInfo("Component_", typeof(String), 72, true),
184 },
185 new string[] { "Registry" });
186 } }
187
188 #endregion
189
190 }
191
192 public class Action
193 {
194 public readonly string Name;
195 public readonly int Sequence;
196
197 public Action(string name, int sequence)
198 {
199 this.Name = name;
200 this.Sequence = sequence;
201 }
202
203 }
204
205 public class Sequence
206 {
207 public static IList<Action> InstallExecute
208 {
209 get
210 {
211 return new Action[]
212 {
213 new Action("CostInitialize", 800),
214 new Action("FileCost", 900),
215 new Action("CostFinalize", 1000),
216 new Action("InstallValidate", 1400),
217 new Action("InstallInitialize", 1500),
218 new Action("ProcessComponents", 1600),
219 new Action("UnpublishComponents", 1700),
220 new Action("UnpublishFeatures", 1800),
221 new Action("RemoveRegistryValues", 2600),
222 new Action("RemoveFiles", 3500),
223 new Action("RemoveFolders", 3600),
224 new Action("CreateFolders", 3700),
225 new Action("MoveFiles", 3800),
226 new Action("InstallFiles", 4000),
227 new Action("WriteRegistryValues", 5000),
228 new Action("RegisterProduct", 6100),
229 new Action("PublishComponents", 6200),
230 new Action("PublishFeatures", 6300),
231 new Action("PublishProduct", 6400),
232 new Action("InstallFinalize", 6600),
233 };
234 }
235 }
236
237 }
238}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTest.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTest.cs
new file mode 100644
index 00000000..f994dfef
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTest.cs
@@ -0,0 +1,409 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Windows.Forms;
8 using System.Globalization;
9 using System.Collections.Generic;
10 using Microsoft.VisualStudio.TestTools.UnitTesting;
11 using WixToolset.Dtf.WindowsInstaller;
12 using View = WixToolset.Dtf.WindowsInstaller.View;
13
14 [TestClass]
15 public class WindowsInstallerTest
16 {
17 public WindowsInstallerTest()
18 {
19 }
20
21 [TestInitialize()]
22 public void Initialize()
23 {
24 }
25
26 [TestCleanup()]
27 public void Cleanup()
28 {
29 }
30
31 [TestMethod]
32 [Ignore] // Currently fails.
33 public void InstallerErrorMessages()
34 {
35 string msg3002 = Installer.GetErrorMessage(3002);
36 Console.WriteLine("3002=" + msg3002);
37 Assert.IsNotNull(msg3002);
38 Assert.IsTrue(msg3002.Length > 0);
39 }
40
41 [TestMethod]
42 public void InstallerDatabaseSchema()
43 {
44 string dbFile = "InstallerDatabaseSchema.msi";
45
46 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
47 {
48 WindowsInstallerUtils.InitializeProductDatabase(db);
49 db.Commit();
50 }
51
52 Assert.IsTrue(File.Exists(dbFile), "Checking whether created database file " + dbFile + " exists.");
53
54 using (Database db = new Database(dbFile, DatabaseOpenMode.ReadOnly))
55 {
56 TableCollection tables = db.Tables;
57 Assert.AreEqual<int>(Schema.Tables.Count, tables.Count, "Counting tables.");
58 Assert.AreEqual<int>(Schema.Property.Columns.Count, tables["Property"].Columns.Count, "Counting columns in Property table.");
59
60 foreach (TableInfo tableInfo in tables)
61 {
62 Console.WriteLine(tableInfo.Name);
63 foreach (ColumnInfo columnInfo in tableInfo.Columns)
64 {
65 Console.WriteLine("\t{0} {1}", columnInfo.Name, columnInfo.ColumnDefinitionString);
66 }
67 }
68 }
69 }
70
71 [TestMethod]
72 public void InstallerViewTables()
73 {
74 string dbFile = "InstallerViewTables.msi";
75
76 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
77 {
78 WindowsInstallerUtils.InitializeProductDatabase(db);
79 db.Commit();
80
81 using (View view1 = db.OpenView("SELECT `Property`, `Value` FROM `Property` WHERE `Value` IS NOT NULL"))
82 {
83 IList<TableInfo> viewTables = view1.Tables;
84 Assert.IsNotNull(viewTables);
85 Assert.AreEqual<int>(1, viewTables.Count);
86 Assert.AreEqual<String>("Property", viewTables[0].Name);
87 }
88
89 using (View view2 = db.OpenView("INSERT INTO `Property` (`Property`, `Value`) VALUES ('TestViewTables', 1)"))
90 {
91 IList<TableInfo> viewTables = view2.Tables;
92 Assert.IsNotNull(viewTables);
93 Assert.AreEqual<int>(1, viewTables.Count);
94 Assert.AreEqual<String>("Property", viewTables[0].Name);
95 }
96
97 using (View view3 = db.OpenView("UPDATE `Property` SET `Value` = 2 WHERE `Property` = 'TestViewTables'"))
98 {
99 IList<TableInfo> viewTables = view3.Tables;
100 Assert.IsNotNull(viewTables);
101 Assert.AreEqual<int>(1, viewTables.Count);
102 Assert.AreEqual<String>("Property", viewTables[0].Name);
103 }
104
105 using (View view4 = db.OpenView("alter table Property hold"))
106 {
107 IList<TableInfo> viewTables = view4.Tables;
108 Assert.IsNotNull(viewTables);
109 Assert.AreEqual<int>(1, viewTables.Count);
110 Assert.AreEqual<String>("Property", viewTables[0].Name);
111 }
112 }
113 }
114
115 [TestMethod]
116 public void InstallerInstallProduct()
117 {
118 string dbFile = "InstallerInstallProduct.msi";
119 string productCode;
120
121 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
122 {
123 WindowsInstallerUtils.InitializeProductDatabase(db);
124 WindowsInstallerUtils.CreateTestProduct(db);
125
126 productCode = db.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];
127
128 db.Commit();
129 }
130
131 ProductInstallation installation = new ProductInstallation(productCode);
132 Assert.IsFalse(installation.IsInstalled, "Checking that product is not installed before starting.");
133
134 Installer.SetInternalUI(InstallUIOptions.Silent);
135 ExternalUIHandler prevHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUILogger,
136 InstallLogModes.FatalExit |
137 InstallLogModes.Error |
138 InstallLogModes.Warning |
139 InstallLogModes.User |
140 InstallLogModes.Info |
141 InstallLogModes.ResolveSource |
142 InstallLogModes.OutOfDiskSpace |
143 InstallLogModes.ActionStart |
144 InstallLogModes.ActionData |
145 InstallLogModes.CommonData |
146 InstallLogModes.Progress |
147 InstallLogModes.Initialize |
148 InstallLogModes.Terminate |
149 InstallLogModes.ShowDialog);
150 Assert.IsNull(prevHandler, "Checking that returned previous UI handler is null.");
151
152 Exception caughtEx = null;
153 try
154 {
155 Installer.InstallProduct(dbFile, String.Empty);
156 }
157 catch (Exception ex) { caughtEx = ex; }
158 Assert.IsNull(caughtEx, "Exception thrown while installing product: " + caughtEx);
159
160 prevHandler = Installer.SetExternalUI(prevHandler, InstallLogModes.None);
161 Assert.AreEqual<ExternalUIHandler>(WindowsInstallerTest.ExternalUILogger, prevHandler, "Checking that previously-set UI handler is returned.");
162
163 Assert.IsTrue(installation.IsInstalled, "Checking that product is installed.");
164 Console.WriteLine();
165 Console.WriteLine();
166 Console.WriteLine();
167 Console.WriteLine("===================================================================");
168 Console.WriteLine();
169 Console.WriteLine();
170 Console.WriteLine();
171
172 ExternalUIRecordHandler prevRecHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUIRecordLogger,
173 InstallLogModes.FatalExit |
174 InstallLogModes.Error |
175 InstallLogModes.Warning |
176 InstallLogModes.User |
177 InstallLogModes.Info |
178 InstallLogModes.ResolveSource |
179 InstallLogModes.OutOfDiskSpace |
180 InstallLogModes.ActionStart |
181 InstallLogModes.ActionData |
182 InstallLogModes.CommonData |
183 InstallLogModes.Progress |
184 InstallLogModes.Initialize |
185 InstallLogModes.Terminate |
186 InstallLogModes.ShowDialog);
187 Assert.IsNull(prevRecHandler, "Checking that returned previous UI record handler is null.");
188
189 try
190 {
191 Installer.InstallProduct(dbFile, "REMOVE=All");
192 }
193 catch (Exception ex) { caughtEx = ex; }
194 Assert.IsNull(caughtEx, "Exception thrown while installing product: " + caughtEx);
195
196 Assert.IsFalse(installation.IsInstalled, "Checking that product is not installed after removing.");
197
198 prevRecHandler = Installer.SetExternalUI(prevRecHandler, InstallLogModes.None);
199 Assert.AreEqual<ExternalUIRecordHandler>(WindowsInstallerTest.ExternalUIRecordLogger, prevRecHandler, "Checking that previously-set UI record handler is returned.");
200 }
201
202 public static MessageResult ExternalUILogger(
203 InstallMessage messageType,
204 string message,
205 MessageButtons buttons,
206 MessageIcon icon,
207 MessageDefaultButton defaultButton)
208 {
209 Console.WriteLine("{0}: {1}", messageType, message);
210 return MessageResult.None;
211 }
212
213 public static MessageResult ExternalUIRecordLogger(
214 InstallMessage messageType,
215 Record messageRecord,
216 MessageButtons buttons,
217 MessageIcon icon,
218 MessageDefaultButton defaultButton)
219 {
220 if (messageRecord != null)
221 {
222 if (messageRecord.FormatString.Length == 0 && messageRecord.FieldCount > 0)
223 {
224 messageRecord.FormatString = "1: [1] 2: [2] 3: [3] 4: [4] 5: [5]";
225 }
226 Console.WriteLine("{0}: {1}", messageType, messageRecord.ToString());
227 }
228 else
229 {
230 Console.WriteLine("{0}: (null)", messageType);
231 }
232 return MessageResult.None;
233 }
234
235 [TestMethod]
236 [Ignore] // Currently fails.
237 public void InstallerMessageResources()
238 {
239 string message1101 = Installer.GetErrorMessage(1101);
240 Console.WriteLine("Message 1101: " + message1101);
241 Assert.IsNotNull(message1101);
242 Assert.IsTrue(message1101.Contains("file"));
243
244 message1101 = Installer.GetErrorMessage(1101, CultureInfo.GetCultureInfo(1033));
245 Console.WriteLine("Message 1101: " + message1101);
246 Assert.IsNotNull(message1101);
247 Assert.IsTrue(message1101.Contains("file"));
248
249 string message2621 = Installer.GetErrorMessage(2621);
250 Console.WriteLine("Message 2621: " + message2621);
251 Assert.IsNotNull(message2621);
252 Assert.IsTrue(message2621.Contains("DLL"));
253
254 string message3002 = Installer.GetErrorMessage(3002);
255 Console.WriteLine("Message 3002: " + message3002);
256 Assert.IsNotNull(message3002);
257 Assert.IsTrue(message3002.Contains("sequencing"));
258 }
259
260 [TestMethod]
261 public void EnumComponentQualifiers()
262 {
263 foreach (ComponentInstallation comp in ComponentInstallation.AllComponents)
264 {
265 bool qualifiers = false;
266 foreach (ComponentInstallation.Qualifier qualifier in comp.Qualifiers)
267 {
268 if (!qualifiers)
269 {
270 Console.WriteLine(comp.Path);
271 qualifiers = true;
272 }
273
274 Console.WriteLine("\t{0}: {1}", qualifier.QualifierCode, qualifier.Data);
275 }
276 }
277 }
278
279 [TestMethod]
280 public void DeleteRecord()
281 {
282 string dbFile = "DeleteRecord.msi";
283
284 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
285 {
286 WindowsInstallerUtils.InitializeProductDatabase(db);
287 WindowsInstallerUtils.CreateTestProduct(db);
288
289 string query = "SELECT `Property`, `Value` FROM `Property` WHERE `Property` = 'UpgradeCode'";
290
291 using (View view = db.OpenView(query))
292 {
293 view.Execute();
294
295 Record rec = view.Fetch();
296
297 Console.WriteLine("Calling ToString() : " + rec);
298
299 view.Delete(rec);
300 }
301
302 Assert.AreEqual(0, db.ExecuteStringQuery(query).Count);
303 }
304 }
305
306 [TestMethod]
307 public void InsertRecordThenTryFormatString()
308 {
309 string dbFile = "InsertRecordThenTryFormatString.msi";
310
311 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
312 {
313 WindowsInstallerUtils.InitializeProductDatabase(db);
314 WindowsInstallerUtils.CreateTestProduct(db);
315
316 string parameterFormatString = "[1]";
317 string[] properties = new string[]
318 {
319 "SonGoku", "Over 9000",
320 };
321
322 string query = "SELECT `Property`, `Value` FROM `Property`";
323
324 using (View view = db.OpenView(query))
325 {
326 using (Record rec = new Record(2))
327 {
328 rec[1] = properties[0];
329 rec[2] = properties[1];
330 rec.FormatString = parameterFormatString;
331 Console.WriteLine("Format String before inserting: " + rec.FormatString);
332 view.Insert(rec);
333
334 Console.WriteLine("Format String after inserting: " + rec.FormatString);
335 // After inserting, the format string is invalid.
336 Assert.AreEqual(String.Empty, rec.ToString());
337
338 // Setting the format string manually makes it valid again.
339 rec.FormatString = parameterFormatString;
340 Assert.AreEqual(properties[0], rec.ToString());
341 }
342 }
343 }
344 }
345
346 [TestMethod]
347 public void SeekRecordThenTryFormatString()
348 {
349 string dbFile = "SeekRecordThenTryFormatString.msi";
350
351 using (Database db = new Database(dbFile, DatabaseOpenMode.CreateDirect))
352 {
353 WindowsInstallerUtils.InitializeProductDatabase(db);
354 WindowsInstallerUtils.CreateTestProduct(db);
355
356 string parameterFormatString = "[1]";
357 string[] properties = new string[]
358 {
359 "SonGoku", "Over 9000",
360 };
361
362 string query = "SELECT `Property`, `Value` FROM `Property`";
363
364 using (View view = db.OpenView(query))
365 {
366 using (Record rec = new Record(2))
367 {
368 rec[1] = properties[0];
369 rec[2] = properties[1];
370 rec.FormatString = parameterFormatString;
371 Console.WriteLine("Record fields before seeking: " + rec[0] + " " + rec[1] + " " + rec[2]);
372 view.Seek(rec);
373
374 //TODO: Why does view.Seek remove the record fields?
375 Console.WriteLine("Record fields after seeking: " + rec[0] + " " + rec[1] + " " + rec[2]);
376 // After inserting, the format string is invalid.
377 Assert.AreEqual(String.Empty, rec.ToString());
378 }
379 }
380 }
381 }
382
383 [TestMethod]
384 public void TestToString()
385 {
386 string defaultString = "1: ";
387 string vegetaShout = "It's OVER 9000!!";
388 string gokuPowerLevel = "9001";
389 string nappaInquiry = "Vegeta, what's the Scouter say about his power level?";
390 string parameterFormatString = "[1]";
391
392 Record rec = new Record(1);
393 Assert.AreEqual(defaultString, rec.ToString(), "Testing default FormatString");
394
395 rec.FormatString = String.Empty;
396 Assert.AreEqual(defaultString, rec.ToString(), "Explicitly set the FormatString to the empty string.");
397
398 rec.FormatString = vegetaShout;
399 Assert.AreEqual(vegetaShout, rec.ToString(), "Testing text only (empty FormatString)");
400
401 rec.FormatString = gokuPowerLevel;
402 Assert.AreEqual(gokuPowerLevel, rec.ToString(), "Testing numbers only from a record that wasn't fetched.");
403
404 Record rec2 = new Record(nappaInquiry);
405 rec2.FormatString = parameterFormatString;
406 Assert.AreEqual(nappaInquiry, rec2.ToString(), "Testing text with a FormatString set.");
407 }
408 }
409}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTransactions.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTransactions.cs
new file mode 100644
index 00000000..3bdf5acd
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerTransactions.cs
@@ -0,0 +1,161 @@
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.Dtf.Test
4{
5 using System;
6 using System.IO;
7 using System.Windows.Forms;
8 using System.Globalization;
9 using System.Collections.Generic;
10 using Microsoft.VisualStudio.TestTools.UnitTesting;
11 using WixToolset.Dtf.WindowsInstaller;
12 using View = WixToolset.Dtf.WindowsInstaller.View;
13
14 [TestClass]
15 public class WindowsInstallerTransactions
16 {
17 [TestInitialize()]
18 public void Initialize()
19 {
20 }
21
22 [TestCleanup()]
23 public void Cleanup()
24 {
25 }
26
27 [TestMethod]
28 [Ignore] // Requires elevation.
29 public void InstallerTransactTwoProducts()
30 {
31 string dbFile1 = "InstallerTransactProduct1.msi";
32 string dbFile2 = "InstallerTransactProduct2.msi";
33 string productCode1;
34 string productCode2;
35
36 using (Database db1 = new Database(dbFile1, DatabaseOpenMode.CreateDirect))
37 {
38 WindowsInstallerUtils.InitializeProductDatabase(db1);
39 WindowsInstallerUtils.CreateTestProduct(db1);
40
41 productCode1 = db1.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];
42
43 db1.Commit();
44 }
45
46 using (Database db2 = new Database(dbFile2, DatabaseOpenMode.CreateDirect))
47 {
48 WindowsInstallerUtils.InitializeProductDatabase(db2);
49 WindowsInstallerUtils.CreateTestProduct(db2);
50
51 productCode2 = db2.ExecuteStringQuery("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")[0];
52
53 db2.Commit();
54 }
55
56 ProductInstallation installation1 = new ProductInstallation(productCode1);
57 ProductInstallation installation2 = new ProductInstallation(productCode2);
58 Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed before starting.");
59 Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed before starting.");
60
61 Installer.SetInternalUI(InstallUIOptions.Silent);
62 ExternalUIHandler prevHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUILogger,
63 InstallLogModes.FatalExit |
64 InstallLogModes.Error |
65 InstallLogModes.Warning |
66 InstallLogModes.User |
67 InstallLogModes.Info |
68 InstallLogModes.ResolveSource |
69 InstallLogModes.OutOfDiskSpace |
70 InstallLogModes.ActionStart |
71 InstallLogModes.ActionData |
72 InstallLogModes.CommonData |
73 InstallLogModes.Progress |
74 InstallLogModes.Initialize |
75 InstallLogModes.Terminate |
76 InstallLogModes.ShowDialog);
77 Assert.IsNull(prevHandler, "Checking that returned previous UI handler is null.");
78
79 Transaction transaction = new Transaction("TestInstallTransaction", TransactionAttributes.None);
80
81 Exception caughtEx = null;
82 try
83 {
84 Installer.InstallProduct(dbFile1, String.Empty);
85 }
86 catch (Exception ex) { caughtEx = ex; }
87 Assert.IsNull(caughtEx, "Exception thrown while installing product 1: " + caughtEx);
88
89 Console.WriteLine();
90 Console.WriteLine("===================================================================");
91 Console.WriteLine();
92
93 try
94 {
95 Installer.InstallProduct(dbFile2, String.Empty);
96 }
97 catch (Exception ex) { caughtEx = ex; }
98 Assert.IsNull(caughtEx, "Exception thrown while installing product 2: " + caughtEx);
99
100 transaction.Commit();
101 transaction.Close();
102
103 prevHandler = Installer.SetExternalUI(prevHandler, InstallLogModes.None);
104 Assert.AreEqual<ExternalUIHandler>(WindowsInstallerTest.ExternalUILogger, prevHandler, "Checking that previously-set UI handler is returned.");
105
106 Assert.IsTrue(installation1.IsInstalled, "Checking that product 1 is installed.");
107 Assert.IsTrue(installation2.IsInstalled, "Checking that product 2 is installed.");
108
109 Console.WriteLine();
110 Console.WriteLine();
111 Console.WriteLine();
112 Console.WriteLine("===================================================================");
113 Console.WriteLine("===================================================================");
114 Console.WriteLine();
115 Console.WriteLine();
116 Console.WriteLine();
117
118 ExternalUIRecordHandler prevRecHandler = Installer.SetExternalUI(WindowsInstallerTest.ExternalUIRecordLogger,
119 InstallLogModes.FatalExit |
120 InstallLogModes.Error |
121 InstallLogModes.Warning |
122 InstallLogModes.User |
123 InstallLogModes.Info |
124 InstallLogModes.ResolveSource |
125 InstallLogModes.OutOfDiskSpace |
126 InstallLogModes.ActionStart |
127 InstallLogModes.ActionData |
128 InstallLogModes.CommonData |
129 InstallLogModes.Progress |
130 InstallLogModes.Initialize |
131 InstallLogModes.Terminate |
132 InstallLogModes.ShowDialog);
133 Assert.IsNull(prevRecHandler, "Checking that returned previous UI record handler is null.");
134
135 transaction = new Transaction("TestUninstallTransaction", TransactionAttributes.None);
136
137 try
138 {
139 Installer.InstallProduct(dbFile1, "REMOVE=All");
140 }
141 catch (Exception ex) { caughtEx = ex; }
142 Assert.IsNull(caughtEx, "Exception thrown while removing product 1: " + caughtEx);
143
144 try
145 {
146 Installer.InstallProduct(dbFile2, "REMOVE=All");
147 }
148 catch (Exception ex) { caughtEx = ex; }
149 Assert.IsNull(caughtEx, "Exception thrown while removing product 2: " + caughtEx);
150
151 transaction.Commit();
152 transaction.Close();
153
154 Assert.IsFalse(installation1.IsInstalled, "Checking that product 1 is not installed after removing.");
155 Assert.IsFalse(installation2.IsInstalled, "Checking that product 2 is not installed after removing.");
156
157 prevRecHandler = Installer.SetExternalUI(prevRecHandler, InstallLogModes.None);
158 Assert.AreEqual<ExternalUIRecordHandler>(WindowsInstallerTest.ExternalUIRecordLogger, prevRecHandler, "Checking that previously-set UI record handler is returned.");
159 }
160 }
161}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerUtils.cs b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerUtils.cs
new file mode 100644
index 00000000..644f1988
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WindowsInstallerUtils.cs
@@ -0,0 +1,174 @@
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.Dtf.Test
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Text;
8 using WixToolset.Dtf.WindowsInstaller;
9
10 public class WindowsInstallerUtils
11 {
12 public static void InitializeProductDatabase(Database db)
13 {
14 InitializeProductDatabase(db, false);
15 }
16
17 public static void InitializeProductDatabase(Database db, bool sixtyFourBit)
18 {
19 db.SummaryInfo.CodePage = (short) Encoding.Default.CodePage;
20 db.SummaryInfo.Title = "Windows Installer Test";
21 db.SummaryInfo.Subject = db.SummaryInfo.Title;
22 db.SummaryInfo.Author = typeof(WindowsInstallerUtils).Assembly.FullName;
23 db.SummaryInfo.CreatingApp = db.SummaryInfo.Author;
24 db.SummaryInfo.Comments = typeof(WindowsInstallerUtils).FullName + ".CreateBasicDatabase()";
25 db.SummaryInfo.Keywords = "Installer,MSI,Database";
26 db.SummaryInfo.PageCount = 300;
27 db.SummaryInfo.WordCount = 0;
28 db.SummaryInfo.RevisionNumber = Guid.NewGuid().ToString("B").ToUpper();
29 db.SummaryInfo.Template = (sixtyFourBit ? "x64" : "Intel") + ";0";
30
31 foreach (TableInfo tableInfo in Schema.Tables)
32 {
33 db.Execute(tableInfo.SqlCreateString);
34 }
35
36 db.Execute("INSERT INTO `Directory` (`Directory`, `DefaultDir`) VALUES ('TARGETDIR', 'SourceDir')");
37 db.Execute("INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) VALUES ('ProgramFilesFolder', 'TARGETDIR', '.')");
38
39 foreach (Action action in Sequence.InstallExecute)
40 {
41 db.Execute("INSERT INTO `InstallExecuteSequence` (`Action`, `Sequence`) VALUES ('{0}', {1})",
42 action.Name, action.Sequence);
43 }
44 }
45
46 public const string UpgradeCode = "{05955FE8-005F-4695-A81F-D559338065BB}";
47
48 public static void CreateTestProduct(Database db)
49 {
50 Guid productGuid = Guid.NewGuid();
51
52 string[] properties = new string[]
53 {
54 "ProductCode", productGuid.ToString("B").ToUpper(),
55 "UpgradeCode", UpgradeCode,
56 "ProductName", "Windows Installer Test Product " + productGuid.ToString("P").ToUpper(),
57 "ProductVersion", "1.0.0.0000",
58 };
59
60 using (View view = db.OpenView("INSERT INTO `Property` (`Property`, `Value`) VALUES (?, ?)"))
61 {
62 using (Record rec = new Record(2))
63 {
64 for (int i = 0; i < properties.Length; i += 2)
65 {
66 rec[1] = properties[i];
67 rec[2] = properties[i + 1];
68 view.Execute(rec);
69 }
70 }
71 }
72
73 int randomId = new Random().Next(10000);
74 string productDir = "TestDir" + randomId;
75 db.Execute(
76 "INSERT INTO `Directory` (`Directory`, `Directory_Parent`, `DefaultDir`) " +
77 "VALUES ('TestDir', 'ProgramFilesFolder', 'TestDir|{0}:.')", productDir);
78
79 string compId = Guid.NewGuid().ToString("B").ToUpper();
80 db.Execute(
81 "INSERT INTO `Component` " +
82 "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " +
83 "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')",
84 "TestRegComp1",
85 compId,
86 "TestDir",
87 (int) ComponentAttributes.RegistryKeyPath,
88 "TestReg1");
89
90 string productReg = "TestReg" + randomId;
91 db.Execute(
92 "INSERT INTO `Registry` (`Registry`, `Root`, `Key`, `Component_`) VALUES ('{0}', {1}, '{2}', '{3}')",
93 "TestReg1",
94 -1,
95 @"Software\Microsoft\Windows Installer Test\" + productReg,
96 "TestRegComp1");
97
98 db.Execute(
99 "INSERT INTO `Feature` (`Feature`, `Title`, `Level`, `Attributes`) VALUES ('{0}', '{1}', {2}, {3})",
100 "TestFeature1",
101 "Test Feature 1",
102 1,
103 (int) FeatureAttributes.None);
104
105 db.Execute(
106 "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')",
107 "TestFeature1",
108 "TestRegComp1");
109 }
110
111 public static void AddFeature(Database db, string featureName)
112 {
113 db.Execute(
114 "INSERT INTO `Feature` (`Feature`, `Title`, `Level`, `Attributes`) VALUES ('{0}', '{1}', {2}, {3})",
115 featureName,
116 featureName,
117 1,
118 (int) FeatureAttributes.None);
119 }
120
121 public static void AddRegistryComponent(Database db,
122 string featureName, string compName, string compId,
123 string keyName, string keyValueName, string value)
124 {
125 db.Execute(
126 "INSERT INTO `Component` " +
127 "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " +
128 "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')",
129 compName,
130 compId,
131 "TestDir",
132 (int) ComponentAttributes.RegistryKeyPath,
133 compName + "Reg1");
134 db.Execute(
135 "INSERT INTO `Registry` (`Registry`, `Root`, `Key`, `Name`, `Value`, `Component_`) VALUES ('{0}', {1}, '{2}', '{3}', '{4}', '{5}')",
136 compName + "Reg1",
137 -1,
138 @"Software\Microsoft\Windows Installer Test\" + keyName,
139 keyValueName,
140 value,
141 compName);
142 db.Execute(
143 "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')",
144 featureName,
145 compName);
146 }
147
148 public static void AddFileComponent(Database db,
149 string featureName, string compName, string compId,
150 string fileKey, string fileName)
151 {
152 db.Execute(
153 "INSERT INTO `Component` " +
154 "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `KeyPath`) " +
155 "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')",
156 compName,
157 compId,
158 "TestDir",
159 (int) ComponentAttributes.None,
160 fileKey);
161 db.Execute(
162 "INSERT INTO `File` " +
163 "(`File`, `Component_`, `FileName`, `FileSize`, `Attributes`, `Sequence`) " +
164 "VALUES ('{0}', '{1}', '{2}', 1, 0, 1)",
165 fileKey,
166 compName,
167 fileName);
168 db.Execute(
169 "INSERT INTO `FeatureComponents` (`Feature_`, `Component_`) VALUES ('{0}', '{1}')",
170 featureName,
171 compName);
172 }
173 }
174}
diff --git a/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WixToolsetTests.Dtf.WindowsInstaller.csproj b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WixToolsetTests.Dtf.WindowsInstaller.csproj
new file mode 100644
index 00000000..eaa273ed
--- /dev/null
+++ b/src/dtf/test/WixToolsetTests.Dtf.WindowsInstaller/WixToolsetTests.Dtf.WindowsInstaller.csproj
@@ -0,0 +1,39 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="Current">
4 <PropertyGroup>
5 <ProjectGuid>{16F5202F-9276-4166-975C-C9654BAF8012}</ProjectGuid>
6 <OutputType>Library</OutputType>
7 <RootNamespace>WixToolsetTests.Dtf</RootNamespace>
8 <AssemblyName>WixToolsetTests.Dtf.WindowsInstaller</AssemblyName>
9 <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
10 <CreateDocumentation>false</CreateDocumentation>
11 <SignOutput>false</SignOutput>
12 <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
13 </PropertyGroup>
14
15 <ItemGroup>
16 <Compile Include="EmbeddedExternalUI.cs" />
17 <Compile Include="Schema.cs" />
18 <Compile Include="WindowsInstallerTest.cs" />
19 <Compile Include="WindowsInstallerTransactions.cs" />
20 <Compile Include="WindowsInstallerUtils.cs" />
21 </ItemGroup>
22
23 <ItemGroup>
24 <Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
25 <Reference Include="System" />
26 <Reference Include="System.Windows.Forms" />
27 <Reference Include="System.Xml" />
28 </ItemGroup>
29
30 <ItemGroup>
31 <ProjectReference Include="..\..\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj">
32 <Project>{85225597-5121-4361-8332-4E3246D5BBF5}</Project>
33 <Name>WixToolset.Dtf.WindowsInstaller</Name>
34 </ProjectReference>
35 </ItemGroup>
36
37 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
38 <Target Name="Pack" DependsOnTargets="Build" />
39</Project>