diff --git a/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs new file mode 100644 index 00000000..d85fb033 --- /dev/null +++ b/tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; + +namespace SharpCompress.Test.Mocks +{ + // This is a simplified version of CryptoStream that always flushes the inner stream on Dispose to trigger an error in EntryStream + // CryptoStream doesn't always trigger the Flush, so this class is used instead + // See https://referencesource.microsoft.com/#mscorlib/system/security/cryptography/cryptostream.cs,141 + + public class FlushOnDisposeStream : Stream, IDisposable + { + private Stream inner; + + public FlushOnDisposeStream(Stream innerStream) { + this.inner = innerStream; + } + + public override bool CanRead => this.inner.CanRead; + + public override bool CanSeek => false; + + public override bool CanWrite => false; + + public override long Length => this.inner.Length; + + public override long Position { get => this.inner.Position; set => this.inner.Position = value; } + + public override void Flush() { + throw new NotImplementedException(); + } + + public override int Read(byte[] buffer, int offset, int count) { + return this.inner.Read(buffer, offset, count); + } + + 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(); + } + + protected override void Dispose(bool disposing) { + if(disposing) { + this.inner.Flush(); + this.inner.Close(); + } + + base.Dispose(disposing); + } + } +} diff --git a/tests/SharpCompress.Test/Tar/TarReaderTests.cs b/tests/SharpCompress.Test/Tar/TarReaderTests.cs index acd73eec..c155de3d 100644 --- a/tests/SharpCompress.Test/Tar/TarReaderTests.cs +++ b/tests/SharpCompress.Test/Tar/TarReaderTests.cs @@ -160,5 +160,31 @@ namespace SharpCompress.Test.Tar Assert.True(reader.ArchiveType == ArchiveType.Tar); } } - } + + [Fact] + public void Tar_With_TarGz_With_Flushed_EntryStream() + { + string archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.ContainsTarGz.tar"); + using(Stream stream = File.OpenRead(archiveFullPath)) + using(IReader reader = ReaderFactory.Open(stream)) + { + Assert.True(reader.MoveToNextEntry()); + Assert.Equal("inner.tar.gz", reader.Entry.Key); + + using(var entryStream = reader.OpenEntryStream()) { + + using(FlushOnDisposeStream flushingStream = new FlushOnDisposeStream(entryStream)) { + + // Extract inner.tar.gz + using(var innerReader = ReaderFactory.Open(flushingStream)) { + + Assert.True(innerReader.MoveToNextEntry()); + Assert.Equal("test", innerReader.Entry.Key); + + } + } + } + } + } + } } diff --git a/tests/TestArchives/Archives/Tar.ContainsTarGz.tar b/tests/TestArchives/Archives/Tar.ContainsTarGz.tar new file mode 100644 index 00000000..697060bc Binary files /dev/null and b/tests/TestArchives/Archives/Tar.ContainsTarGz.tar differ