From 6dd5da48f7fcae7122a66f2eaff15acdd9ef5c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20=C3=98rland?= Date: Thu, 4 Oct 2018 13:08:53 +0200 Subject: [PATCH] Added test that calls EntryStream.Flush() --- .../Mocks/FlushOnDisposeStream.cs | 57 ++++++++++++++++++ .../SharpCompress.Test/Tar/TarReaderTests.cs | 28 ++++++++- .../Archives/Tar.ContainsTarGz.tar | Bin 0 -> 10240 bytes 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 tests/SharpCompress.Test/Mocks/FlushOnDisposeStream.cs create mode 100644 tests/TestArchives/Archives/Tar.ContainsTarGz.tar 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 0000000000000000000000000000000000000000..697060bcaf1b395a887a517e6252028d469309aa GIT binary patch literal 10240 zcmd1I%S$cND@iQUORr*}5il??FfcPQVF1zQW~N};zzD(zi5Z$3GZ-2ho0=M%nV5jY z4UG(q%@`C6XyhIgV@r!m5{ncR7`*dJOHd@xIK?H2X=!L;!+IK8Fo-u&p;?Oc~; zwI*DQe&G_`oAv0++YN_zO-U^Cdp0MZe`BwvZ#+xw>h=Hg|Mj5;lFc?|F~jUG1`Sl< zQQl|>jE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin vXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kgRi6H<0a#Be$ literal 0 HcmV?d00001