diff --git a/tests/Base/InflaterDeflaterTests.cs b/tests/Base/InflaterDeflaterTests.cs index 4945c0001..b38fadeaf 100644 --- a/tests/Base/InflaterDeflaterTests.cs +++ b/tests/Base/InflaterDeflaterTests.cs @@ -24,39 +24,52 @@ void Inflate(MemoryStream ms, byte[] original, int level, bool zlib) Inflater inflater = new Inflater(!zlib); InflaterInputStream inStream = new InflaterInputStream(ms, inflater); byte[] buf2 = new byte[original.Length]; - int pos = 0; - + + int currentIndex = 0; + int count = buf2.Length; + try { - while (true) { - int numRead = inStream.Read(buf2, pos, 4096); - if (numRead <= 0) { + while (true) + { + int numRead = inStream.Read(buf2, currentIndex, count); + if (numRead <= 0) + { break; } - pos += numRead; + currentIndex += numRead; + count -= numRead; } } catch(Exception ex) { Console.WriteLine("Unexpected exception - '{0}'", ex.Message); + throw; } - - if ( pos != original.Length ) { - Console.WriteLine("Original {0}, new {1}", original.Length, pos); + + if ( currentIndex != original.Length ) + { + Console.WriteLine("Original {0}, new {1}", original.Length, currentIndex); + Assert.Fail("Lengths different"); } - - for (int i = 0; i < original.Length; ++i) { - if ( buf2[i] != original[i] ) { - string description = string.Format("Difference at {0} lvl {1} zlib {2} ", i, level, zlib); - if ( original.Length < 2048 ) { + + for (int i = 0; i < original.Length; ++i) + { + if ( buf2[i] != original[i] ) + { + string description = string.Format("Difference at {0} level {1} zlib {2} ", i, level, zlib); + if ( original.Length < 2048 ) + { StringBuilder builder = new StringBuilder(description); - for (int d = 0; d < original.Length; ++d) { - builder.AppendFormat("{0} ", original[i]); + for (int d = 0; d < original.Length; ++d) + { + builder.AppendFormat("{0} ", original[d]); } - + Assert.Fail(builder.ToString()); } - else { + else + { Assert.Fail(description); } } @@ -65,110 +78,152 @@ void Inflate(MemoryStream ms, byte[] original, int level, bool zlib) MemoryStream Deflate(byte[] data, int level, bool zlib) { - MemoryStream ms = new MemoryStream(); + MemoryStream memoryStream = new MemoryStream(); Deflater deflater = new Deflater(level, !zlib); - DeflaterOutputStream outStream = new DeflaterOutputStream(ms, deflater); - - outStream.Write(data, 0, data.Length); - outStream.Flush(); - outStream.Finish(); - - return ms; + using ( DeflaterOutputStream outStream = new DeflaterOutputStream(memoryStream, deflater) ) + { + outStream.IsStreamOwner = false; + outStream.Write(data, 0, data.Length); + outStream.Flush(); + outStream.Finish(); + } + return memoryStream; } void RandomDeflateInflate(int size, int level, bool zlib) { - byte[] buf = new byte[size]; + byte[] buffer = new byte[size]; System.Random rnd = new Random(); - rnd.NextBytes(buf); + rnd.NextBytes(buffer); - MemoryStream ms = Deflate(buf, level, zlib); - Inflate(ms, buf, level, zlib); + MemoryStream ms = Deflate(buffer, level, zlib); + Inflate(ms, buffer, level, zlib); } /// - /// Random inflate/deflate test using zlib headers. + /// Basic inflate/deflate test /// [Test] [Category("Base")] - public void TestInflateDeflateZlib() + public void InflateDeflateZlib() { - for (int level = 0; level < 10; ++level) { + for (int level = 0; level < 10; ++level) + { RandomDeflateInflate(100000, level, true); } } - /// - /// Random inflate/deflate using non-zlib variant - /// + + delegate void RunCompress(byte[] buffer); + + int runLevel; + bool runZlib; + long runCount = 0; + Random runRandom = new Random(5); + + void DeflateAndInflate(byte[] buffer) + { + ++runCount; + MemoryStream ms = Deflate(buffer, runLevel, runZlib); + Inflate(ms, buffer, runLevel, runZlib); + } + + void TryVariants(RunCompress test, byte[] buffer, int index) + { + int worker = 0; + while ( worker <= 255 ) + { + buffer[index] = (byte)worker; + if ( index < buffer.Length - 1) + { + TryVariants(test, buffer, index + 1); + } + else + { + test(buffer); + } + + worker += runRandom.Next(256); + } + } + + void TryManyVariants(int level, bool zlib, RunCompress test, byte[] buffer) + { + runLevel = level; + runZlib = zlib; + TryVariants(test, buffer, 0); + } + + [Test] [Category("Base")] - public void TestInflateDeflateNonZlib() + public void SmallBlocks() { - for (int level = 0; level < 10; ++level) { - RandomDeflateInflate(100000, level, false); + byte[] buffer = new byte[10]; + Array.Clear(buffer, 0, buffer.Length); + TryManyVariants(0, false, new RunCompress(DeflateAndInflate), buffer); + } + + [Test] + [Category("Base")] + public void FindBug() + { + using ( FileStream fs = File.OpenRead("c:\\tmp\\original.dat") ) + { + long readOffset = 0; + long readLength = fs.Length - readOffset; +// readLength -= 5567; // 5568 works 5567 doesnt.... + + fs.Seek(readOffset, SeekOrigin.Begin); + + byte[] original = new byte[readLength]; + + int bytesRead = fs.Read(original, 0, original.Length); + Assert.AreEqual(bytesRead, original.Length); + + MemoryStream ms = Deflate(original, Deflater.BEST_SPEED, true); + Inflate(ms, original, Deflater.BEST_SPEED, true); } } - + /// /// Basic inflate/deflate test /// [Test] [Category("Base")] - public void TestInflateDeflate() + public void InflateDeflateNonZlib() { - MemoryStream ms = new MemoryStream(); - Deflater deflater = new Deflater(6); - DeflaterOutputStream outStream = new DeflaterOutputStream(ms, deflater); - - byte[] buf = new byte[1000000]; - System.Random rnd = new Random(); - rnd.NextBytes(buf); - - outStream.Write(buf, 0, buf.Length); - outStream.Flush(); - outStream.Finish(); - - ms.Seek(0, SeekOrigin.Begin); - - InflaterInputStream inStream = new InflaterInputStream(ms); - byte[] buf2 = new byte[buf.Length]; - int pos = 0; - while (true) { - int numRead = inStream.Read(buf2, pos, 4096); - if (numRead <= 0) { - break; - } - pos += numRead; - } - - for (int i = 0; i < buf.Length; ++i) { - Assert.AreEqual(buf2[i], buf[i]); + for (int level = 0; level < 10; ++level) + { + RandomDeflateInflate(100000, level, false); } } - + [Test] [Category("Base")] public void CloseDeflatorWithNestedUsing() { string tempFile = null; - try { + try + { tempFile = Path.GetTempPath(); } - catch (SecurityException) { + catch (SecurityException) + { } Assert.IsNotNull(tempFile, "No permission to execute this test?"); - if (tempFile != null) { + if (tempFile != null) + { tempFile = Path.Combine(tempFile, "SharpZipTest.Zip"); - using (FileStream diskFile = File.Create(tempFile)) using (DeflaterOutputStream deflator = new DeflaterOutputStream(diskFile)) - using (StreamWriter txtFile = new StreamWriter(deflator)) { + using (StreamWriter txtFile = new StreamWriter(deflator)) + { txtFile.Write("Hello"); txtFile.Flush(); } - + File.Delete(tempFile); } } @@ -178,29 +233,41 @@ public void CloseDeflatorWithNestedUsing() public void CloseInflatorWithNestedUsing() { string tempFile = null; - try { + try + { tempFile = Path.GetTempPath(); } - catch (SecurityException) { + catch (SecurityException) + { } - + Assert.IsNotNull(tempFile, "No permission to execute this test?"); - if (tempFile != null) { + + if (tempFile != null) + { tempFile = Path.Combine(tempFile, "SharpZipTest.Zip"); using (FileStream diskFile = File.Create(tempFile)) using (DeflaterOutputStream deflator = new DeflaterOutputStream(diskFile)) - using (StreamWriter txtFile = new StreamWriter(deflator)) { - txtFile.Write("Hello"); - txtFile.Flush(); + using (StreamWriter textWriter = new StreamWriter(deflator)) + { + textWriter.Write("Hello"); + textWriter.Flush(); } - - // This wont actually fail... Test is not valid + using (FileStream diskFile = File.OpenRead(tempFile)) using (InflaterInputStream deflator = new InflaterInputStream(diskFile)) - using (StreamReader reader = new StreamReader(deflator)) { - reader.Peek(); + using (StreamReader textReader = new StreamReader(deflator)) + { + char[] buffer = new char[5]; + int readCount = textReader.Read(buffer, 0, 5); + Assert.AreEqual(5, readCount); + + StringBuilder b = new StringBuilder(); + b.Append(buffer); + Assert.AreEqual("Hello", b.ToString()); + } - + File.Delete(tempFile); } } diff --git a/tests/SharpZipLibTests.prjx b/tests/SharpZipLibTests.prjx index 3cb16b184..e5bdd9aa6 100644 --- a/tests/SharpZipLibTests.prjx +++ b/tests/SharpZipLibTests.prjx @@ -14,7 +14,7 @@ - + diff --git a/tests/SharpZipLibTests.sln b/tests/SharpZipLibTests.sln new file mode 100644 index 000000000..bed388da4 --- /dev/null +++ b/tests/SharpZipLibTests.sln @@ -0,0 +1,16 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.1710 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpZipLibTests", "SharpZipLibTests.csproj", "{4F9BF21E-A7FC-4005-A1C7-A17108F7010D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4F9BF21E-A7FC-4005-A1C7-A17108F7010D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F9BF21E-A7FC-4005-A1C7-A17108F7010D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F9BF21E-A7FC-4005-A1C7-A17108F7010D}.Release|Any CPU.Build.0 = Release|Any CPU + {4F9BF21E-A7FC-4005-A1C7-A17108F7010D}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/tests/Tar/TarTests.cs b/tests/Tar/TarTests.cs index 4c1bc7f3d..353fcbd03 100644 --- a/tests/Tar/TarTests.cs +++ b/tests/Tar/TarTests.cs @@ -555,7 +555,7 @@ public void CloningAndUniqueness() headerD.LinkName = "Something different"; - Assert.IsTrue(headerD.LinkName != entryf.TarHeader.LinkName, "Entry headers should be unique"); + Assert.AreNotEqual(headerD.LinkName, entryf.TarHeader.LinkName, "Entry headers should be unique"); } } } diff --git a/tests/Zip/ZipTests.cs b/tests/Zip/ZipTests.cs index 3dc8f7f99..1346482b6 100644 --- a/tests/Zip/ZipTests.cs +++ b/tests/Zip/ZipTests.cs @@ -3,12 +3,14 @@ using System.Reflection; using System.Runtime.Serialization.Formatters.Binary; using System.Security; +using System.Text; using ICSharpCode.SharpZipLib.Zip.Compression; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using ICSharpCode.SharpZipLib.GZip; using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Checksums; +using ICSharpCode.SharpZipLib.Core; using NUnit.Framework; @@ -124,6 +126,35 @@ public bool IsDirectory } #endregion + class MemoryDataSource : IStaticDataSource + { + public MemoryDataSource(byte[] data) + { + data_ = data; + } + + #region IDataSource Members + + public Stream GetSource() + { + return new MemoryStream(data_); + } + + #endregion + + #region Instance Fields + byte[] data_; + #endregion + } + + class StringMemoryDataSource : MemoryDataSource + { + public StringMemoryDataSource(string data) + : base(Encoding.ASCII.GetBytes(data)) + { + } + } + #region ZipBase public class ZipBase { @@ -275,6 +306,23 @@ static void AddKnownDataToEntry(ZipOutputStream zipStream, int size) } } + + #region MakeZipFile Names + protected void MakeZipFile(Stream storage, bool isOwner, string[] names, int size, string comment) + { + using ( ZipOutputStream zOut = new ZipOutputStream(storage) ) + { + zOut.IsStreamOwner = isOwner; + zOut.SetComment(comment); + for (int i = 0; i < names.Length; ++i) + { + zOut.PutNextEntry(new ZipEntry(names[i])); + AddKnownDataToEntry(zOut, size); + } + zOut.Close(); + } + } + protected void MakeZipFile(string name, string[] names, int size, string comment) { using (FileStream fs = File.Create(name)) @@ -292,23 +340,40 @@ protected void MakeZipFile(string name, string[] names, int size, string comment fs.Close(); } } - + #endregion + #region MakeZipFile Entries protected void MakeZipFile(string name, string entryNamePrefix, int entries, int size, string comment) { using (FileStream fs = File.Create(name)) + using (ZipOutputStream zOut = new ZipOutputStream(fs)) { - ZipOutputStream zOut = new ZipOutputStream(fs); zOut.SetComment(comment); for (int i = 0; i < entries; ++i) { zOut.PutNextEntry(new ZipEntry(entryNamePrefix + (i + 1).ToString())); AddKnownDataToEntry(zOut, size); } - zOut.Close(); - fs.Close(); } } + protected void MakeZipFile(Stream storage, bool isOwner, + string entryNamePrefix, int entries, int size, string comment) + { + using ( ZipOutputStream zOut = new ZipOutputStream(storage) ) + { + zOut.IsStreamOwner = isOwner; + zOut.SetComment(comment); + for (int i = 0; i < entries; ++i) + { + zOut.PutNextEntry(new ZipEntry(entryNamePrefix + (i + 1).ToString())); + AddKnownDataToEntry(zOut, size); + } + } + } + + + #endregion + protected static void CheckKnownEntry(Stream inStream, int expectedCount) { byte[] buffer = new byte[1024]; @@ -1171,6 +1236,53 @@ public void NameConversion() CheckNameConversion("Hello"); CheckNameConversion("a/b/c/d/e/f/g/h/SomethingLikeAnArchiveName.txt"); } + + /// + /// Regression test for problem where the password check would fail for an archive whose + /// date was updated from the extra data. + /// This applies to archives where the crc wasnt know at the time of encryption. + /// The date of the entry is used in its place. + /// + [ Test ] + public void PasswordCheckingWithDateInExtraData() + { + MemoryStream ms = new MemoryStream(); + DateTime checkTime = new DateTime(2010, 10, 16, 0, 3, 28); + + using ( ZipOutputStream zos = new ZipOutputStream(ms)) + { + zos.IsStreamOwner = false; + zos.Password = "secret"; + ZipEntry ze = new ZipEntry("uno"); + ze.DateTime = new DateTime(1998, 6, 5, 4, 3, 2); + + ZipExtraData zed = new ZipExtraData(); + + zed.StartNewEntry(); + + zed.AddData(1); + + TimeSpan delta = checkTime.ToUniversalTime() - new System.DateTime ( 1970, 1, 1, 0, 0, 0 ).ToUniversalTime(); + int seconds = (int)delta.TotalSeconds; + zed.AddLeInt(seconds); + zed.AddNewEntry(0x5455); + + ze.ExtraData = zed.GetEntryData(); + zos.PutNextEntry(ze); + zos.WriteByte(54); + } + + ms.Position = 0; + using (ZipInputStream zis = new ZipInputStream(ms) ) + { + zis.Password = "secret"; + ZipEntry uno = zis.GetNextEntry(); + byte theByte = (byte)zis.ReadByte(); + Assert.AreEqual(54, theByte); + Assert.AreEqual(-1, zis.ReadByte()); + Assert.AreEqual(checkTime, uno.DateTime); + } + } } [TestFixture] @@ -1188,7 +1300,7 @@ public void IsDataUnique() extra[0] = 27; a.ExtraData = extra; - ZipEntry b = new ZipEntry(a); + ZipEntry b = (ZipEntry)a.Clone(); b.ExtraData[0] = 89; Assert.IsTrue(b.ExtraData[0] != a.ExtraData[0], "Extra data not unique " + b.ExtraData[0] + " " + a.ExtraData[0]); @@ -1640,11 +1752,138 @@ public void Zip64Entries() zipFile.Add(ze); } zipFile.CommitUpdate(); - zipFile.TestArchive(true); + + Assert.IsTrue(zipFile.TestArchive(true)); Assert.AreEqual(target, zipFile.Count, "Incorrect number of entries stored"); } } + void Compare(byte[] a, byte[] b) + { + Assert.AreEqual(a.Length, b.Length); + for ( int i = 0; i < a.Length; ++i ) + { + Assert.AreEqual(a[i], b[i]); + } + } + + [Test] + [Category("Zip")] + public void EmbeddedArchive() + { + MemoryStream memStream = new MemoryStream(); + using (ZipFile f = new ZipFile(memStream)) + { + f.IsStreamOwner = false; + + StringMemoryDataSource m = new StringMemoryDataSource("0000000"); + f.BeginUpdate(new MemoryArchiveStorage()); + f.Add(m, "a.dat"); + f.Add(m, "b.dat"); + f.CommitUpdate(); + Assert.IsTrue(f.TestArchive(true)); + } + + byte[] rawArchive = memStream.ToArray(); + byte[] pseudoSfx = new byte[1049 + rawArchive.Length]; + Array.Copy(rawArchive, 0, pseudoSfx, 1049, rawArchive.Length); + + memStream = new MemoryStream(pseudoSfx); + using (ZipFile f = new ZipFile(memStream)) + { + for ( int index = 0; index < f.Count; ++index) + { + Stream entryStream = f.GetInputStream(index); + MemoryStream data = new MemoryStream(); + StreamUtils.Copy(entryStream, data, new byte[128]); + string contents = Encoding.ASCII.GetString(data.ToArray()); + Assert.AreEqual("0000000", contents); + } + } + } + + void TryDeleting(byte[] master, int totalEntries, int additions, params int[] toDelete) + { + MemoryStream ms = new MemoryStream(); + ms.Write(master, 0, master.Length); + + using ( ZipFile f = new ZipFile(ms) ) + { + f.IsStreamOwner = false; + Assert.AreEqual(totalEntries, f.Count); + Assert.IsTrue(f.TestArchive(true)); + f.BeginUpdate(new MemoryArchiveStorage()); + + for ( int i = 0; i < additions; ++i ) + { + f.Add(new StringMemoryDataSource("Another great file"), + string.Format("Add{0}.dat", i + 1)); + } + + foreach ( int i in toDelete ) + { + f.Delete(f[i]); + } + f.CommitUpdate(); + +/* write stream to file to assist debugging. + byte[] data = ms.ToArray(); + using ( FileStream fs = File.Open(@"c:\aha.zip", FileMode.Create, FileAccess.ReadWrite, FileShare.Read) ) + { + fs.Write(data, 0, data.Length); + } +*/ + int newTotal = totalEntries + additions - toDelete.Length; + Assert.AreEqual(newTotal, f.Count, + string.Format("Expected {0} entries after update found {1}", newTotal, f.Count)); + Assert.IsTrue(f.TestArchive(true), "Archive test should pass"); + } + } + + [Test] + [Category("Zip")] + public void AddAndDeleteEntriesMemory() + { + MemoryStream memStream = new MemoryStream(); + + using (ZipFile f = new ZipFile(memStream)) + { + f.IsStreamOwner = false; + + f.BeginUpdate(new MemoryArchiveStorage()); + f.Add(new StringMemoryDataSource("Hello world"), "a.dat"); + f.Add(new StringMemoryDataSource("Another"), "b.dat"); + f.Add(new StringMemoryDataSource("Mr C"), "c.dat"); + f.Add(new StringMemoryDataSource("Mrs D was a star"), "d.dat"); + f.CommitUpdate(); + Assert.IsTrue(f.TestArchive(true)); + } + + byte[] master = memStream.ToArray(); + + TryDeleting(master, 4, 0, 0); + TryDeleting(master, 4, 0, 1); + TryDeleting(master, 4, 0, 2); + TryDeleting(master, 4, 0, 3); + TryDeleting(master, 4, 0, 0, 1); + TryDeleting(master, 4, 0, 0, 2); + TryDeleting(master, 4, 0, 0, 3); + TryDeleting(master, 4, 0, 1, 2); + TryDeleting(master, 4, 0, 1, 3); + TryDeleting(master, 4, 0, 2); + + TryDeleting(master, 4, 1, 0); + TryDeleting(master, 4, 1, 1); + TryDeleting(master, 4, 3, 2); + TryDeleting(master, 4, 4, 3); + TryDeleting(master, 4, 10, 0, 1); + TryDeleting(master, 4, 10, 0, 2); + TryDeleting(master, 4, 10, 0, 3); + TryDeleting(master, 4, 20, 1, 2); + TryDeleting(master, 4, 30, 1, 3); + TryDeleting(master, 4, 40, 2); + } + [Test] [Category("Zip")] [Category("CreatesTempFile")] @@ -1667,6 +1906,7 @@ public void AddAndDeleteEntries() f.Add(addFile); f.Add(addFile2); f.CommitUpdate(); + Assert.IsTrue(f.TestArchive(true)); } using ( ZipFile f = new ZipFile(tempFile) ) @@ -1677,16 +1917,17 @@ public void AddAndDeleteEntries() f.Delete(f[0]); f.CommitUpdate(); Assert.AreEqual(1, f.Count); + Assert.IsTrue(f.TestArchive(true)); } File.Delete(addFile); File.Delete(addFile2); File.Delete(tempFile); } + /// /// Simple round trip test for ZipFile class /// - [Test] [Category("Zip")] [Category("CreatesTempFile")] @@ -1707,13 +1948,34 @@ public void RoundTrip() Stream instream = zipFile.GetInputStream(e); CheckKnownEntry(instream, 1024); } - zipFile.Close(); } File.Delete(tempFile); } } + /// + /// Simple round trip test for ZipFile class + /// + [Test] + [Category("Zip")] + [Category("CreatesTempFile")] + public void RoundTripInMemory() + { + MemoryStream storage = new MemoryStream(); + MakeZipFile(storage, false, "", 10, 1024, ""); + + using ( ZipFile zipFile = new ZipFile(storage)) + { + foreach (ZipEntry e in zipFile) + { + Stream instream = zipFile.GetInputStream(e); + CheckKnownEntry(instream, 1024); + } + zipFile.Close(); + } + } + [Test] [Category("Zip")] public void AddToEmptyArchive() @@ -1733,6 +1995,7 @@ public void AddToEmptyArchive() f.Add(addFile); f.CommitUpdate(); Assert.AreEqual(1, f.Count); + Assert.IsTrue(f.TestArchive(true)); } using ( ZipFile f = new ZipFile(tempFile) ) @@ -1742,6 +2005,7 @@ public void AddToEmptyArchive() f.Delete(f[0]); f.CommitUpdate(); Assert.AreEqual(0, f.Count); + Assert.IsTrue(f.TestArchive(true)); f.Close(); } @@ -1765,6 +2029,7 @@ public void CreateEmptyArchive() { f.BeginUpdate(); f.CommitUpdate(); + Assert.IsTrue(f.TestArchive(true)); f.Close(); }