mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
203 lines
6.1 KiB
C#
203 lines
6.1 KiB
C#
using System;
|
|
using System.IO;
|
|
using SharpCompress.Common;
|
|
using SharpCompress.Compressors;
|
|
using SharpCompress.Compressors.BZip2;
|
|
using SharpCompress.Compressors.Deflate;
|
|
using SharpCompress.Compressors.LZMA;
|
|
using SharpCompress.Compressors.Lzw;
|
|
using SharpCompress.Compressors.PPMd;
|
|
using SharpCompress.Compressors.Reduce;
|
|
using SharpCompress.Compressors.ZStandard;
|
|
using SharpCompress.IO;
|
|
using SharpCompress.Readers;
|
|
using SharpCompress.Test.Mocks;
|
|
using Xunit;
|
|
|
|
namespace SharpCompress.Test.Streams;
|
|
|
|
public class DisposalTests
|
|
{
|
|
private void VerifyStreamDisposal(
|
|
Func<Stream, bool, Stream> createStream,
|
|
bool supportsLeaveOpen = true
|
|
)
|
|
{
|
|
// 1. Test Dispose behavior (should dispose inner stream)
|
|
{
|
|
using var innerStream = new TestStream(new MemoryStream());
|
|
// createStream(stream, leaveOpen: false)
|
|
var stream = createStream(innerStream, false);
|
|
stream.Dispose();
|
|
|
|
// Some streams might not support disposal of inner stream (e.g. PpmdStream apparently)
|
|
// But for those that satisfy the pattern, we assert true.
|
|
Assert.True(
|
|
innerStream.IsDisposed,
|
|
"Stream should have been disposed when leaveOpen=false"
|
|
);
|
|
}
|
|
|
|
// 2. Test LeaveOpen behavior (should NOT dispose inner stream)
|
|
if (supportsLeaveOpen)
|
|
{
|
|
using var innerStream = new TestStream(new MemoryStream());
|
|
// createStream(stream, leaveOpen: true)
|
|
var stream = createStream(innerStream, true);
|
|
stream.Dispose();
|
|
Assert.False(
|
|
innerStream.IsDisposed,
|
|
"Stream should NOT have been disposed when leaveOpen=true"
|
|
);
|
|
}
|
|
}
|
|
|
|
private void VerifyAlwaysDispose(Func<Stream, Stream> createStream)
|
|
{
|
|
using var innerStream = new TestStream(new MemoryStream());
|
|
var stream = createStream(innerStream);
|
|
stream.Dispose();
|
|
Assert.True(innerStream.IsDisposed, "Stream should have been disposed (AlwaysDispose)");
|
|
}
|
|
|
|
private void VerifyNeverDispose(Func<Stream, Stream> createStream)
|
|
{
|
|
using var innerStream = new TestStream(new MemoryStream());
|
|
var stream = createStream(innerStream);
|
|
stream.Dispose();
|
|
Assert.False(innerStream.IsDisposed, "Stream should NOT have been disposed (NeverDispose)");
|
|
}
|
|
|
|
[Fact]
|
|
public void SourceStream_Disposal()
|
|
{
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
new SourceStream(
|
|
stream,
|
|
i => null,
|
|
new ReaderOptions { LeaveStreamOpen = leaveOpen }
|
|
)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void ProgressReportingStream_Disposal()
|
|
{
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
new ProgressReportingStream(
|
|
stream,
|
|
new Progress<ProgressReport>(),
|
|
"",
|
|
0,
|
|
leaveOpen: leaveOpen
|
|
)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void DataDescriptorStream_Disposal()
|
|
{
|
|
// DataDescriptorStream DOES dispose inner stream
|
|
VerifyAlwaysDispose(stream => new DataDescriptorStream(stream));
|
|
}
|
|
|
|
[Fact]
|
|
public void DeflateStream_Disposal()
|
|
{
|
|
// DeflateStream in SharpCompress always disposes inner stream
|
|
VerifyAlwaysDispose(stream => new DeflateStream(stream, CompressionMode.Compress));
|
|
}
|
|
|
|
[Fact]
|
|
public void GZipStream_Disposal()
|
|
{
|
|
// GZipStream in SharpCompress always disposes inner stream
|
|
VerifyAlwaysDispose(stream => new GZipStream(stream, CompressionMode.Compress));
|
|
}
|
|
|
|
[Fact]
|
|
public void LzwStream_Disposal()
|
|
{
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
{
|
|
var lzw = new LzwStream(stream);
|
|
lzw.IsStreamOwner = !leaveOpen;
|
|
return lzw;
|
|
}
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void PpmdStream_Disposal()
|
|
{
|
|
// PpmdStream seems to not dispose inner stream based on code analysis
|
|
// It takes PpmdProperties which we need to mock or create.
|
|
var props = new PpmdProperties();
|
|
VerifyNeverDispose(stream => new PpmdStream(props, stream, false));
|
|
}
|
|
|
|
[Fact]
|
|
public void LzmaStream_Disposal()
|
|
{
|
|
// LzmaStream always disposes inner stream
|
|
// Need to provide valid properties to avoid crash in constructor (invalid window size)
|
|
// 5 bytes: 1 byte properties + 4 bytes dictionary size (little endian)
|
|
// Dictionary size = 1024 (0x400) -> 00 04 00 00
|
|
var lzmaProps = new byte[] { 0, 0, 4, 0, 0 };
|
|
VerifyAlwaysDispose(stream => new LzmaStream(lzmaProps, stream));
|
|
}
|
|
|
|
[Fact]
|
|
public void LZipStream_Disposal()
|
|
{
|
|
// LZipStream now supports leaveOpen parameter
|
|
// Use Compress mode to avoid need for valid input header
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) => new LZipStream(stream, CompressionMode.Compress, leaveOpen)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void BZip2Stream_Disposal()
|
|
{
|
|
// BZip2Stream now supports leaveOpen parameter
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
new BZip2Stream(stream, CompressionMode.Compress, false, leaveOpen)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void ReduceStream_Disposal()
|
|
{
|
|
// ReduceStream does not dispose inner stream
|
|
VerifyNeverDispose(stream => new ReduceStream(stream, 0, 0, 1));
|
|
}
|
|
|
|
[Fact]
|
|
public void ZStandard_CompressionStream_Disposal()
|
|
{
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
new CompressionStream(stream, level: 0, bufferSize: 0, leaveOpen: leaveOpen)
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void ZStandard_DecompressionStream_Disposal()
|
|
{
|
|
VerifyStreamDisposal(
|
|
(stream, leaveOpen) =>
|
|
new DecompressionStream(
|
|
stream,
|
|
bufferSize: 0,
|
|
checkEndOfStream: false,
|
|
leaveOpen: leaveOpen
|
|
)
|
|
);
|
|
}
|
|
}
|