diff options
Diffstat (limited to 'src/dtf/test')
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 | |||
3 | namespace 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 | |||
3 | namespace 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 | |||
3 | using System; | ||
4 | using System.IO; | ||
5 | using System.Text; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Security.Cryptography; | ||
8 | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
9 | using WixToolset.Dtf.Compression; | ||
10 | |||
11 | namespace 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 | |||
3 | using System; | ||
4 | using System.IO; | ||
5 | using System.Collections.Generic; | ||
6 | using WixToolset.Dtf.Compression; | ||
7 | |||
8 | namespace 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 | |||
3 | using System; | ||
4 | using System.Collections.Generic; | ||
5 | using WixToolset.Dtf.Compression; | ||
6 | |||
7 | namespace 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 | |||
3 | namespace 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 | |||
3 | using System; | ||
4 | using System.Text; | ||
5 | using System.Collections; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Linq; | ||
8 | using System.Linq.Expressions; | ||
9 | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
10 | using WixToolset.Dtf.WindowsInstaller; | ||
11 | using WixToolset.Dtf.WindowsInstaller.Linq; | ||
12 | |||
13 | namespace 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 | |||
3 | namespace 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 | |||
3 | namespace 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 | |||
3 | namespace 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 | |||
3 | namespace 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 | |||
3 | namespace 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> | ||