2026-04-23 10:11:54 +01:00
|
|
|
using System;
|
2026-07-24 07:35:07 +00:00
|
|
|
using System.Collections.Generic;
|
2026-04-23 10:11:54 +01:00
|
|
|
using System.IO;
|
2026-07-24 07:35:07 +00:00
|
|
|
using System.Text;
|
2026-04-23 10:11:54 +01:00
|
|
|
using System.Threading.Tasks;
|
2026-07-24 07:35:07 +00:00
|
|
|
using SharpCompress.Common;
|
|
|
|
|
using SharpCompress.Compressors;
|
|
|
|
|
using SharpCompress.Compressors.Deflate;
|
2026-04-23 10:11:54 +01:00
|
|
|
using SharpCompress.Readers;
|
|
|
|
|
using SharpCompress.Readers.Rar;
|
2026-07-24 07:35:07 +00:00
|
|
|
using SharpCompress.Readers.Tar;
|
2026-04-23 10:11:54 +01:00
|
|
|
using SharpCompress.Test.Mocks;
|
2026-07-24 07:35:07 +00:00
|
|
|
using SharpCompress.Writers.Tar;
|
2026-04-23 10:11:54 +01:00
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
namespace SharpCompress.Test;
|
|
|
|
|
|
2026-07-24 07:35:07 +00:00
|
|
|
public class ReaderFactoryTests : TestBase
|
2026-04-23 10:11:54 +01:00
|
|
|
{
|
|
|
|
|
[Fact]
|
|
|
|
|
public void OpenReader_Stream_Throws_On_Unreadable_Stream()
|
|
|
|
|
{
|
|
|
|
|
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
|
|
|
|
|
|
|
|
|
Assert.Throws<ArgumentException>(() => ReaderFactory.OpenReader(unreadable));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async ValueTask OpenAsyncReader_Stream_Throws_On_Unreadable_Stream()
|
|
|
|
|
{
|
|
|
|
|
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
|
|
|
|
|
|
|
|
|
await Assert.ThrowsAsync<ArgumentException>(() =>
|
|
|
|
|
ReaderFactory.OpenAsyncReader(unreadable).AsTask()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void RarReader_StreamCollection_Throws_On_Unreadable_Stream()
|
|
|
|
|
{
|
|
|
|
|
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
|
|
|
|
using var readable = new MemoryStream();
|
|
|
|
|
|
2026-04-23 11:43:10 +01:00
|
|
|
Assert.Throws<ArgumentException>(() =>
|
|
|
|
|
RarReader.OpenReader([unreadable, readable]).MoveToNextEntry()
|
|
|
|
|
);
|
2026-04-23 10:11:54 +01:00
|
|
|
}
|
2026-07-24 07:35:07 +00:00
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public void OpenReader_DeflateStream_WithTarPayload_DetectsTarReader()
|
|
|
|
|
{
|
|
|
|
|
using var compressedStream = new MemoryStream(CompressWithDeflate(CreateTarPayload()));
|
2026-07-24 09:34:18 +01:00
|
|
|
using var sharpCompressStream = SharpCompress.IO.SharpCompressStream.CreateNonDisposing(
|
|
|
|
|
compressedStream
|
|
|
|
|
);
|
2026-07-24 07:35:07 +00:00
|
|
|
using var deflateStream = new DeflateStream(
|
2026-07-24 09:34:18 +01:00
|
|
|
sharpCompressStream,
|
2026-07-24 07:35:07 +00:00
|
|
|
CompressionMode.Decompress,
|
|
|
|
|
CompressionLevel.Default,
|
|
|
|
|
leaveOpen: false
|
|
|
|
|
);
|
|
|
|
|
using var reader = ReaderFactory.OpenReader(deflateStream);
|
|
|
|
|
|
|
|
|
|
Assert.IsType<TarReader>(reader);
|
|
|
|
|
Assert.Equal(
|
|
|
|
|
new Dictionary<string, string>
|
|
|
|
|
{
|
|
|
|
|
["alpha.txt"] = "alpha",
|
|
|
|
|
["nested/beta.txt"] = "beta",
|
|
|
|
|
},
|
|
|
|
|
ReadAllFiles(reader)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-25 17:08:50 +01:00
|
|
|
[Fact]
|
|
|
|
|
public async ValueTask OpenAsyncReader_DeflateStream_WithTarPayload_DetectsTarReader()
|
|
|
|
|
{
|
|
|
|
|
using var compressedStream = new MemoryStream(CompressWithDeflate(CreateTarPayload()));
|
|
|
|
|
using var sharpCompressStream = SharpCompress.IO.SharpCompressStream.CreateNonDisposing(
|
|
|
|
|
compressedStream
|
|
|
|
|
);
|
|
|
|
|
using var deflateStream = new DeflateStream(
|
|
|
|
|
sharpCompressStream,
|
|
|
|
|
CompressionMode.Decompress,
|
|
|
|
|
CompressionLevel.Default,
|
|
|
|
|
leaveOpen: false
|
|
|
|
|
);
|
|
|
|
|
await using var reader = await ReaderFactory.OpenAsyncReader(deflateStream);
|
|
|
|
|
|
|
|
|
|
Assert.IsType<TarReader>(reader);
|
|
|
|
|
Assert.Equal(
|
|
|
|
|
new Dictionary<string, string>
|
|
|
|
|
{
|
|
|
|
|
["alpha.txt"] = "alpha",
|
|
|
|
|
["nested/beta.txt"] = "beta",
|
|
|
|
|
},
|
|
|
|
|
await ReadAllFilesAsync(reader)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-24 07:35:07 +00:00
|
|
|
private static Dictionary<string, string> ReadAllFiles(IReader reader)
|
|
|
|
|
{
|
|
|
|
|
var entries = new Dictionary<string, string>();
|
|
|
|
|
while (reader.MoveToNextEntry())
|
|
|
|
|
{
|
|
|
|
|
if (reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using var entryStream = reader.OpenEntryStream();
|
|
|
|
|
using var streamReader = new StreamReader(entryStream, Encoding.UTF8);
|
|
|
|
|
entries.Add(reader.Entry.Key!, streamReader.ReadToEnd());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return entries;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-25 17:08:50 +01:00
|
|
|
private static async ValueTask<Dictionary<string, string>> ReadAllFilesAsync(
|
|
|
|
|
IAsyncReader reader
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
var entries = new Dictionary<string, string>();
|
|
|
|
|
while (await reader.MoveToNextEntryAsync())
|
|
|
|
|
{
|
|
|
|
|
if (reader.Entry.IsDirectory)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using var entryStream = await reader.OpenEntryStreamAsync();
|
|
|
|
|
using var streamReader = new StreamReader(entryStream, Encoding.UTF8);
|
|
|
|
|
entries.Add(reader.Entry.Key!, await streamReader.ReadToEndAsync());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return entries;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-24 07:35:07 +00:00
|
|
|
private static byte[] CreateTarPayload()
|
|
|
|
|
{
|
|
|
|
|
var archiveEncoding = new ArchiveEncoding { Default = Encoding.UTF8 };
|
|
|
|
|
var tarWriterOptions = new TarWriterOptions(CompressionType.None, true)
|
|
|
|
|
{
|
|
|
|
|
ArchiveEncoding = archiveEncoding,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var memoryStream = new MemoryStream();
|
|
|
|
|
using (var tarWriter = new TarWriter(memoryStream, tarWriterOptions))
|
|
|
|
|
using (var alphaStream = new MemoryStream(Encoding.UTF8.GetBytes("alpha")))
|
|
|
|
|
using (var betaStream = new MemoryStream(Encoding.UTF8.GetBytes("beta")))
|
|
|
|
|
{
|
|
|
|
|
tarWriter.Write("alpha.txt", alphaStream, null);
|
|
|
|
|
tarWriter.Write("nested/beta.txt", betaStream, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return memoryStream.ToArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static byte[] CompressWithDeflate(byte[] bytes)
|
|
|
|
|
{
|
|
|
|
|
using var sourceStream = new MemoryStream(bytes);
|
|
|
|
|
using var deflateStream = new DeflateStream(
|
|
|
|
|
sourceStream,
|
|
|
|
|
CompressionMode.Compress,
|
|
|
|
|
CompressionLevel.Default
|
|
|
|
|
);
|
|
|
|
|
using var compressedStream = new MemoryStream();
|
|
|
|
|
|
|
|
|
|
var buffer = new byte[4096];
|
|
|
|
|
int read;
|
|
|
|
|
while ((read = deflateStream.Read(buffer, 0, buffer.Length)) > 0)
|
|
|
|
|
{
|
|
|
|
|
compressedStream.Write(buffer, 0, read);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return compressedStream.ToArray();
|
|
|
|
|
}
|
2026-04-23 10:11:54 +01:00
|
|
|
}
|