4 using ICSharpCode.SharpZipLib.Silverlight.Tar;
7 namespace ICSharpCode.SharpZipLib.Tests.Tar {
10 /// This class contains test cases for Tar archive handling
13 public class TarTestSuite
17 void EntryCounter(TarArchive archive, TarEntry entry, string message)
23 /// Test that an empty archive can be created and when read has 0 entries in it
27 public void EmptyTar()
29 MemoryStream ms = new MemoryStream();
31 using ( TarArchive tarOut = TarArchive.CreateOutputTarArchive(ms) )
33 recordSize = tarOut.RecordSize;
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");
39 MemoryStream ms2 = new MemoryStream();
40 ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
41 ms2.Seek(0, SeekOrigin.Begin);
43 using ( TarArchive tarIn = TarArchive.CreateInputTarArchive(ms2) )
46 tarIn.ProgressMessageEvent += new ProgressMessageHandler(EntryCounter);
48 Assert.AreEqual(0, entryCount, "Expected 0 tar entries");
52 /// Check that the tar block factor can be varied successfully.
55 public void BlockFactorHandling()
57 const int MinimumBlockFactor = 1;
58 const int MaximumBlockFactor = 64;
59 const int FillFactor = 2;
61 for ( int factor = MinimumBlockFactor; factor < MaximumBlockFactor; ++factor)
63 MemoryStream ms = new MemoryStream();
65 using ( TarOutputStream tarOut = new TarOutputStream(ms, factor) )
67 TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
68 entry.Size = (TarBuffer.BlockSize * factor * FillFactor);
69 tarOut.PutNextEntry(entry);
71 byte[] buffer = new byte[TarBuffer.BlockSize];
73 Random r = new Random();
76 // Last block is a partial one
77 for ( int i = 0; i < factor * FillFactor; ++i)
79 tarOut.Write(buffer, 0, buffer.Length);
83 byte[] tarData = ms.ToArray();
84 Assert.IsNotNull(tarData, "Data written is null");
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;
92 Assert.AreEqual(TarBuffer.BlockSize * totalBlocks, tarData.Length, "Tar file should contain {0} blocks in length",
95 if ( usedBlocks < totalBlocks )
97 // Start at first byte after header.
98 int byteIndex = TarBuffer.BlockSize * ((factor * FillFactor)+ 1);
99 while ( byteIndex < tarData.Length )
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}",
106 blockNumber, offset, byteIndex));
115 /// Check that the tar trailer only contains nulls.
118 public void TrailerContainsNulls()
120 const int TestBlockFactor = 3;
122 for ( int iteration = 0; iteration < TestBlockFactor * 2; ++iteration)
124 MemoryStream ms = new MemoryStream();
126 using ( TarOutputStream tarOut = new TarOutputStream(ms, TestBlockFactor) )
128 TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
131 entry.Size = (TarBuffer.BlockSize * (iteration - 1)) + 9;
133 tarOut.PutNextEntry(entry);
135 byte[] buffer = new byte[TarBuffer.BlockSize];
137 Random r = new Random();
142 for ( int i = 0; i < iteration - 1; ++i )
144 tarOut.Write(buffer, 0, buffer.Length);
147 // Last block is a partial one
148 for ( int i = 1; i < 10; ++i)
150 tarOut.WriteByte((byte)i);
155 byte[] tarData = ms.ToArray();
156 Assert.IsNotNull(tarData, "Data written is null");
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;
164 Assert.AreEqual(TarBuffer.BlockSize * totalBlocks, tarData.Length,
165 string.Format("Tar file should be {0} blocks in length", totalBlocks));
167 if ( usedBlocks < totalBlocks )
169 // Start at first byte after header.
170 int byteIndex = TarBuffer.BlockSize * (iteration + 1);
171 while ( byteIndex < tarData.Length )
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}",
178 blockNumber, offset, byteIndex));
185 void TryLongName(string name)
187 MemoryStream ms = new MemoryStream();
188 using ( TarOutputStream tarOut = new TarOutputStream(ms) )
190 DateTime modTime = DateTime.Now;
192 TarEntry entry = TarEntry.CreateTarEntry(name);
193 tarOut.PutNextEntry(entry);
196 MemoryStream ms2 = new MemoryStream();
197 ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
198 ms2.Seek(0, SeekOrigin.Begin);
200 using (TarInputStream tarIn = new TarInputStream(ms2))
202 TarEntry nextEntry = tarIn.GetNextEntry();
204 Assert.AreEqual(nextEntry.Name, name, "Name match failure");
209 /// Check that long names are handled correctly for reading and writing.
213 public void LongNames()
215 TryLongName("11111111112222222222333333333344444444445555555555" +
216 "6666666666777777777788888888889999999999000000000");
218 TryLongName("11111111112222222222333333333344444444445555555555" +
219 "66666666667777777777888888888899999999990000000000");
221 TryLongName("11111111112222222222333333333344444444445555555555" +
222 "66666666667777777777888888888899999999990000000000" +
225 TryLongName("11111111112222222222333333333344444444445555555555" +
226 "66666666667777777777888888888899999999990000000000" +
227 "11111111112222222222333333333344444444445555555555" +
228 "66666666667777777777888888888899999999990000000000");
230 TryLongName("11111111112222222222333333333344444444445555555555" +
231 "66666666667777777777888888888899999999990000000000" +
232 "11111111112222222222333333333344444444445555555555" +
233 "66666666667777777777888888888899999999990000000000" +
234 "11111111112222222222333333333344444444445555555555" +
235 "66666666667777777777888888888899999999990000000000" +
236 "11111111112222222222333333333344444444445555555555" +
237 "66666666667777777777888888888899999999990000000000" +
238 "11111111112222222222333333333344444444445555555555" +
239 "66666666667777777777888888888899999999990000000000");
241 for (int n = 1; n < 1024; ++n)
243 string format = "{0," + n + "}";
244 string formatted = string.Format(format, "A");
245 TryLongName(formatted);
250 /// Test equals function for tar headers.
254 public void HeaderEquality()
256 TarHeader h1 = new TarHeader();
257 TarHeader h2 = new TarHeader();
259 Assert.IsTrue(h1.Equals(h2));
262 Assert.IsFalse(h1.Equals(h2));
264 Assert.IsTrue(h1.Equals(h2));
267 Assert.IsFalse(h1.Equals(h2));
269 Assert.IsTrue(h1.Equals(h2));
272 Assert.IsFalse(h1.Equals(h2));
273 h2.UserId = h1.UserId;
274 Assert.IsTrue(h1.Equals(h2));
277 Assert.IsFalse(h1.Equals(h2));
278 h2.GroupId = h1.GroupId;
279 Assert.IsTrue(h1.Equals(h2));
282 Assert.IsFalse(h1.Equals(h2));
284 Assert.IsTrue(h1.Equals(h2));
286 h1.ModTime = DateTime.Now;
287 Assert.IsFalse(h1.Equals(h2));
288 h2.ModTime = h1.ModTime;
289 Assert.IsTrue(h1.Equals(h2));
292 Assert.IsFalse(h1.Equals(h2));
293 h2.TypeFlag = h1.TypeFlag;
294 Assert.IsTrue(h1.Equals(h2));
296 h1.LinkName = "link";
297 Assert.IsFalse(h1.Equals(h2));
298 h2.LinkName = h1.LinkName;
299 Assert.IsTrue(h1.Equals(h2));
302 Assert.IsFalse(h1.Equals(h2));
304 Assert.IsTrue(h1.Equals(h2));
307 Assert.IsFalse(h1.Equals(h2));
308 h2.Version = h1.Version;
309 Assert.IsTrue(h1.Equals(h2));
311 h1.UserName = "user";
312 Assert.IsFalse(h1.Equals(h2));
313 h2.UserName = h1.UserName;
314 Assert.IsTrue(h1.Equals(h2));
316 h1.GroupName = "group";
317 Assert.IsFalse(h1.Equals(h2));
318 h2.GroupName = h1.GroupName;
319 Assert.IsTrue(h1.Equals(h2));
323 Assert.IsFalse(h1.Equals(h2));
324 h2.DevMajor = h1.DevMajor;
325 Assert.IsTrue(h1.Equals(h2));
328 Assert.IsFalse(h1.Equals(h2));
329 h2.DevMinor = h1.DevMinor;
330 Assert.IsTrue(h1.Equals(h2));
336 public void Checksum()
338 MemoryStream ms = new MemoryStream();
339 using ( TarOutputStream tarOut = new TarOutputStream(ms) )
341 DateTime modTime = DateTime.Now;
343 TarEntry entry = TarEntry.CreateTarEntry("TestEntry");
344 entry.TarHeader.Mode = 12345;
346 tarOut.PutNextEntry(entry);
349 MemoryStream ms2 = new MemoryStream();
350 ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
351 ms2.Seek(0, SeekOrigin.Begin);
354 using (TarInputStream tarIn = new TarInputStream(ms2))
356 nextEntry = tarIn.GetNextEntry();
357 Assert.IsTrue(nextEntry.TarHeader.IsChecksumValid, "Checksum should be valid");
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);
366 using (TarInputStream tarIn = new TarInputStream(ms3))
368 bool trapped = false;
372 nextEntry = tarIn.GetNextEntry();
379 Assert.IsTrue(trapped, "Checksum should be invalid");
384 /// Check that values set are preserved when writing and reading archives.
388 public void ValuesPreserved()
390 MemoryStream ms = new MemoryStream();
392 DateTime modTime = DateTime.Now;
394 using (TarOutputStream tarOut = new TarOutputStream(ms))
396 entry = TarEntry.CreateTarEntry("TestEntry");
399 entry.ModTime = modTime;
400 entry.UserName = "UserName";
401 entry.GroupName = "GroupName";
402 entry.TarHeader.Mode = 12345;
404 tarOut.PutNextEntry(entry);
407 MemoryStream ms2 = new MemoryStream();
408 ms2.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
409 ms2.Seek(0, SeekOrigin.Begin);
411 using (TarInputStream tarIn = new TarInputStream(ms2))
413 TarEntry nextEntry = tarIn.GetNextEntry();
414 Assert.AreEqual(entry.TarHeader.Checksum, nextEntry.TarHeader.Checksum, "Checksum");
416 Assert.IsTrue(nextEntry.Equals(entry), "Entries should be equal");
417 Assert.IsTrue(nextEntry.TarHeader.Equals(entry.TarHeader), "Headers should match");
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");
425 while ( nextEntry != null )
428 nextEntry = tarIn.GetNextEntry();
431 Assert.AreEqual(1, entryCount, "Expected 1 entry");
436 /// Check invalid mod times are detected
439 [ExpectedException(typeof(ArgumentOutOfRangeException))]
440 public void InvalidModTime()
442 TarEntry e = TarEntry.CreateTarEntry("test");
443 e.ModTime = DateTime.MinValue;
448 /// Check invalid sizes are detected
451 [ExpectedException(typeof(ArgumentOutOfRangeException))]
452 public void InvalidSize()
454 TarEntry e = TarEntry.CreateTarEntry("test");
459 /// Check invalid names are detected
462 [ExpectedException(typeof(ArgumentNullException))]
463 public void InvalidName()
465 TarEntry e = TarEntry.CreateTarEntry("test");
470 /// Check setting user and group names.
473 public void UserAndGroupNames()
475 TarEntry e = TarEntry.CreateTarEntry("test");
477 Assert.IsNotNull(e.UserName, "Name set to OS default");
479 Assert.AreEqual(0, e.UserName.Length, "Empty name allowed");
481 Assert.AreEqual("None", e.GroupName, "default group name is None");
485 /// Check invalid magic values are detected
488 [ExpectedException(typeof(ArgumentNullException))]
489 public void InvalidMagic()
491 TarEntry e = TarEntry.CreateTarEntry("test");
492 e.TarHeader.Magic = null;
496 /// Check invalid link names are detected
499 [ExpectedException(typeof(ArgumentNullException))]
500 public void InvalidLinkName()
502 TarEntry e = TarEntry.CreateTarEntry("test");
503 e.TarHeader.LinkName = null;
507 /// Check invalid version names are detected
510 [ExpectedException(typeof(ArgumentNullException))]
511 public void InvalidVersionName()
513 TarEntry e = TarEntry.CreateTarEntry("test");
514 e.TarHeader.Version = null;
518 public void CloningAndUniqueness()
520 // Partial test of cloning for TarHeader and TarEntry
521 TarEntry e = TarEntry.CreateTarEntry("ohsogood");
523 e.GroupName = "GroupName";
524 e.ModTime = DateTime.Now;
527 TarHeader headerE = e.TarHeader;
529 headerE.DevMajor = 99;
530 headerE.DevMinor = 98;
531 headerE.LinkName = "LanceLink";
533 TarEntry d = (TarEntry)e.Clone();
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);
542 TarHeader headerD = d.TarHeader;
544 Assert.AreEqual(headerE.Checksum, headerD.Checksum);
545 Assert.AreEqual(headerE.LinkName, headerD.LinkName);
547 Assert.AreEqual(99, headerD.DevMajor);
548 Assert.AreEqual(98, headerD.DevMinor);
550 Assert.AreEqual("LanceLink", headerD.LinkName);
552 TarEntry entryf = new TarEntry(headerD);
554 headerD.LinkName = "Something different";
556 Assert.AreNotEqual(headerD.LinkName, entryf.TarHeader.LinkName, "Entry headers should be unique");