Added hammock project to debug streaming issues
[pithos-ms-client] / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight.Tests / Tar / TarTests.cs
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 }