Compare commits

...

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
20f2c9e0d3 Add comprehensive RAR5 async extraction tests
- Created Rar5AsyncExtractionTests with 12 tests that exercise Unpack5Async code path
- Tests use AsyncOnlyStream to ensure async methods are called (not sync fallbacks)
- Cover basic archives, solid archives, encrypted archives, and various extraction methods
- Tests verify:
  * ExtractAllEntries for solid archives
  * Individual file extraction with WriteEntryToDirectoryAsync
  * OpenEntryStream for manual extraction
  * WriteToDirectory for full archive extraction
  * Encrypted files (both header+files and files only)
  * Special formats (Blake2 CRC, comments, uncompressed)
  * Skipping entries in solid archives
- All tests passing on both net48 and net10.0

Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-11 17:02:24 +00:00
copilot-swe-agent[bot]
d9320c0930 Initial plan for RAR5 async test improvements
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
2026-02-11 16:56:53 +00:00
copilot-swe-agent[bot]
6ddeb048f6 Initial plan 2026-02-11 16:55:12 +00:00
2 changed files with 249 additions and 6 deletions

View File

@@ -216,9 +216,9 @@
"net10.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[10.0.0, )",
"resolved": "10.0.0",
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
"requested": "[10.0.2, )",
"resolved": "10.0.2",
"contentHash": "sXdDtMf2qcnbygw9OdE535c2lxSxrZP8gO4UhDJ0xiJbl1wIqXS1OTcTDFTIJPOFd6Mhcm8gPEthqWGUxBsTqw=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
@@ -264,9 +264,9 @@
"net8.0": {
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.22, )",
"resolved": "8.0.22",
"contentHash": "MhcMithKEiyyNkD2ZfbDZPmcOdi0GheGfg8saEIIEfD/fol3iHmcV8TsZkD4ZYz5gdUuoX4YtlVySUU7Sxl9SQ=="
"requested": "[8.0.23, )",
"resolved": "8.0.23",
"contentHash": "GqHiB1HbbODWPbY/lc5xLQH8siEEhNA0ptpJCC6X6adtAYNEzu5ZlqV3YHA3Gh7fuEwgA8XqVwMtH2KNtuQM1Q=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",

View File

@@ -0,0 +1,243 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Test.Mocks;
using Xunit;
namespace SharpCompress.Test.Rar;
/// <summary>
/// Tests specifically designed to exercise the Unpack5Async code path for RAR5 archives.
/// These tests use AsyncOnlyStream to ensure that async methods are actually being called.
/// </summary>
public class Rar5AsyncExtractionTests : ArchiveTests
{
[Fact]
public async Task Rar5_Basic_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_None_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.none.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_ExtractAllEntries_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
Assert.True(await archive.IsSolidAsync());
await using var reader = await archive.ExtractAllEntriesAsync();
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_Reader_ExtractAll_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Reader_OpenEntryStream_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
var entryStream = await reader.OpenEntryStreamAsync();
try
{
var file = Path.GetFileName(reader.Entry.Key).NotNull();
var folder = Path.GetDirectoryName(reader.Entry.Key) ?? "";
var destdir = Path.Combine(SCRATCH_FILES_PATH, folder);
if (!Directory.Exists(destdir))
{
Directory.CreateDirectory(destdir);
}
var destinationFileName = Path.Combine(destdir, file);
using var fs = File.OpenWrite(destinationFileName);
await entryStream.CopyToAsync(fs);
}
finally
{
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
await entryStream.DisposeAsync();
#else
entryStream.Dispose();
#endif
}
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Encrypted_FilesOnly_Reader_Async()
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar5.encrypted_filesOnly.rar")
);
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { Password = "test" }
);
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Encrypted_FilesAndHeader_Reader_Async()
{
using var stream = File.OpenRead(
Path.Combine(TEST_ARCHIVES_PATH, "Rar5.encrypted_filesAndHeader.rar")
);
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { Password = "test" }
);
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_CRC_Blake2_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.crc_blake2.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Comment_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.comment.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_Skip_Some_Entries_Reader_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var reader = await ReaderFactory.OpenAsyncReader(new AsyncOnlyStream(stream));
while (await reader.MoveToNextEntryAsync())
{
// Only extract jpg files to test skipping in solid archive
if (!reader.Entry.IsDirectory && reader.Entry.Key.NotNull().Contains("jpg"))
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(SCRATCH_FILES_PATH);
}
}
}
[Fact]
public async Task Rar5_WriteToDirectory_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
VerifyFiles();
}
[Fact]
public async Task Rar5_Solid_WriteToDirectory_Async()
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar5.solid.rar"));
await using var archive = RarArchive.OpenAsyncArchive(new AsyncOnlyStream(stream));
Assert.True(await archive.IsSolidAsync());
await archive.WriteToDirectoryAsync(SCRATCH_FILES_PATH);
VerifyFiles();
}
}