mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-22 15:04:43 +00:00
add more tests
This commit is contained in:
73
tests/SharpCompress.Test/GZip/GZipWriterNonSeekableTests.cs
Normal file
73
tests/SharpCompress.Test/GZip/GZipWriterNonSeekableTests.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives.GZip;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using SharpCompress.Writers.GZip;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.GZip;
|
||||
|
||||
/// <summary>
|
||||
/// Regression tests for writing gzip streams to non-seekable (forward-only) output streams.
|
||||
/// GZip is inherently a single forward stream with no seek-dependent layout, so streaming to
|
||||
/// a <see cref="ForwardOnlyStream"/> must simply produce a valid, readable gzip stream.
|
||||
/// </summary>
|
||||
public class GZipWriterNonSeekableTests
|
||||
{
|
||||
private const string EntryName = "content.txt";
|
||||
|
||||
private static byte[] CreateContent() =>
|
||||
Encoding.UTF8.GetBytes(string.Concat(Enumerable.Repeat("Hello streaming gzip! ", 500)));
|
||||
|
||||
private static async Task<byte[]> WriteToNonSeekableAsync(byte[] content)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
await using (var writer = new GZipWriter(new ForwardOnlyStream(ms)))
|
||||
{
|
||||
using var source = new MemoryStream(content);
|
||||
await writer.WriteAsync(EntryName, source, null);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] WriteToNonSeekableSync(byte[] content)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using (var writer = new GZipWriter(new ForwardOnlyStream(ms)))
|
||||
{
|
||||
using var source = new MemoryStream(content);
|
||||
writer.Write(EntryName, source, null);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static void AssertRoundTrips(byte[] gz, byte[] expected)
|
||||
{
|
||||
using var archive = GZipArchive.OpenArchive(new MemoryStream(gz));
|
||||
var entry = archive.Entries.First();
|
||||
using var extracted = new MemoryStream();
|
||||
using (var entryStream = entry.OpenEntryStream())
|
||||
{
|
||||
entryStream.CopyTo(extracted);
|
||||
}
|
||||
Assert.Equal(expected, extracted.ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GZip_Async_NonSeekable_RoundTrips()
|
||||
{
|
||||
var content = CreateContent();
|
||||
var gz = await WriteToNonSeekableAsync(content);
|
||||
AssertRoundTrips(gz, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GZip_Sync_NonSeekable_RoundTrips()
|
||||
{
|
||||
var content = CreateContent();
|
||||
var gz = WriteToNonSeekableSync(content);
|
||||
AssertRoundTrips(gz, content);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using SharpCompress.Writers.SevenZip;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.SevenZip;
|
||||
|
||||
/// <summary>
|
||||
/// 7z writing requires a seekable output stream so the signature header can be back-patched on
|
||||
/// finalize (see SevenZipWriter.cs). Unlike Zip, it cannot fall back to a streaming layout, so
|
||||
/// constructing a writer over a non-seekable output must fail fast. This pins that documented
|
||||
/// limitation against silent regression.
|
||||
/// </summary>
|
||||
public class SevenZipWriterNonSeekableTests
|
||||
{
|
||||
[Fact]
|
||||
public void SevenZip_NonSeekable_Output_Throws()
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
Assert.Throws<ArchiveOperationException>(() =>
|
||||
new SevenZipWriter(new ForwardOnlyStream(ms), new SevenZipWriterOptions())
|
||||
);
|
||||
}
|
||||
}
|
||||
129
tests/SharpCompress.Test/Tar/TarWriterNonSeekableTests.cs
Normal file
129
tests/SharpCompress.Test/Tar/TarWriterNonSeekableTests.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives.Tar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using SharpCompress.Writers.Tar;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Tar;
|
||||
|
||||
/// <summary>
|
||||
/// Regression tests for writing tar archives to non-seekable (forward-only) output streams.
|
||||
/// Tar is a forward-only format with no header back-patching, so streaming to a
|
||||
/// <see cref="ForwardOnlyStream"/> must produce a valid, readable archive. The sources are
|
||||
/// seekable so the writer can derive each entry's size up front (see TarWriter.cs).
|
||||
/// </summary>
|
||||
public class TarWriterNonSeekableTests
|
||||
{
|
||||
private static readonly DateTime FixedModificationTime = new(2024, 5, 15, 10, 30, 0);
|
||||
|
||||
private static (string Name, byte[] Content)[] CreateStreamingTestEntries() =>
|
||||
[
|
||||
(
|
||||
"first.txt",
|
||||
Encoding.UTF8.GetBytes(
|
||||
string.Concat(Enumerable.Repeat("Hello streaming tar! ", 500))
|
||||
)
|
||||
),
|
||||
(
|
||||
"nested/second.txt",
|
||||
Encoding.UTF8.GetBytes(
|
||||
string.Concat(Enumerable.Repeat("Another entry with different content. ", 300))
|
||||
)
|
||||
),
|
||||
];
|
||||
|
||||
private static async Task<byte[]> WriteArchiveToNonSeekableAsync(
|
||||
(string Name, byte[] Content)[] entries
|
||||
)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
await using (
|
||||
var writer = new TarWriter(
|
||||
new ForwardOnlyStream(ms),
|
||||
new TarWriterOptions(CompressionType.None, true)
|
||||
)
|
||||
)
|
||||
{
|
||||
foreach (var (name, content) in entries)
|
||||
{
|
||||
using var source = new MemoryStream(content);
|
||||
await writer.WriteAsync(name, source, FixedModificationTime);
|
||||
}
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] WriteArchiveToNonSeekableSync((string Name, byte[] Content)[] entries)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using (
|
||||
var writer = new TarWriter(
|
||||
new ForwardOnlyStream(ms),
|
||||
new TarWriterOptions(CompressionType.None, true)
|
||||
)
|
||||
)
|
||||
{
|
||||
foreach (var (name, content) in entries)
|
||||
{
|
||||
using var source = new MemoryStream(content);
|
||||
writer.Write(name, source, FixedModificationTime);
|
||||
}
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static async Task AssertRoundTripsAsync(
|
||||
byte[] tar,
|
||||
(string Name, byte[] Content)[] entries
|
||||
)
|
||||
{
|
||||
using var archive = TarArchive.OpenArchive(new MemoryStream(tar));
|
||||
var fileEntries = archive.Entries.Where(e => !e.IsDirectory).ToList();
|
||||
Assert.Equal(entries.Length, fileEntries.Count);
|
||||
foreach (var (name, content) in entries)
|
||||
{
|
||||
var entry = fileEntries.Single(e => e.Key == name);
|
||||
using var extracted = new MemoryStream();
|
||||
#if LEGACY_DOTNET
|
||||
using (var entryStream = await entry.OpenEntryStreamAsync())
|
||||
#else
|
||||
await using (var entryStream = await entry.OpenEntryStreamAsync())
|
||||
#endif
|
||||
{
|
||||
await entryStream.CopyToAsync(extracted);
|
||||
}
|
||||
Assert.Equal(content, extracted.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Tar_Async_NonSeekable_RoundTrips()
|
||||
{
|
||||
var entries = CreateStreamingTestEntries();
|
||||
var tar = await WriteArchiveToNonSeekableAsync(entries);
|
||||
await AssertRoundTripsAsync(tar, entries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Tar_Sync_NonSeekable_RoundTrips()
|
||||
{
|
||||
var entries = CreateStreamingTestEntries();
|
||||
var tar = WriteArchiveToNonSeekableSync(entries);
|
||||
await AssertRoundTripsAsync(tar, entries);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Tar_Async_NonSeekable_Matches_Sync_Output()
|
||||
{
|
||||
var entries = CreateStreamingTestEntries();
|
||||
var asyncTar = await WriteArchiveToNonSeekableAsync(entries);
|
||||
var syncTar = WriteArchiveToNonSeekableSync(entries);
|
||||
|
||||
Assert.Equal(syncTar, asyncTar);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user