Files
sharpcompress/tests/SharpCompress.Test/Rar/RarReaderAsyncTests.cs
2026-01-16 09:12:54 +00:00

397 lines
14 KiB
C#

using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.Rar;
using SharpCompress.Test.Mocks;
using Xunit;
namespace SharpCompress.Test.Rar;
public class RarReaderAsyncTests : ReaderTests
{
[Fact]
public async ValueTask Rar_Multi_Reader_Async() =>
await DoRar_Multi_Reader_Async([
"Rar.multi.part01.rar",
"Rar.multi.part02.rar",
"Rar.multi.part03.rar",
"Rar.multi.part04.rar",
"Rar.multi.part05.rar",
"Rar.multi.part06.rar",
]);
[Fact]
public async ValueTask Rar5_Multi_Reader_Async() =>
await DoRar_Multi_Reader_Async([
"Rar5.multi.part01.rar",
"Rar5.multi.part02.rar",
"Rar5.multi.part03.rar",
"Rar5.multi.part04.rar",
"Rar5.multi.part05.rar",
"Rar5.multi.part06.rar",
]);
private async ValueTask DoRar_Multi_Reader_Async(string[] archives)
{
using (
IReader baseReader = RarReader.OpenReader(
archives
.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
.Select(p => File.OpenRead(p))
)
)
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
VerifyFiles();
}
[Fact]
public async ValueTask Rar_Multi_Reader_Encrypted_Async() =>
await Assert.ThrowsAsync<InvalidFormatException>(async () =>
{
string[] archives =
[
"Rar.EncryptedParts.part01.rar",
"Rar.EncryptedParts.part02.rar",
"Rar.EncryptedParts.part03.rar",
"Rar.EncryptedParts.part04.rar",
"Rar.EncryptedParts.part05.rar",
"Rar.EncryptedParts.part06.rar",
];
using (
IReader baseReader = RarReader.OpenReader(
archives
.Select(s => Path.Combine(TEST_ARCHIVES_PATH, s))
.Select(p => File.OpenRead(p)),
new ReaderOptions { Password = "test" }
)
)
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
VerifyFiles();
});
[Fact]
public async ValueTask Rar_Multi_Reader_Delete_Files_Async() =>
await DoRar_Multi_Reader_Delete_Files_Async([
"Rar.multi.part01.rar",
"Rar.multi.part02.rar",
"Rar.multi.part03.rar",
"Rar.multi.part04.rar",
"Rar.multi.part05.rar",
"Rar.multi.part06.rar",
]);
[Fact]
public async ValueTask Rar5_Multi_Reader_Delete_Files_Async() =>
await DoRar_Multi_Reader_Delete_Files_Async([
"Rar5.multi.part01.rar",
"Rar5.multi.part02.rar",
"Rar5.multi.part03.rar",
"Rar5.multi.part04.rar",
"Rar5.multi.part05.rar",
"Rar5.multi.part06.rar",
]);
private async ValueTask DoRar_Multi_Reader_Delete_Files_Async(string[] archives)
{
foreach (var file in archives)
{
File.Copy(
Path.Combine(TEST_ARCHIVES_PATH, file),
Path.Combine(SCRATCH2_FILES_PATH, file)
);
}
var streams = archives
.Select(s => Path.Combine(SCRATCH2_FILES_PATH, s))
.Select(File.OpenRead)
.ToList();
using (IReader baseReader = RarReader.OpenReader(streams))
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
foreach (var stream in streams)
{
stream.Dispose();
}
VerifyFiles();
foreach (var file in archives.Select(s => Path.Combine(SCRATCH2_FILES_PATH, s)))
{
File.Delete(file);
}
}
[Fact]
public async ValueTask Rar_None_Reader_Async() =>
await ReadAsync("Rar.none.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar5_None_Reader_Async() =>
await ReadAsync("Rar5.none.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar_Reader_Async() => await ReadAsync("Rar.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar5_Reader_Async() => await ReadAsync("Rar5.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar5_CRC_Blake2_Reader_Async() =>
await ReadAsync("Rar5.crc_blake2.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar_EncryptedFileAndHeader_Reader_Async() =>
await ReadRar_Async("Rar.encrypted_filesAndHeader.rar", "test");
[Fact]
public async ValueTask Rar5_EncryptedFileAndHeader_Reader_Async() =>
await ReadRar_Async("Rar5.encrypted_filesAndHeader.rar", "test");
[Fact]
public async ValueTask Rar_EncryptedFileOnly_Reader_Async() =>
await ReadRar_Async("Rar.encrypted_filesOnly.rar", "test");
[Fact]
public async ValueTask Rar5_EncryptedFileOnly_Reader_Async() =>
await ReadRar_Async("Rar5.encrypted_filesOnly.rar", "test");
[Fact]
public async ValueTask Rar_Encrypted_Reader_Async() =>
await ReadRar_Async("Rar.Encrypted.rar", "test");
[Fact]
public async ValueTask Rar5_Encrypted_Reader_Async() =>
await ReadRar_Async("Rar5.encrypted_filesOnly.rar", "test");
private async ValueTask ReadRar_Async(string testArchive, string password) =>
await ReadAsync(
testArchive,
CompressionType.Rar,
new ReaderOptions { Password = password }
);
[Fact]
public async ValueTask Rar_Entry_Stream_Async() => await DoRar_Entry_Stream_Async("Rar.rar");
[Fact]
public async ValueTask Rar5_Entry_Stream_Async() => await DoRar_Entry_Stream_Async("Rar5.rar");
private async ValueTask DoRar_Entry_Stream_Async(string filename)
{
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename)))
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);
var entryStream = await reader.OpenEntryStreamAsync();
try
{
var file = Path.GetFileName(reader.Entry.Key).NotNull();
var folder =
Path.GetDirectoryName(reader.Entry.Key)
?? throw new ArgumentNullException();
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 ValueTask Rar_Reader_Audio_program_Async()
{
using (
var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.Audio_program.rar"))
)
await using (
var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { LookForHeader = true }
)
)
{
while (await reader.MoveToNextEntryAsync())
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
CompareFilesByPath(
Path.Combine(SCRATCH_FILES_PATH, "test.dat"),
Path.Combine(MISC_TEST_FILES_PATH, "test.dat")
);
}
[Fact]
public async ValueTask Rar_Jpg_Reader_Async()
{
using (var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Rar.jpeg.jpg")))
using (
IReader baseReader = RarReader.OpenReader(
stream,
new ReaderOptions { LookForHeader = true }
)
)
{
IAsyncReader reader = (IAsyncReader)baseReader;
while (await reader.MoveToNextEntryAsync())
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
VerifyFiles();
}
[Fact]
public async ValueTask Rar_Solid_Reader_Async() =>
await ReadAsync("Rar.solid.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar_Comment_Reader_Async() =>
await ReadAsync("Rar.comment.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar5_Comment_Reader_Async() =>
await ReadAsync("Rar5.comment.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar5_Solid_Reader_Async() =>
await ReadAsync("Rar5.solid.rar", CompressionType.Rar);
[Fact]
public async ValueTask Rar_Solid_Skip_Reader_Async() =>
await DoRar_Solid_Skip_Reader_Async("Rar.solid.rar");
[Fact]
public async ValueTask Rar5_Solid_Skip_Reader_Async() =>
await DoRar_Solid_Skip_Reader_Async("Rar5.solid.rar");
private async ValueTask DoRar_Solid_Skip_Reader_Async(string filename)
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename));
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { LookForHeader = true }
);
while (await reader.MoveToNextEntryAsync())
{
if (reader.Entry.Key.NotNull().Contains("jpg"))
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
}
[Fact]
public async ValueTask Rar_Reader_Skip_Async() => await DoRar_Reader_Skip_Async("Rar.rar");
[Fact]
public async ValueTask Rar5_Reader_Skip_Async() => await DoRar_Reader_Skip_Async("Rar5.rar");
private async ValueTask DoRar_Reader_Skip_Async(string filename)
{
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, filename));
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
new ReaderOptions { LookForHeader = true }
);
while (await reader.MoveToNextEntryAsync())
{
if (reader.Entry.Key.NotNull().Contains("jpg"))
{
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
}
private async ValueTask ReadAsync(
string testArchive,
CompressionType expectedCompression,
ReaderOptions? readerOptions = null
)
{
testArchive = Path.Combine(TEST_ARCHIVES_PATH, testArchive);
using Stream stream = File.OpenRead(testArchive);
await using var reader = await ReaderFactory.OpenAsyncReader(
new AsyncOnlyStream(stream),
readerOptions ?? new ReaderOptions()
);
while (await reader.MoveToNextEntryAsync())
{
if (!reader.Entry.IsDirectory)
{
Assert.Equal(expectedCompression, reader.Entry.CompressionType);
await reader.WriteEntryToDirectoryAsync(
SCRATCH_FILES_PATH,
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
);
}
}
VerifyFiles();
}
}