Merge pull request #404 from MattKotsenas/bugfix/idisposable

Enable parallel test execution
This commit is contained in:
Adam Hathcock
2018-07-12 19:53:50 +01:00
committed by GitHub
24 changed files with 220 additions and 475 deletions

View File

@@ -92,7 +92,7 @@ namespace SharpCompress.Archives
public static IArchive Open(string filePath, ReaderOptions options = null)
{
filePath.CheckNotNullOrEmpty("filePath");
return Open(new FileInfo(filePath), options ?? new ReaderOptions());
return Open(new FileInfo(filePath), options);
}
/// <summary>
@@ -103,36 +103,31 @@ namespace SharpCompress.Archives
public static IArchive Open(FileInfo fileInfo, ReaderOptions options = null)
{
fileInfo.CheckNotNull("fileInfo");
options = options ?? new ReaderOptions();
options = options ?? new ReaderOptions { LeaveStreamOpen = false };
using (var stream = fileInfo.OpenRead())
{
if (ZipArchive.IsZipFile(stream, null))
{
stream.Dispose();
return ZipArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (SevenZipArchive.IsSevenZipFile(stream))
{
stream.Dispose();
return SevenZipArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (GZipArchive.IsGZipFile(stream))
{
stream.Dispose();
return GZipArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (RarArchive.IsRarFile(stream, options))
{
stream.Dispose();
return RarArchive.Open(fileInfo, options);
}
stream.Seek(0, SeekOrigin.Begin);
if (TarArchive.IsTarFile(stream))
{
stream.Dispose();
return TarArchive.Open(fileInfo, options);
}
throw new InvalidOperationException("Cannot determine compressed stream type. Supported Archive Formats: Zip, GZip, Tar, Rar, 7Zip");

View File

@@ -1,16 +1,16 @@
using System;
using SharpCompress.IO;
using System;
using System.IO;
namespace SharpCompress.Common.Tar
{
internal class TarReadOnlySubStream : Stream
internal class TarReadOnlySubStream : NonDisposingStream
{
private bool _isDisposed;
private long _amountRead;
public TarReadOnlySubStream(Stream stream, long bytesToRead)
public TarReadOnlySubStream(Stream stream, long bytesToRead) : base(stream, throwOnDispose: false)
{
Stream = stream;
BytesLeftToRead = bytesToRead;
}
@@ -36,12 +36,11 @@ namespace SharpCompress.Common.Tar
var buffer = new byte[skipBytes];
Stream.ReadFully(buffer);
}
base.Dispose(disposing);
}
private long BytesLeftToRead { get; set; }
public Stream Stream { get; }
public override bool CanRead => true;
public override bool CanSeek => false;

View File

@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using SharpCompress.IO;
using SharpCompress.Readers;
@@ -33,15 +34,18 @@ namespace SharpCompress.Common
/// </summary>
public virtual bool IsMultiVolume => true;
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_actualStream.Dispose();
}
}
public void Dispose()
{
if (!_disposed)
{
_actualStream.Dispose();
_disposed = true;
}
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -1,74 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace SharpCompress.IO
{
public class ReadOnlyAppendingStream : Stream
{
private readonly Queue<Stream> streams;
private Stream current;
public ReadOnlyAppendingStream(IEnumerable<Stream> streams)
{
this.streams = new Queue<Stream>(streams);
}
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override void Flush()
{
throw new NotImplementedException();
}
public override long Length => throw new NotImplementedException();
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override int Read(byte[] buffer, int offset, int count)
{
if (current == null && streams.Count == 0)
{
return -1;
}
if (current == null)
{
current = streams.Dequeue();
}
int totalRead = 0;
while (totalRead < count)
{
int read = current.Read(buffer, offset + totalRead, count - totalRead);
if (read <= 0)
{
if (streams.Count == 0)
{
return totalRead;
}
current = streams.Dequeue();
}
totalRead += read;
}
return totalRead;
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
}
}

View File

@@ -3,33 +3,22 @@ using System.IO;
namespace SharpCompress.IO
{
internal class BufferedSubStream : Stream
internal class BufferedSubStream : NonDisposingStream
{
private long position;
private int cacheOffset;
private int cacheLength;
private readonly byte[] cache;
public BufferedSubStream(Stream stream, long origin, long bytesToRead)
public BufferedSubStream(Stream stream, long origin, long bytesToRead) : base(stream, throwOnDispose: false)
{
Stream = stream;
position = origin;
BytesLeftToRead = bytesToRead;
cache = new byte[32 << 10];
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
//Stream.Dispose();
}
}
private long BytesLeftToRead { get; set; }
public Stream Stream { get; }
public override bool CanRead => true;
public override bool CanSeek => false;

View File

@@ -3,13 +3,10 @@ using System.IO;
namespace SharpCompress.IO
{
internal class CountingWritableSubStream : Stream
internal class CountingWritableSubStream : NonDisposingStream
{
private readonly Stream writableStream;
internal CountingWritableSubStream(Stream stream)
internal CountingWritableSubStream(Stream stream) : base(stream, throwOnDispose: false)
{
writableStream = stream;
}
public ulong Count { get; private set; }
@@ -22,7 +19,7 @@ namespace SharpCompress.IO
public override void Flush()
{
writableStream.Flush();
Stream.Flush();
}
public override long Length => throw new NotSupportedException();
@@ -46,13 +43,13 @@ namespace SharpCompress.IO
public override void Write(byte[] buffer, int offset, int count)
{
writableStream.Write(buffer, offset, count);
Stream.Write(buffer, offset, count);
Count += (uint)count;
}
public override void WriteByte(byte value)
{
writableStream.WriteByte(value);
Stream.WriteByte(value);
++Count;
}
}

View File

@@ -20,6 +20,7 @@ namespace SharpCompress.IO
{
Stream.Dispose();
}
base.Dispose(disposing);
}
public Stream Stream { get; }
@@ -74,10 +75,5 @@ namespace SharpCompress.IO
{
Stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
Stream.WriteByte(value);
}
}
}

View File

@@ -15,10 +15,9 @@ namespace SharpCompress.IO
protected override void Dispose(bool disposing)
{
GC.SuppressFinalize(this);
if (ThrowOnDispose)
{
throw new InvalidOperationException();
throw new InvalidOperationException($"Attempt to dispose of a {nameof(NonDisposingStream)} when {nameof(ThrowOnDispose)} is {ThrowOnDispose}");
}
}
@@ -44,11 +43,6 @@ namespace SharpCompress.IO
return Stream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return Stream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
return Stream.Seek(offset, origin);
@@ -63,10 +57,5 @@ namespace SharpCompress.IO
{
Stream.Write(buffer, offset, count);
}
public override void WriteByte(byte value)
{
Stream.WriteByte(value);
}
}
}

View File

@@ -11,7 +11,7 @@ namespace SharpCompress.IO
}
public ReadOnlySubStream(Stream stream, long? origin, long bytesToRead)
: base(stream, false)
: base(stream, throwOnDispose: false)
{
if (origin != null)
{

View File

@@ -10,7 +10,7 @@ using Xunit;
namespace SharpCompress.Test
{
public class ArchiveTests : TestBase
public class ArchiveTests : ReaderTests
{
protected void ArchiveStreamReadExtractAll(string testArchive, CompressionType compression)
{
@@ -29,7 +29,7 @@ namespace SharpCompress.Test
Assert.True(archive.IsSolid);
using (var reader = archive.ExtractAllEntries())
{
ReaderTests.UseReader(this, reader, compression);
UseReader(reader, compression);
}
VerifyFiles();
@@ -104,116 +104,42 @@ namespace SharpCompress.Test
protected void ArchiveFileRead(string testArchive, ReaderOptions readerOptions = null)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
ArchiveFileRead(testArchive.AsEnumerable(), readerOptions);
}
protected void ArchiveFileRead(IEnumerable<string> testArchives, ReaderOptions readerOptions = null)
{
foreach (var path in testArchives)
using (var archive = ArchiveFactory.Open(testArchive, readerOptions))
{
using (var archive = ArchiveFactory.Open(path, readerOptions))
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
//archive.EntryExtractionBegin += archive_EntryExtractionBegin;
//archive.FilePartExtractionBegin += archive_FilePartExtractionBegin;
//archive.CompressedBytesRead += archive_CompressedBytesRead;
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(SCRATCH_FILES_PATH,
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
entry.WriteToDirectory(SCRATCH_FILES_PATH,
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
VerifyFiles();
}
VerifyFiles();
}
private void archive_CompressedBytesRead(object sender, CompressedBytesReadEventArgs e)
{
Console.WriteLine("Read Compressed File Part Bytes: {0} Percentage: {1}%",
e.CurrentFilePartCompressedBytesRead, CreatePercentage(e.CurrentFilePartCompressedBytesRead, partTotal));
string percentage = entryTotal.HasValue ? CreatePercentage(e.CompressedBytesRead,
entryTotal.Value).ToString() : "Unknown";
Console.WriteLine("Read Compressed File Entry Bytes: {0} Percentage: {1}%",
e.CompressedBytesRead, percentage);
}
private void archive_FilePartExtractionBegin(object sender, FilePartExtractionBeginEventArgs e)
{
partTotal = e.Size;
Console.WriteLine("Initializing File Part Extraction: " + e.Name);
}
private void archive_EntryExtractionBegin(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
{
entryTotal = e.Item.Size;
Console.WriteLine("Initializing File Entry Extraction: " + e.Item.Key);
}
private long? entryTotal;
private long partTotal;
private long totalSize;
/// <summary>
/// Demonstrate the ExtractionOptions.PreserveFileTime and ExtractionOptions.PreserveAttributes extract options
/// </summary>
protected void ArchiveFileReadEx(string testArchive)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
ArchiveFileReadEx(testArchive.AsEnumerable());
}
/// <summary>
/// Demonstrate the TotalUncompressSize property, and the ExtractionOptions.PreserveFileTime and ExtractionOptions.PreserveAttributes extract options
/// </summary>
protected void ArchiveFileReadEx(IEnumerable<string> testArchives)
{
foreach (var path in testArchives)
using (var archive = ArchiveFactory.Open(testArchive))
{
using (var archive = ArchiveFactory.Open(path))
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
totalSize = archive.TotalUncompressSize;
//archive.EntryExtractionBegin += Archive_EntryExtractionBeginEx;
//archive.EntryExtractionEnd += Archive_EntryExtractionEndEx;
//archive.CompressedBytesRead += Archive_CompressedBytesReadEx;
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
{
entry.WriteToDirectory(SCRATCH_FILES_PATH,
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true,
PreserveAttributes = true,
PreserveFileTime = true
});
}
entry.WriteToDirectory(SCRATCH_FILES_PATH,
new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true,
PreserveAttributes = true,
PreserveFileTime = true
});
}
VerifyFilesEx();
}
}
private void Archive_EntryExtractionEndEx(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
{
partTotal += e.Item.Size;
}
private void Archive_CompressedBytesReadEx(object sender, CompressedBytesReadEventArgs e)
{
string percentage = entryTotal.HasValue ? CreatePercentage(e.CompressedBytesRead, entryTotal.Value).ToString() : "-";
string tortalPercentage = CreatePercentage(partTotal + e.CompressedBytesRead, totalSize).ToString();
Console.WriteLine(@"Read Compressed File Progress: {0}% Total Progress {1}%", percentage, tortalPercentage);
}
private void Archive_EntryExtractionBeginEx(object sender, ArchiveExtractionEventArgs<IArchiveEntry> e)
{
entryTotal = e.Item.Size;
}
private int CreatePercentage(long n, long d)
{
return (int)(((double)n / (double)d) * 100);
VerifyFilesEx();
}
}
}

View File

@@ -17,7 +17,7 @@ namespace SharpCompress.Test.GZip
[Fact]
public void GZip_Archive_Generic()
{
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
using (var archive = ArchiveFactory.Open(stream))
{
var entry = archive.Entries.First();
@@ -30,7 +30,7 @@ namespace SharpCompress.Test.GZip
[Fact]
public void GZip_Archive()
{
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
using (var archive = GZipArchive.Open(stream))
{
var entry = archive.Entries.First();
@@ -45,7 +45,7 @@ namespace SharpCompress.Test.GZip
public void GZip_Archive_NoAdd()
{
string jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg");
using (Stream stream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
using (var archive = GZipArchive.Open(stream))
{
Assert.Throws<InvalidOperationException>(() => archive.AddEntry("jpg\\test.jpg", jpg));
@@ -58,7 +58,7 @@ namespace SharpCompress.Test.GZip
public void GZip_Archive_Multiple_Reads()
{
var inputStream = new MemoryStream();
using (var fileStream = File.Open(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"), FileMode.Open))
using (var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
{
fileStream.CopyTo(inputStream);
inputStream.Position = 0;

View File

@@ -42,16 +42,12 @@ namespace SharpCompress.Test.GZip
public void GZip_Writer_Generic_Bad_Compression()
{
Assert.Throws<InvalidFormatException>(() =>
{
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz")))
using (var writer = WriterFactory.Open(stream, ArchiveType.GZip, CompressionType.BZip2))
{
writer.Write("Tar.tar", Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
}
CompareArchivesByPath(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"),
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
});
{
using (Stream stream = File.OpenWrite(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz")))
using (var writer = WriterFactory.Open(stream, ArchiveType.GZip, CompressionType.BZip2))
{
}
});
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.IO;
namespace SharpCompress.Test
namespace SharpCompress.Test.Mocks
{
public class ForwardOnlyStream : Stream
{
@@ -16,9 +16,15 @@ namespace SharpCompress.Test
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
stream.Dispose();
IsDisposed = true;
if (!IsDisposed)
{
if (disposing)
{
stream.Dispose();
IsDisposed = true;
base.Dispose(disposing);
}
}
}
public override bool CanRead => true;
@@ -44,11 +50,6 @@ namespace SharpCompress.Test
return stream.Read(buffer, offset, count);
}
public override int ReadByte()
{
return stream.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();

View File

@@ -0,0 +1,69 @@
using System.IO;
namespace SharpCompress.Test.Mocks
{
public class TestStream : Stream
{
private readonly Stream stream;
public TestStream(Stream stream) : this(stream, stream.CanRead, stream.CanWrite, stream.CanSeek)
{
}
public bool IsDisposed { get; private set; }
public TestStream(Stream stream, bool read, bool write, bool seek)
{
this.stream = stream;
CanRead = read;
CanWrite = write;
CanSeek = seek;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
stream.Dispose();
IsDisposed = true;
}
public override bool CanRead { get; }
public override bool CanSeek { get; }
public override bool CanWrite { get; }
public override void Flush()
{
stream.Flush();
}
public override long Length => stream.Length;
public override long Position
{
get => stream.Position;
set => stream.Position = value;
}
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}
}
}

View File

@@ -46,7 +46,7 @@ namespace SharpCompress.Test.Rar
private void ReadEncryptedFlag(string testArchive, bool isEncrypted)
{
using (var stream = GetReaderStream(testArchive))
using (var stream = new FileStream(Path.Combine(TEST_ARCHIVES_PATH, testArchive), FileMode.Open, FileAccess.Read))
{
foreach (var header in rarHeaderFactory.ReadHeaders(stream))
{
@@ -58,10 +58,5 @@ namespace SharpCompress.Test.Rar
}
}
}
private FileStream GetReaderStream(string testArchive)
{
return new FileStream(Path.Combine(TEST_ARCHIVES_PATH, testArchive), FileMode.Open);
}
}
}

View File

@@ -199,26 +199,7 @@ namespace SharpCompress.Test.Rar
private void ReadRar(string testArchive, string password)
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, testArchive)))
using (var reader = RarReader.Open(stream, new ReaderOptions()
{
Password = password
}))
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
}
VerifyFiles();
Read(testArchive, CompressionType.Rar, new ReaderOptions { Password = password });
}
[Fact]
@@ -234,7 +215,7 @@ namespace SharpCompress.Test.Rar
private void DoRar_Entry_Stream(string filename)
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)))
using (var reader = RarReader.Open(stream))
using (var reader = ReaderFactory.Open(stream))
{
while (reader.MoveToNextEntry())
{
@@ -267,7 +248,7 @@ namespace SharpCompress.Test.Rar
public void Rar_Reader_Audio_program()
{
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.Audio_program.rar")))
using (var reader = RarReader.Open(stream, new ReaderOptions()
using (var reader = ReaderFactory.Open(stream, new ReaderOptions()
{
LookForHeader = true
}))
@@ -333,7 +314,7 @@ namespace SharpCompress.Test.Rar
private void DoRar_Solid_Skip_Reader(string filename)
{
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)))
using (var reader = RarReader.Open(stream, new ReaderOptions()
using (var reader = ReaderFactory.Open(stream, new ReaderOptions()
{
LookForHeader = true
}))
@@ -366,7 +347,7 @@ namespace SharpCompress.Test.Rar
private void DoRar_Reader_Skip(string filename)
{
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)))
using (var reader = RarReader.Open(stream, new ReaderOptions()
using (var reader = ReaderFactory.Open(stream, new ReaderOptions()
{
LookForHeader = true
}))

View File

@@ -1,51 +1,66 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Readers;
using SharpCompress.Test.Mocks;
using Xunit;
namespace SharpCompress.Test
{
public class ReaderTests : TestBase
public abstract class ReaderTests : TestBase
{
protected void Read(string testArchive, CompressionType expectedCompression)
protected void Read(string testArchive, CompressionType expectedCompression, ReaderOptions options = null)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
Read(testArchive.AsEnumerable(), expectedCompression);
options = options ?? new ReaderOptions();
options.LeaveStreamOpen = true;
ReadImpl(testArchive, expectedCompression, options);
options.LeaveStreamOpen = false;
ReadImpl(testArchive, expectedCompression, options);
VerifyFiles();
}
protected void Read(IEnumerable<string> testArchives, CompressionType expectedCompression)
private void ReadImpl(string testArchive, CompressionType expectedCompression, ReaderOptions options)
{
foreach (var path in testArchives)
using (var file = File.OpenRead(testArchive))
{
using (var stream = new NonDisposingStream(new ForwardOnlyStream(File.OpenRead(path)), true))
using (var reader = ReaderFactory.Open(stream, new ReaderOptions()
{
LeaveStreamOpen = true
}))
using (var protectedStream = new NonDisposingStream(new ForwardOnlyStream(file), throwOnDispose: true))
{
UseReader(this, reader, expectedCompression);
stream.ThrowOnDispose = false;
using (var testStream = new TestStream(protectedStream))
{
using (var reader = ReaderFactory.Open(testStream, options))
{
UseReader(reader, expectedCompression);
protectedStream.ThrowOnDispose = false;
Assert.False(testStream.IsDisposed, "{nameof(testStream)} prematurely closed");
}
// Boolean XOR -- If the stream should be left open (true), then the stream should not be diposed (false)
// and if the stream should be closed (false), then the stream should be disposed (true)
var message = $"{nameof(options.LeaveStreamOpen)} is set to '{options.LeaveStreamOpen}', so {nameof(testStream.IsDisposed)} should be set to '{!testStream.IsDisposed}', but is set to {testStream.IsDisposed}";
Assert.True(options.LeaveStreamOpen != testStream.IsDisposed, message);
}
}
}
}
public static void UseReader(TestBase test, IReader reader, CompressionType expectedCompression)
public void UseReader(IReader reader, CompressionType expectedCompression)
{
while (reader.MoveToNextEntry())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(reader.Entry.CompressionType, expectedCompression);
reader.WriteEntryToDirectory(test.SCRATCH_FILES_PATH, new ExtractionOptions()
Assert.Equal(expectedCompression, reader.Entry.CompressionType);
reader.WriteEntryToDirectory(SCRATCH_FILES_PATH, new ExtractionOptions()
{
ExtractFullPath = true,
Overwrite = true
});
}
}
test.VerifyFiles();
}
}
}

View File

@@ -4,7 +4,7 @@ using Xunit;
namespace SharpCompress.Test.Streams
{
public class StreamTests
public class LzmaStreamTests
{
[Fact]
public void TestLzma2Decompress1Byte()

View File

@@ -2,7 +2,7 @@
using SharpCompress.IO;
using Xunit;
namespace SharpCompress.Test
namespace SharpCompress.Test.Streams
{
public class RewindableStreamTest
{

View File

@@ -3,6 +3,7 @@ using System.IO;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.Tar;
using SharpCompress.Test.Mocks;
using Xunit;
namespace SharpCompress.Test.Tar

View File

@@ -6,8 +6,6 @@ using System.Text;
using SharpCompress.Readers;
using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace SharpCompress.Test
{
public class TestBase : IDisposable
@@ -39,12 +37,6 @@ namespace SharpCompress.Test
public void Dispose()
{
// WARNING: This garbage collection is needed to reclaim leaked file handles
// (likely due to improperly handled IDisposables). Without it, The following
// delete fails because files are still is use. This GC should be removed once
// all the files pass without it.
GC.Collect(2, GCCollectionMode.Forced, true, false);
Directory.Delete(SCRATCH_BASE_PATH, true);
}
@@ -169,14 +161,6 @@ namespace SharpCompress.Test
return;
}
if (IsFileLocked(new FileInfo(file1)))
{
throw new InvalidOperationException($"{file1} is not disposed");
}
if (IsFileLocked(new FileInfo(file2)))
{
throw new InvalidOperationException($"{file2} is not disposed");
}
using (var file1Stream = File.OpenRead(file1))
using (var file2Stream = File.OpenRead(file2))
{
@@ -205,8 +189,7 @@ namespace SharpCompress.Test
}
protected void CompareArchivesByPath(string file1, string file2) {
ReaderOptions readerOptions = new ReaderOptions();
ReaderOptions readerOptions = new ReaderOptions { LeaveStreamOpen = false };
readerOptions.ArchiveEncoding.Default = Encoding.GetEncoding(866);
//don't compare the order. OS X reads files from the file system in a different order therefore makes the archive ordering different
@@ -231,29 +214,5 @@ namespace SharpCompress.Test
}
}
protected bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
stream?.Close();
}
//file is not locked
return false;
}
}
}

View File

@@ -1,70 +0,0 @@
using System.IO;
namespace SharpCompress.Test
{
public class TestStream : Stream
{
private readonly Stream stream;
public TestStream(Stream stream)
: this(stream, true, true, true)
{
}
public bool IsDisposed { get; private set; }
public TestStream(Stream stream, bool read, bool write, bool seek)
{
this.stream = stream;
CanRead = read;
CanWrite = write;
CanSeek = seek;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
stream.Dispose();
IsDisposed = true;
}
public override bool CanRead { get; }
public override bool CanSeek { get; }
public override bool CanWrite { get; }
public override void Flush()
{
stream.Flush();
}
public override long Length => stream.Length;
public override long Position
{
get => stream.Position;
set => stream.Position = value;
}
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
}
}
}

View File

@@ -5,6 +5,7 @@ using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.Zip;
using SharpCompress.Test.Mocks;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;
using Xunit;
@@ -133,7 +134,7 @@ namespace SharpCompress.Test.Zip
var eo = new ZipWriterEntryOptions() { DeflateCompressionLevel = Compressors.Deflate.CompressionLevel.None };
using (var zip = File.OpenWrite(filename))
using(var st = forward_only ? (Stream)new NonSeekableStream(zip) : zip)
using(var st = forward_only ? (Stream)new ForwardOnlyStream(zip) : zip)
using (var zipWriter = (ZipWriter)WriterFactory.Open(st, ArchiveType.Zip, opts))
{
@@ -186,38 +187,5 @@ namespace SharpCompress.Test.Zip
);
}
}
/// <summary>
/// Helper to create non-seekable streams from filestream
/// </summary>
private class NonSeekableStream : Stream
{
private readonly Stream stream;
public NonSeekableStream(Stream s) { stream = s; }
public override bool CanRead => stream.CanRead;
public override bool CanSeek => false;
public override bool CanWrite => stream.CanWrite;
public override long Length => throw new NotImplementedException();
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override void Flush() { stream.Flush(); }
public override int Read(byte[] buffer, int offset, int count)
{ return stream.Read(buffer, offset, count); }
public override int ReadByte()
{ return stream.ReadByte(); }
public override long Seek(long offset, SeekOrigin origin)
{ throw new NotImplementedException(); }
public override void SetLength(long value)
{ throw new NotImplementedException(); }
public override void Write(byte[] buffer, int offset, int count)
{ stream.Write(buffer, offset, count); }
public override void WriteByte(byte value)
{ stream.WriteByte(value); }
}
}
}

View File

@@ -4,6 +4,7 @@ using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Readers;
using SharpCompress.Readers.Zip;
using SharpCompress.Test.Mocks;
using SharpCompress.Writers;
using Xunit;
@@ -268,40 +269,48 @@ namespace SharpCompress.Test.Zip
VerifyFiles();
}
private class NonSeekableMemoryStream : MemoryStream
{
public override bool CanSeek => false;
}
[Fact]
public void TestSharpCompressWithEmptyStream()
{
MemoryStream stream = new NonSeekableMemoryStream();
using (IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
var expected = new Tuple<string, byte[]>[]
{
zipWriter.Write("foo.txt", new MemoryStream(new byte[0]));
zipWriter.Write("foo2.txt", new MemoryStream(new byte[10]));
}
new Tuple<string, byte[]>("foo.txt", new byte[0]),
new Tuple<string, byte[]>("foo2.txt", new byte[10])
};
stream = new MemoryStream(stream.ToArray());
File.WriteAllBytes(Path.Combine(SCRATCH_FILES_PATH, "foo.zip"), stream.ToArray());
using (IReader zipReader = ZipReader.Open(new NonDisposingStream(stream, true)))
using (var memory = new MemoryStream())
{
while (zipReader.MoveToNextEntry())
Stream stream = new TestStream(memory, read: true, write: true, seek: false);
using (IWriter zipWriter = WriterFactory.Open(stream, ArchiveType.Zip, CompressionType.Deflate))
{
using (EntryStream entry = zipReader.OpenEntryStream())
zipWriter.Write(expected[0].Item1, new MemoryStream(expected[0].Item2));
zipWriter.Write(expected[1].Item1, new MemoryStream(expected[1].Item2));
}
stream = new MemoryStream(memory.ToArray());
File.WriteAllBytes(Path.Combine(SCRATCH_FILES_PATH, "foo.zip"), memory.ToArray());
using (IReader zipReader = ZipReader.Open(new NonDisposingStream(stream, true)))
{
var i = 0;
while (zipReader.MoveToNextEntry())
{
MemoryStream tempStream = new MemoryStream();
const int bufSize = 0x1000;
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = entry.Read(buf, 0, bufSize)) > 0)
using (EntryStream entry = zipReader.OpenEntryStream())
{
tempStream.Write(buf, 0, bytesRead);
MemoryStream tempStream = new MemoryStream();
const int bufSize = 0x1000;
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = entry.Read(buf, 0, bufSize)) > 0)
{
tempStream.Write(buf, 0, bytesRead);
}
Assert.Equal(expected[i].Item1, zipReader.Entry.Key);
Assert.Equal(expected[i].Item2, tempStream.ToArray());
}
i++;
}
}
}