diff --git a/SevenZip.Tests/SevenZip.Tests.csproj b/SevenZip.Tests/SevenZip.Tests.csproj index f8ace8a..01d4d11 100644 --- a/SevenZip.Tests/SevenZip.Tests.csproj +++ b/SevenZip.Tests/SevenZip.Tests.csproj @@ -18,15 +18,16 @@ true - - + + + - + @@ -75,6 +76,24 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/SevenZip.Tests/SevenZipExtractorTests.cs b/SevenZip.Tests/SevenZipExtractorTests.cs index 94b7d78..0a4ae07 100644 --- a/SevenZip.Tests/SevenZipExtractorTests.cs +++ b/SevenZip.Tests/SevenZipExtractorTests.cs @@ -32,6 +32,22 @@ public static List TestFiles return result; } } + /// + /// TestCaseSource for ReadSolidArchive test + /// + public static List SolidArchivesFiles + { + get + { + var result = new List(); + foreach (var file in Directory.GetFiles(Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData_solid"))) + { + result.Add(new TestFile(file)); + } + + return result; + } + } [Test] public void ExtractFilesTest() @@ -85,7 +101,7 @@ public void ExtractionWithCancellationTest() e.Cancel = true; } }; - + tmp.ExtractArchive(OutputDirectory); Assert.AreEqual(2, Directory.GetFiles(OutputDirectory).Length); @@ -160,10 +176,10 @@ public void DetectMultiVolumeIndexTest() [Test] public void ThreadedExtractionTest() { - var destination1 = Path.Combine(OutputDirectory, "t1"); - var destination2 = Path.Combine(OutputDirectory, "t2"); + var destination1 = Path.Combine(OutputDirectory, "t1"); + var destination2 = Path.Combine(OutputDirectory, "t2"); - var t1 = new Thread(() => + var t1 = new Thread(() => { using (var tmp = new SevenZipExtractor(@"TestData\multiple_files.7z")) { @@ -172,8 +188,8 @@ public void ThreadedExtractionTest() }); var t2 = new Thread(() => { - using (var tmp = new SevenZipExtractor(@"TestData\multiple_files.7z")) - { + using (var tmp = new SevenZipExtractor(@"TestData\multiple_files.7z")) + { tmp.ExtractArchive(destination2); } }); @@ -183,11 +199,11 @@ public void ThreadedExtractionTest() t1.Join(); t2.Join(); - Assert.IsTrue(Directory.Exists(destination1)); - Assert.IsTrue(Directory.Exists(destination2)); - Assert.AreEqual(3, Directory.GetFiles(destination1).Length); - Assert.AreEqual(3, Directory.GetFiles(destination2).Length); - } + Assert.IsTrue(Directory.Exists(destination1)); + Assert.IsTrue(Directory.Exists(destination2)); + Assert.AreEqual(3, Directory.GetFiles(destination1).Length); + Assert.AreEqual(3, Directory.GetFiles(destination2).Length); + } [Test] public void ExtractArchiveWithLongPath() @@ -211,7 +227,7 @@ public void ReadArchivedFileNames() Assert.AreEqual("file3.txt", fileNames[2]); } } - + [Test] public void ReadArchivedFileData() { @@ -235,6 +251,108 @@ public void ExtractDifferentFormatsTest(TestFile file) Assert.AreEqual(1, Directory.GetFiles(OutputDirectory).Length); } } + + [Test, TestCaseSource(nameof(SolidArchivesFiles))] + public void ReadStreamFromSolidArchiveTest(TestFile file) + { + using (var extractor = new SevenZipExtractor(file.FilePath)) + { + bool isSolid = Path.GetFileName(file.FilePath).ToLowerInvariant().Contains("solid"); + + var fileData = extractor.ArchiveFileData; + Assert.AreEqual(isSolid, extractor.IsSolid); + Assert.AreEqual(5, fileData.Count); + + // extract files in non-sequential order + foreach (int index in new int[] { 2, 4, 1, 3, 0 }) + { + string content = string.Empty; + using (var stream = new MemoryStream()) + { + extractor.ExtractFile(index, stream); + stream.Seek(0, SeekOrigin.Begin); + + using (TextReader reader = new StreamReader(stream)) + { + content = reader.ReadToEnd(); + } + } + Assert.AreEqual("test file", content); + } + } + } + + [Test, TestCaseSource(nameof(SolidArchivesFiles))] + public void ExtractSpecificFilesFromSolidArchiveTest(TestFile file) + { + using (var extractor = new SevenZipExtractor(file.FilePath)) + { + extractor.ExtractFiles(OutputDirectory, 2, 4); + Assert.AreEqual(2, Directory.GetFiles(OutputDirectory).Length); + } + + Assert.AreEqual(2, Directory.GetFiles(OutputDirectory).Length); + Assert.Contains(Path.Combine(OutputDirectory, "test3.txt"), Directory.GetFiles(OutputDirectory)); + Assert.Contains(Path.Combine(OutputDirectory, "test5.txt"), Directory.GetFiles(OutputDirectory)); + } + + [Test, TestCaseSource(nameof(SolidArchivesFiles))] + public void ExtractFileCallbackFromSolidArchiveTest(TestFile file) + { + using (var extractor = new SevenZipExtractor(file.FilePath)) + { + extractor.ExtractFiles(args => + { + if (args.Reason == ExtractFileCallbackReason.Start && + (args.ArchiveFileInfo.Index == 2 || args.ArchiveFileInfo.Index == 4)) + { + args.ExtractToFile = Path.Combine(OutputDirectory, args.ArchiveFileInfo.FileName); + } + }); + } + + Assert.AreEqual(2, Directory.GetFiles(OutputDirectory).Length); + Assert.Contains(Path.Combine(OutputDirectory, "test3.txt"), Directory.GetFiles(OutputDirectory)); + Assert.Contains(Path.Combine(OutputDirectory, "test5.txt"), Directory.GetFiles(OutputDirectory)); + } + + [Test, TestCaseSource(nameof(SolidArchivesFiles))] + public void ReadStreamCallbackFromSolidArchiveTest(TestFile file) + { + using (var extractor = new SevenZipExtractor(file.FilePath)) + { + extractor.ExtractFiles(args => + { + if (args.Reason == ExtractFileCallbackReason.Start) + { + if (args.ArchiveFileInfo.Index == 2 || args.ArchiveFileInfo.Index == 4) + { + args.ExtractToStream = new MemoryStream(); + } + } + else if (args.Reason == ExtractFileCallbackReason.Done) + { + if (args.ExtractToStream != null) + { + string content = string.Empty; + args.ExtractToStream.Seek(0, SeekOrigin.Begin); + using (TextReader reader = new StreamReader(args.ExtractToStream)) + { + content = reader.ReadToEnd(); + } + Assert.AreEqual("test file", content); + + args.ExtractToStream.Dispose(); + args.ExtractToStream = null; + } + } + else + { + Assert.Fail("Extract file failed " + args.Exception?.Message); + } + }); + } + } } /// diff --git a/SevenZip.Tests/TestData_solid/testFiles.7z b/SevenZip.Tests/TestData_solid/testFiles.7z new file mode 100644 index 0000000..d2fe417 Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.7z differ diff --git a/SevenZip.Tests/TestData_solid/testFiles.rar b/SevenZip.Tests/TestData_solid/testFiles.rar new file mode 100644 index 0000000..7aded5a Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.rar differ diff --git a/SevenZip.Tests/TestData_solid/testFiles.solid.7z b/SevenZip.Tests/TestData_solid/testFiles.solid.7z new file mode 100644 index 0000000..d3c78c4 Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.solid.7z differ diff --git a/SevenZip.Tests/TestData_solid/testFiles.solid.rar b/SevenZip.Tests/TestData_solid/testFiles.solid.rar new file mode 100644 index 0000000..a3820c5 Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.solid.rar differ diff --git a/SevenZip.Tests/TestData_solid/testFiles.tar b/SevenZip.Tests/TestData_solid/testFiles.tar new file mode 100644 index 0000000..2d03cc1 Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.tar differ diff --git a/SevenZip.Tests/TestData_solid/testFiles.zip b/SevenZip.Tests/TestData_solid/testFiles.zip new file mode 100644 index 0000000..7c3802e Binary files /dev/null and b/SevenZip.Tests/TestData_solid/testFiles.zip differ diff --git a/SevenZip/EventArguments/ExtractFileCallbackArgs.cs b/SevenZip/EventArguments/ExtractFileCallbackArgs.cs index 212c811..ace2fa9 100644 --- a/SevenZip/EventArguments/ExtractFileCallbackArgs.cs +++ b/SevenZip/EventArguments/ExtractFileCallbackArgs.cs @@ -89,7 +89,7 @@ public Stream ExtractToStream get => _extractToStream; set { - if (_extractToStream != null && !_extractToStream.CanWrite) + if (value != null && !value.CanWrite) { throw new ExtractionFailedException("The specified stream is not writable!"); } diff --git a/SevenZip/SevenZipExtractor.cs b/SevenZip/SevenZipExtractor.cs index 9b32f6e..2bf66d5 100644 --- a/SevenZip/SevenZipExtractor.cs +++ b/SevenZip/SevenZipExtractor.cs @@ -574,14 +574,9 @@ private void GetArchiveInfo(bool disposeStream) _archiveProperties = new ReadOnlyCollection(archProps); - if (!_isSolid.HasValue && _format == InArchiveFormat.Zip) - { - _isSolid = false; - } - if (!_isSolid.HasValue) { - _isSolid = true; + _isSolid = false; } #endregion @@ -618,31 +613,6 @@ private void InitArchiveFileData(bool disposeStream) } } - /// - /// Produces an array of indexes from 0 to the maximum value in the specified array - /// - /// The source array - /// The array of indexes from 0 to the maximum value in the specified array - private static uint[] SolidIndexes(uint[] indexes) - { - var max = indexes.Aggregate(0, (current, i) => Math.Max(current, (int) i)); - - if (max > 0) - { - max++; - var res = new uint[max]; - - for (var i = 0; i < max; i++) - { - res[i] = (uint)i; - } - - return res; - } - - return indexes; - } - /// /// Checks whether all the indexes are valid. /// @@ -1085,12 +1055,6 @@ public void ExtractFile(int index, Stream stream) try { var indexes = new[] { (uint)index }; - var entry = _archiveFileData[index]; - - if (_isSolid.Value && !entry.Method.Equals("Copy", StringComparison.InvariantCultureIgnoreCase)) - { - indexes = SolidIndexes(indexes); - } using (var aec = GetArchiveExtractCallback(stream, (uint) index, indexes.Length)) { @@ -1163,11 +1127,6 @@ public void ExtractFiles(string directory, params int[] indexes) origIndexes.Sort(); uindexes = origIndexes.ToArray(); - if (_isSolid.Value) - { - uindexes = SolidIndexes(uindexes); - } - #endregion try @@ -1272,11 +1231,6 @@ public void ExtractFiles(ExtractFileCallback extractFileCallback) DisposedCheck(); InitArchiveFileData(false); - if (IsSolid) - { - throw new SevenZipExtractionFailedException("Solid archives are not supported."); - } - foreach (var archiveFileInfo in ArchiveFileData) { var extractFileCallbackArgs = new ExtractFileCallbackArgs(archiveFileInfo);