Statistics
| Branch: | Revision:

root / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight.Tests / Tar / TarTests.cs @ 0eea575a

History | View | Annotate | Download (15.1 kB)

1
using System;
2
using System.IO;
3
using System.Text;
4
using ICSharpCode.SharpZipLib.Silverlight.Tar;
5
using NUnit.Framework;
6

    
7
namespace ICSharpCode.SharpZipLib.Tests.Tar {
8
	
9
	/// <summary>
10
	/// This class contains test cases for Tar archive handling
11
	/// </summary>
12
	[TestFixture]
13
	public class TarTestSuite
14
	{
15
		int entryCount;
16
		
17
		void EntryCounter(TarArchive archive, TarEntry entry, string message)
18
		{
19
			entryCount++;
20
		}
21
		
22
		/// <summary>
23
		/// Test that an empty archive can be created and when read has 0 entries in it
24
		/// </summary>
25
		[Test]
26
		[Category("Tar")]
27
		public void EmptyTar()
28
		{
29
			MemoryStream ms = new MemoryStream();
30
			int recordSize = 0;
31
			using ( TarArchive tarOut = TarArchive.CreateOutputTarArchive(ms) )
32
			{
33
				recordSize = tarOut.RecordSize;
34
			}
35
			
36
			Assert.IsTrue(ms.GetBuffer().Length > 0, "Archive size must be > zero");
37
			Assert.AreEqual(ms.GetBuffer().Length % recordSize, 0, "Archive size must be a multiple of record size");
38
			
39
			MemoryStream ms2 = new MemoryStream();
40
			ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
41
			ms2.Seek(0, SeekOrigin.Begin);
42
			
43
			using ( TarArchive tarIn = TarArchive.CreateInputTarArchive(ms2) )
44
			{
45
				entryCount = 0;
46
				tarIn.ProgressMessageEvent += new ProgressMessageHandler(EntryCounter);
47
				tarIn.ListContents();
48
				Assert.AreEqual(0, entryCount, "Expected 0 tar entries");
49
			}
50
		}
51
		/// <summary>
52
		/// Check that the tar block factor can be varied successfully.
53
		/// </summary>
54
		[Test]
55
		public void BlockFactorHandling()
56
		{
57
			const int MinimumBlockFactor = 1;
58
			const int MaximumBlockFactor = 64;
59
			const int FillFactor = 2;
60

    
61
			for ( int factor = MinimumBlockFactor; factor < MaximumBlockFactor; ++factor)
62
			{
63
				MemoryStream ms = new MemoryStream();
64

    
65
				using ( TarOutputStream tarOut = new TarOutputStream(ms, factor) )
66
				{
67
					TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
68
					entry.Size = (TarBuffer.BlockSize * factor * FillFactor);
69
					tarOut.PutNextEntry(entry);
70

    
71
					byte[] buffer = new byte[TarBuffer.BlockSize];
72

    
73
					Random r = new Random();
74
					r.NextBytes(buffer);
75

    
76
					// Last block is a partial one
77
					for ( int i = 0; i < factor * FillFactor; ++i)
78
					{
79
						tarOut.Write(buffer, 0, buffer.Length);
80
					}
81
				}
82

    
83
				byte[] tarData = ms.ToArray();
84
				Assert.IsNotNull(tarData, "Data written is null");
85

    
86
				// Blocks = Header + Data Blocks + Zero block + Record trailer
87
				int usedBlocks = 1 + (factor * FillFactor) + 1;
88
				int totalBlocks = usedBlocks + (factor - 1);
89
				totalBlocks /= factor;
90
				totalBlocks *= factor;
91

    
92
				Assert.AreEqual(TarBuffer.BlockSize * totalBlocks, tarData.Length, "Tar file should contain {0} blocks in length",
93
					totalBlocks);
94

    
95
				if ( usedBlocks < totalBlocks )
96
				{
97
					// Start at first byte after header.
98
					int byteIndex = TarBuffer.BlockSize * ((factor * FillFactor)+ 1);
99
					while ( byteIndex < tarData.Length )
100
					{
101
						int blockNumber = byteIndex / TarBuffer.BlockSize;
102
						int offset = blockNumber % TarBuffer.BlockSize;
103
						Assert.AreEqual(0, tarData[byteIndex],
104
							string.Format("Trailing block data should be null iteration {0} block {1} offset {2}  index {3}",
105
							factor,
106
							blockNumber, offset, byteIndex));
107
						byteIndex += 1;
108
					}
109
				}
110
			}
111
		}
112

    
113
		
114
		/// <summary>
115
		/// Check that the tar trailer only contains nulls.
116
		/// </summary>
117
		[Test]
118
		public void TrailerContainsNulls()
119
		{
120
			const int TestBlockFactor = 3;
121

    
122
			for ( int iteration = 0; iteration < TestBlockFactor * 2; ++iteration)
123
			{
124
				MemoryStream ms = new MemoryStream();
125

    
126
				using ( TarOutputStream tarOut = new TarOutputStream(ms, TestBlockFactor) )
127
				{
128
					TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
129
					if ( iteration > 0 )
130
					{
131
						entry.Size = (TarBuffer.BlockSize * (iteration - 1)) + 9;
132
					}
133
					tarOut.PutNextEntry(entry);
134

    
135
					byte[] buffer = new byte[TarBuffer.BlockSize];
136

    
137
					Random r = new Random();
138
					r.NextBytes(buffer);
139

    
140
					if ( iteration > 0 )
141
					{
142
						for ( int i = 0; i < iteration - 1; ++i )
143
						{
144
							tarOut.Write(buffer, 0, buffer.Length);
145
						}
146

    
147
						// Last block is a partial one
148
						for ( int i = 1; i < 10; ++i)
149
						{
150
							tarOut.WriteByte((byte)i);
151
						}
152
					}
153
				}
154

    
155
				byte[] tarData = ms.ToArray();
156
				Assert.IsNotNull(tarData, "Data written is null");
157

    
158
				// Blocks = Header + Data Blocks + Zero block + Record trailer
159
				int usedBlocks = 1 + iteration + 1;
160
				int totalBlocks = usedBlocks + (TestBlockFactor - 1);
161
				totalBlocks /= TestBlockFactor;
162
				totalBlocks *= TestBlockFactor;
163

    
164
				Assert.AreEqual(TarBuffer.BlockSize * totalBlocks, tarData.Length,
165
					string.Format("Tar file should be {0} blocks in length", totalBlocks));
166

    
167
				if ( usedBlocks < totalBlocks )
168
				{
169
					// Start at first byte after header.
170
					int byteIndex = TarBuffer.BlockSize * (iteration + 1);
171
					while ( byteIndex < tarData.Length )
172
					{
173
						int blockNumber = byteIndex / TarBuffer.BlockSize;
174
						int offset = blockNumber % TarBuffer.BlockSize;
175
						Assert.AreEqual(0, tarData[byteIndex],
176
							string.Format("Trailing block data should be null iteration {0} block {1} offset {2}  index {3}",
177
							iteration,
178
							blockNumber, offset, byteIndex));
179
						byteIndex += 1;
180
					}
181
				}
182
			}
183
		}
184

    
185
		void TryLongName(string name)
186
		{
187
			MemoryStream ms = new MemoryStream();
188
			using ( TarOutputStream tarOut = new TarOutputStream(ms) )
189
			{
190
				DateTime modTime = DateTime.Now;
191

    
192
				TarEntry entry = TarEntry.CreateTarEntry(name);
193
				tarOut.PutNextEntry(entry);
194
			}
195

    
196
			MemoryStream ms2 = new MemoryStream();
197
			ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
198
			ms2.Seek(0, SeekOrigin.Begin);
199

    
200
			using (TarInputStream tarIn = new TarInputStream(ms2))
201
			{
202
				TarEntry nextEntry = tarIn.GetNextEntry();
203
			
204
				Assert.AreEqual(nextEntry.Name, name, "Name match failure");
205
			}
206
		}
207
		
208
		/// <summary>
209
		/// Check that long names are handled correctly for reading and writing.
210
		/// </summary>
211
		[Test]
212
		[Category("Tar")]
213
		public void LongNames()
214
		{
215
			TryLongName("11111111112222222222333333333344444444445555555555" +
216
			            "6666666666777777777788888888889999999999000000000");
217
			
218
			TryLongName("11111111112222222222333333333344444444445555555555" +
219
			            "66666666667777777777888888888899999999990000000000");
220
			
221
			TryLongName("11111111112222222222333333333344444444445555555555" +
222
			            "66666666667777777777888888888899999999990000000000" +
223
			            "1");
224
			
225
			TryLongName("11111111112222222222333333333344444444445555555555" +
226
			            "66666666667777777777888888888899999999990000000000" +
227
			            "11111111112222222222333333333344444444445555555555" +
228
			            "66666666667777777777888888888899999999990000000000");
229
			
230
			TryLongName("11111111112222222222333333333344444444445555555555" +
231
			            "66666666667777777777888888888899999999990000000000" +
232
			            "11111111112222222222333333333344444444445555555555" +
233
			            "66666666667777777777888888888899999999990000000000" +
234
			            "11111111112222222222333333333344444444445555555555" +
235
			            "66666666667777777777888888888899999999990000000000" +
236
			            "11111111112222222222333333333344444444445555555555" +
237
			            "66666666667777777777888888888899999999990000000000" +
238
			            "11111111112222222222333333333344444444445555555555" +
239
			            "66666666667777777777888888888899999999990000000000");
240
			
241
			for (int n = 1; n < 1024; ++n)
242
			{
243
				string format = "{0," + n + "}";
244
				string formatted = string.Format(format, "A");
245
				TryLongName(formatted);
246
			}
247
		}
248

    
249
		/// <summary>
250
		/// Test equals function for tar headers.
251
		/// </summary>
252
		[Test]
253
		[Category("Tar")]
254
		public void HeaderEquality()
255
		{
256
			TarHeader h1 = new TarHeader();
257
			TarHeader h2 = new TarHeader();
258

    
259
			Assert.IsTrue(h1.Equals(h2));
260

    
261
			h1.Name = "ABCDEFG";
262
			Assert.IsFalse(h1.Equals(h2));
263
			h2.Name = h1.Name;
264
			Assert.IsTrue(h1.Equals(h2));
265

    
266
			h1.Mode = 33188;
267
			Assert.IsFalse(h1.Equals(h2));
268
			h2.Mode = h1.Mode;
269
			Assert.IsTrue(h1.Equals(h2));
270

    
271
			h1.UserId = 654;
272
			Assert.IsFalse(h1.Equals(h2));
273
			h2.UserId = h1.UserId;
274
			Assert.IsTrue(h1.Equals(h2));
275

    
276
			h1.GroupId = 654;
277
			Assert.IsFalse(h1.Equals(h2));
278
			h2.GroupId = h1.GroupId;
279
			Assert.IsTrue(h1.Equals(h2));
280

    
281
			h1.Size = 654;
282
			Assert.IsFalse(h1.Equals(h2));
283
			h2.Size = h1.Size;
284
			Assert.IsTrue(h1.Equals(h2));
285

    
286
			h1.ModTime = DateTime.Now;
287
			Assert.IsFalse(h1.Equals(h2));
288
			h2.ModTime = h1.ModTime;
289
			Assert.IsTrue(h1.Equals(h2));
290

    
291
			h1.TypeFlag = 165;
292
			Assert.IsFalse(h1.Equals(h2));
293
			h2.TypeFlag = h1.TypeFlag;
294
			Assert.IsTrue(h1.Equals(h2));
295

    
296
			h1.LinkName = "link";
297
			Assert.IsFalse(h1.Equals(h2));
298
			h2.LinkName = h1.LinkName;
299
			Assert.IsTrue(h1.Equals(h2));
300
		
301
			h1.Magic = "ustar";
302
			Assert.IsFalse(h1.Equals(h2));
303
			h2.Magic = h1.Magic;
304
			Assert.IsTrue(h1.Equals(h2));
305
		
306
			h1.Version = "1";
307
			Assert.IsFalse(h1.Equals(h2));
308
			h2.Version = h1.Version;
309
			Assert.IsTrue(h1.Equals(h2));
310
		
311
			h1.UserName = "user";
312
			Assert.IsFalse(h1.Equals(h2));
313
			h2.UserName = h1.UserName;
314
			Assert.IsTrue(h1.Equals(h2));
315
		
316
			h1.GroupName = "group";
317
			Assert.IsFalse(h1.Equals(h2));
318
			h2.GroupName = h1.GroupName;
319
			Assert.IsTrue(h1.Equals(h2));
320
		
321
		
322
			h1.DevMajor = 165;
323
			Assert.IsFalse(h1.Equals(h2));
324
			h2.DevMajor = h1.DevMajor;
325
			Assert.IsTrue(h1.Equals(h2));
326
		
327
			h1.DevMinor = 164;
328
			Assert.IsFalse(h1.Equals(h2));
329
			h2.DevMinor = h1.DevMinor;
330
			Assert.IsTrue(h1.Equals(h2));
331
			
332
		}
333
		
334
		[Test]
335
		[Category("Tar")]
336
		public void Checksum()
337
		{
338
			MemoryStream ms = new MemoryStream();
339
			using ( TarOutputStream tarOut = new TarOutputStream(ms) )
340
			{
341
				DateTime modTime = DateTime.Now;
342

    
343
				TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
344
				entry.TarHeader.Mode = 12345;
345

    
346
				tarOut.PutNextEntry(entry);
347
			}
348

    
349
			MemoryStream ms2 = new MemoryStream();
350
			ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
351
			ms2.Seek(0, SeekOrigin.Begin);
352
			TarEntry nextEntry;
353

    
354
			using (TarInputStream tarIn = new TarInputStream(ms2))
355
			{
356
				nextEntry = tarIn.GetNextEntry();
357
				Assert.IsTrue(nextEntry.TarHeader.IsChecksumValid, "Checksum should be valid");
358
			}
359

    
360
			MemoryStream ms3 = new MemoryStream();
361
			ms3.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
362
			ms3.Seek(0, SeekOrigin.Begin);
363
			ms3.Write(new byte[1] { 34 }, 0, 1);
364
			ms3.Seek(0, SeekOrigin.Begin);
365

    
366
			using (TarInputStream tarIn = new TarInputStream(ms3))
367
			{
368
				bool trapped = false;
369
			
370
				try
371
				{
372
					nextEntry = tarIn.GetNextEntry();
373
				}
374
				catch (TarException)
375
				{
376
					trapped = true;
377
				}
378
			
379
				Assert.IsTrue(trapped, "Checksum should be invalid");
380
			}
381
		}
382

    
383
		/// <summary>
384
		/// Check that values set are preserved when writing and reading archives.
385
		/// </summary>
386
		[Test]
387
		[Category("Tar")]
388
		public void ValuesPreserved()
389
		{
390
			MemoryStream ms = new MemoryStream();
391
			TarEntry entry;
392
			DateTime modTime = DateTime.Now;
393

    
394
			using (TarOutputStream tarOut = new TarOutputStream(ms))
395
			{
396
				entry = TarEntry.CreateTarEntry("TestEntry");
397
				entry.GroupId = 12;
398
				entry.UserId = 14;
399
				entry.ModTime = modTime;
400
				entry.UserName = "UserName";
401
				entry.GroupName = "GroupName";
402
				entry.TarHeader.Mode = 12345;
403
			
404
				tarOut.PutNextEntry(entry);
405
			}
406

    
407
			MemoryStream ms2 = new MemoryStream();
408
			ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
409
			ms2.Seek(0, SeekOrigin.Begin);
410
			
411
			using (TarInputStream tarIn = new TarInputStream(ms2))
412
			{
413
				TarEntry nextEntry = tarIn.GetNextEntry();
414
				Assert.AreEqual(entry.TarHeader.Checksum, nextEntry.TarHeader.Checksum, "Checksum");
415
			
416
				Assert.IsTrue(nextEntry.Equals(entry), "Entries should be equal");
417
				Assert.IsTrue(nextEntry.TarHeader.Equals(entry.TarHeader), "Headers should match");
418

    
419
				// Tar only stores seconds 
420
				DateTime truncatedTime = new DateTime(modTime.Year, modTime.Month, modTime.Day, 
421
					modTime.Hour, modTime.Minute, modTime.Second);
422
				Assert.AreEqual(truncatedTime, nextEntry.ModTime, "Modtimes should match");
423
			
424
				int entryCount = 0;
425
				while ( nextEntry != null )
426
				{
427
					++entryCount;
428
					nextEntry = tarIn.GetNextEntry();
429
				}
430
			
431
				Assert.AreEqual(1, entryCount, "Expected 1 entry");
432
			}
433
		}
434
		
435
		/// <summary>
436
		/// Check invalid mod times are detected
437
		/// </summary>
438
		[Test]
439
		[ExpectedException(typeof(ArgumentOutOfRangeException))]
440
		public void InvalidModTime()
441
		{
442
			TarEntry e = TarEntry.CreateTarEntry("test");
443
			e.ModTime = DateTime.MinValue;
444
		}
445
		
446
		
447
		/// <summary>
448
		/// Check invalid sizes are detected
449
		/// </summary>
450
		[Test]
451
		[ExpectedException(typeof(ArgumentOutOfRangeException))]
452
		public void InvalidSize()
453
		{
454
			TarEntry e = TarEntry.CreateTarEntry("test");
455
			e.Size = -6;
456
		}
457
		
458
		/// <summary>
459
		/// Check invalid names are detected
460
		/// </summary>
461
		[Test]
462
		[ExpectedException(typeof(ArgumentNullException))]
463
		public void InvalidName()
464
		{
465
			TarEntry e = TarEntry.CreateTarEntry("test");
466
			e.Name = null;
467
		}
468
		
469
		/// <summary>
470
		/// Check setting user and group names.
471
		/// </summary>
472
		[Test]
473
		public void UserAndGroupNames()
474
		{
475
			TarEntry e = TarEntry.CreateTarEntry("test");
476
			e.UserName = null;
477
			Assert.IsNotNull(e.UserName, "Name set to OS default");
478
			e.UserName = "";
479
			Assert.AreEqual(0, e.UserName.Length, "Empty name allowed");
480
			e.GroupName = null;
481
			Assert.AreEqual("None", e.GroupName, "default group name is None");
482
		}
483
		
484
		/// <summary>
485
		/// Check invalid magic values are detected
486
		/// </summary>
487
		[Test]
488
		[ExpectedException(typeof(ArgumentNullException))]
489
		public void InvalidMagic()
490
		{
491
			TarEntry e = TarEntry.CreateTarEntry("test");
492
			e.TarHeader.Magic = null;
493
		}
494
		
495
		/// <summary>
496
		/// Check invalid link names are detected
497
		/// </summary>
498
		[Test]
499
		[ExpectedException(typeof(ArgumentNullException))]
500
		public void InvalidLinkName()
501
		{
502
			TarEntry e = TarEntry.CreateTarEntry("test");
503
			e.TarHeader.LinkName = null;
504
		}
505
		
506
		/// <summary>
507
		/// Check invalid version names are detected
508
		/// </summary>
509
		[Test]
510
		[ExpectedException(typeof(ArgumentNullException))]
511
		public void InvalidVersionName()
512
		{
513
			TarEntry e = TarEntry.CreateTarEntry("test");
514
			e.TarHeader.Version = null;
515
		}
516

    
517
		[Test]
518
		public void CloningAndUniqueness()
519
		{
520
			// Partial test of cloning for TarHeader and TarEntry
521
			TarEntry e = TarEntry.CreateTarEntry("ohsogood");
522
			e.GroupId = 47;
523
			e.GroupName = "GroupName";
524
			e.ModTime = DateTime.Now;
525
			e.Size = 123234;
526

    
527
			TarHeader headerE = e.TarHeader;
528

    
529
			headerE.DevMajor = 99;
530
			headerE.DevMinor = 98;
531
			headerE.LinkName = "LanceLink";
532

    
533
			TarEntry d = (TarEntry)e.Clone();
534

    
535
			Assert.AreEqual(d.File, e.File);
536
			Assert.AreEqual(d.GroupId, e.GroupId);
537
			Assert.AreEqual(d.GroupName, e.GroupName);
538
			Assert.AreEqual(d.IsDirectory, e.IsDirectory);
539
			Assert.AreEqual(d.ModTime, e.ModTime);
540
			Assert.AreEqual(d.Size, e.Size);
541

    
542
			TarHeader headerD = d.TarHeader;
543

    
544
			Assert.AreEqual(headerE.Checksum, headerD.Checksum);
545
			Assert.AreEqual(headerE.LinkName, headerD.LinkName);
546

    
547
			Assert.AreEqual(99, headerD.DevMajor);
548
			Assert.AreEqual(98, headerD.DevMinor);
549

    
550
			Assert.AreEqual("LanceLink", headerD.LinkName);
551

    
552
			TarEntry entryf = new TarEntry(headerD);
553

    
554
			headerD.LinkName = "Something different";
555

    
556
			Assert.AreNotEqual(headerD.LinkName, entryf.TarHeader.LinkName, "Entry headers should be unique");
557
		}
558
	}
559
}