mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-02-04 05:25:00 +00:00
293 lines
12 KiB
C#
293 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using SharpCompress.Archives.Zip;
|
|
using SharpCompress.Common;
|
|
using SharpCompress.Compressors.Deflate;
|
|
using SharpCompress.Compressors.Xz;
|
|
using SharpCompress.Crypto;
|
|
using SharpCompress.Test.Mocks;
|
|
using SharpCompress.Writers;
|
|
using SharpCompress.Writers.Zip;
|
|
using Xunit;
|
|
|
|
namespace SharpCompress.Test.Zip;
|
|
|
|
public class ZipTypesLevelsWithCrcRatioAsyncTests : ArchiveTests
|
|
{
|
|
public ZipTypesLevelsWithCrcRatioAsyncTests() => UseExtensionInsteadOfNameToVerify = true;
|
|
|
|
[Theory]
|
|
[InlineData(CompressionType.Deflate, 1, 1, 0.11f)] // was 0.8f, actual 0.104
|
|
[InlineData(CompressionType.Deflate, 3, 1, 0.08f)] // was 0.8f, actual 0.078
|
|
[InlineData(CompressionType.Deflate, 6, 1, 0.05f)] // was 0.8f, actual ~0.042
|
|
[InlineData(CompressionType.Deflate, 9, 1, 0.04f)] // was 0.7f, actual 0.038
|
|
[InlineData(CompressionType.ZStandard, 1, 1, 0.025f)] // was 0.8f, actual 0.023
|
|
[InlineData(CompressionType.ZStandard, 3, 1, 0.015f)] // was 0.7f, actual 0.013
|
|
[InlineData(CompressionType.ZStandard, 9, 1, 0.006f)] // was 0.7f, actual 0.005
|
|
[InlineData(CompressionType.ZStandard, 22, 1, 0.005f)] // was 0.7f, actual 0.004
|
|
[InlineData(CompressionType.BZip2, 0, 1, 0.035f)] // was 0.8f, actual 0.033
|
|
[InlineData(CompressionType.LZMA, 0, 1, 0.005f)] // was 0.8f, actual 0.004
|
|
[InlineData(CompressionType.None, 0, 1, 1.001f)] // was 1.1f, actual 1.000
|
|
[InlineData(CompressionType.Deflate, 6, 2, 0.045f)] // was 0.8f, actual 0.042
|
|
[InlineData(CompressionType.ZStandard, 3, 2, 0.012f)] // was 0.7f, actual 0.010
|
|
[InlineData(CompressionType.BZip2, 0, 2, 0.035f)] // was 0.8f, actual 0.032
|
|
[InlineData(CompressionType.Deflate, 9, 3, 0.04f)] // was 0.7f, actual 0.038
|
|
[InlineData(CompressionType.ZStandard, 9, 3, 0.003f)] // was 0.7f, actual 0.002
|
|
public async ValueTask Zip_Create_Archive_With_3_Files_Crc32_Test_Async(
|
|
CompressionType compressionType,
|
|
int compressionLevel,
|
|
int sizeMb,
|
|
float expectedRatio
|
|
)
|
|
{
|
|
const int OneMiB = 1024 * 1024;
|
|
var baseSize = sizeMb * OneMiB;
|
|
|
|
// Generate test content for files with sizes based on the sizeMb parameter
|
|
var file1Data = TestPseudoTextStream.Create(baseSize);
|
|
var file2Data = TestPseudoTextStream.Create(baseSize * 2);
|
|
var file3Data = TestPseudoTextStream.Create(baseSize * 3);
|
|
|
|
var expectedFiles = new Dictionary<string, (byte[] data, uint crc)>
|
|
{
|
|
[$"file1_{sizeMb}MiB.txt"] = (file1Data, CalculateCrc32(file1Data)),
|
|
[$"data/file2_{sizeMb * 2}MiB.txt"] = (file2Data, CalculateCrc32(file2Data)),
|
|
[$"deep/nested/file3_{sizeMb * 3}MiB.txt"] = (file3Data, CalculateCrc32(file3Data)),
|
|
};
|
|
|
|
// Create zip archive in memory
|
|
using var zipStream = new MemoryStream();
|
|
using (
|
|
var writer = CreateWriterWithLevelAsync(zipStream, compressionType, compressionLevel)
|
|
)
|
|
{
|
|
await writer.WriteAsync($"file1_{sizeMb}MiB.txt", new MemoryStream(file1Data));
|
|
await writer.WriteAsync($"data/file2_{sizeMb * 2}MiB.txt", new MemoryStream(file2Data));
|
|
await writer.WriteAsync(
|
|
$"deep/nested/file3_{sizeMb * 3}MiB.txt",
|
|
new MemoryStream(file3Data)
|
|
);
|
|
}
|
|
|
|
// Calculate and output actual compression ratio
|
|
var originalSize = file1Data.Length + file2Data.Length + file3Data.Length;
|
|
var actualRatio = (double)zipStream.Length / originalSize;
|
|
//Debug.WriteLine($"Zip_Create_Archive_With_3_Files_Crc32_Test_Async: {compressionType} Level={compressionLevel} Size={sizeMb}MB Expected={expectedRatio:F3} Actual={actualRatio:F3}");
|
|
|
|
// Verify compression occurred (except for None compression type)
|
|
if (compressionType != CompressionType.None)
|
|
{
|
|
Assert.True(
|
|
zipStream.Length < originalSize,
|
|
$"Compression failed: compressed={zipStream.Length}, original={originalSize}"
|
|
);
|
|
}
|
|
|
|
// Verify compression ratio
|
|
VerifyCompressionRatio(
|
|
originalSize,
|
|
zipStream.Length,
|
|
expectedRatio,
|
|
$"{compressionType} level {compressionLevel}"
|
|
);
|
|
|
|
// Verify archive content and CRC32
|
|
await VerifyArchiveContentAsync(zipStream, expectedFiles);
|
|
|
|
// Verify compression type is correctly set
|
|
VerifyCompressionType(zipStream, compressionType);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(CompressionType.Deflate, 1, 4, 0.11f)] // was 0.8, actual 0.105
|
|
[InlineData(CompressionType.Deflate, 3, 4, 0.08f)] // was 0.8, actual 0.077
|
|
[InlineData(CompressionType.Deflate, 6, 4, 0.045f)] // was 0.8, actual 0.042
|
|
[InlineData(CompressionType.Deflate, 9, 4, 0.04f)] // was 0.8, actual 0.037
|
|
[InlineData(CompressionType.ZStandard, 1, 4, 0.025f)] // was 0.8, actual 0.022
|
|
[InlineData(CompressionType.ZStandard, 3, 4, 0.012f)] // was 0.8, actual 0.010
|
|
[InlineData(CompressionType.ZStandard, 9, 4, 0.003f)] // was 0.8, actual 0.002
|
|
[InlineData(CompressionType.ZStandard, 22, 4, 0.003f)] // was 0.8, actual 0.002
|
|
[InlineData(CompressionType.BZip2, 0, 4, 0.035f)] // was 0.8, actual 0.032
|
|
[InlineData(CompressionType.LZMA, 0, 4, 0.003f)] // was 0.8, actual 0.002
|
|
public async ValueTask Zip_WriterFactory_Crc32_Test_Async(
|
|
CompressionType compressionType,
|
|
int compressionLevel,
|
|
int sizeMb,
|
|
float expectedRatio
|
|
)
|
|
{
|
|
var fileSize = sizeMb * 1024 * 1024;
|
|
|
|
var testData = TestPseudoTextStream.Create(fileSize);
|
|
var expectedCrc = CalculateCrc32(testData);
|
|
|
|
// Create archive with specified compression level
|
|
using var zipStream = new MemoryStream();
|
|
var writerOptions = new ZipWriterOptions(compressionType)
|
|
{
|
|
CompressionLevel = compressionLevel,
|
|
};
|
|
|
|
using (
|
|
var writer = WriterFactory.OpenAsyncWriter(
|
|
new AsyncOnlyStream(zipStream),
|
|
ArchiveType.Zip,
|
|
writerOptions
|
|
)
|
|
)
|
|
{
|
|
await writer.WriteAsync(
|
|
$"{compressionType}_level_{compressionLevel}_{sizeMb}MiB.txt",
|
|
new MemoryStream(testData)
|
|
);
|
|
}
|
|
|
|
// Calculate and output actual compression ratio
|
|
var actualRatio = (double)zipStream.Length / testData.Length;
|
|
//Debug.WriteLine($"Zip_WriterFactory_Crc32_Test_Async: {compressionType} Level={compressionLevel} Size={sizeMb}MB Expected={expectedRatio:F3} Actual={actualRatio:F3}");
|
|
|
|
VerifyCompressionRatio(
|
|
testData.Length,
|
|
zipStream.Length,
|
|
expectedRatio,
|
|
$"{compressionType} level {compressionLevel}"
|
|
);
|
|
|
|
// Verify the archive
|
|
zipStream.Position = 0;
|
|
using var archive = ZipArchive.OpenArchive(zipStream);
|
|
|
|
var entry = archive.Entries.Single(e => !e.IsDirectory);
|
|
using var entryStream = await entry.OpenEntryStreamAsync();
|
|
using var extractedStream = new MemoryStream();
|
|
await entryStream.CopyToAsync(extractedStream);
|
|
|
|
var extractedData = extractedStream.ToArray();
|
|
var actualCrc = CalculateCrc32(extractedData);
|
|
|
|
Assert.Equal(compressionType, entry.CompressionType);
|
|
Assert.Equal(expectedCrc, actualCrc);
|
|
Assert.Equal(testData.Length, extractedData.Length);
|
|
Assert.Equal(testData, extractedData);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(CompressionType.Deflate, 1, 2, 0.11f)] // was 0.8, actual 0.104
|
|
[InlineData(CompressionType.Deflate, 3, 2, 0.08f)] // was 0.8, actual 0.077
|
|
[InlineData(CompressionType.Deflate, 6, 2, 0.045f)] // was 0.8, actual 0.042
|
|
[InlineData(CompressionType.Deflate, 9, 2, 0.04f)] // was 0.7, actual 0.038
|
|
[InlineData(CompressionType.ZStandard, 1, 2, 0.025f)] // was 0.8, actual 0.023
|
|
[InlineData(CompressionType.ZStandard, 3, 2, 0.015f)] // was 0.7, actual 0.012
|
|
[InlineData(CompressionType.ZStandard, 9, 2, 0.006f)] // was 0.7, actual 0.005
|
|
[InlineData(CompressionType.ZStandard, 22, 2, 0.005f)] // was 0.7, actual 0.004
|
|
[InlineData(CompressionType.BZip2, 0, 2, 0.035f)] // was 0.8, actual 0.032
|
|
[InlineData(CompressionType.LZMA, 0, 2, 0.005f)] // was 0.8, actual 0.004
|
|
public async ValueTask Zip_ZipArchiveOpen_Crc32_Test_Async(
|
|
CompressionType compressionType,
|
|
int compressionLevel,
|
|
int sizeMb,
|
|
float expectedRatio
|
|
)
|
|
{
|
|
var fileSize = sizeMb * 1024 * 1024;
|
|
|
|
var testData = TestPseudoTextStream.Create(fileSize);
|
|
var expectedCrc = CalculateCrc32(testData);
|
|
|
|
// Create archive with specified compression and level
|
|
using var zipStream = new MemoryStream();
|
|
using (
|
|
var writer = CreateWriterWithLevelAsync(zipStream, compressionType, compressionLevel)
|
|
)
|
|
{
|
|
await writer.WriteAsync(
|
|
$"{compressionType}_{compressionLevel}_{sizeMb}MiB.txt",
|
|
new MemoryStream(testData)
|
|
);
|
|
}
|
|
|
|
// Calculate and output actual compression ratio
|
|
var actualRatio = (double)zipStream.Length / testData.Length;
|
|
//Debug.WriteLine($"Zip_ZipArchiveOpen_Crc32_Test_Async: {compressionType} Level={compressionLevel} Size={sizeMb}MB Expected={expectedRatio:F3} Actual={actualRatio:F3}");
|
|
|
|
// Verify the archive
|
|
zipStream.Position = 0;
|
|
using var archive = ZipArchive.OpenArchive(zipStream);
|
|
|
|
var entry = archive.Entries.Single(e => !e.IsDirectory);
|
|
using var entryStream = await entry.OpenEntryStreamAsync();
|
|
using var extractedStream = new MemoryStream();
|
|
await entryStream.CopyToAsync(extractedStream);
|
|
|
|
var extractedData = extractedStream.ToArray();
|
|
var actualCrc = CalculateCrc32(extractedData);
|
|
|
|
Assert.Equal(compressionType, entry.CompressionType);
|
|
Assert.Equal(expectedCrc, actualCrc);
|
|
Assert.Equal(testData.Length, extractedData.Length);
|
|
|
|
// For smaller files, verify full content; for larger, spot check
|
|
if (testData.Length <= sizeMb * 2)
|
|
{
|
|
Assert.Equal(testData, extractedData);
|
|
}
|
|
else
|
|
{
|
|
VerifyDataSpotCheck(testData, extractedData);
|
|
}
|
|
|
|
VerifyCompressionRatio(
|
|
testData.Length,
|
|
zipStream.Length,
|
|
expectedRatio,
|
|
$"{compressionType} Level {compressionLevel}"
|
|
);
|
|
}
|
|
|
|
// Helper method for async archive content verification
|
|
private async ValueTask VerifyArchiveContentAsync(
|
|
MemoryStream zipStream,
|
|
Dictionary<string, (byte[] data, uint crc)> expectedFiles
|
|
)
|
|
{
|
|
zipStream.Position = 0;
|
|
using var archive = ZipArchive.OpenArchive(zipStream);
|
|
|
|
foreach (var entry in archive.Entries.Where(e => !e.IsDirectory))
|
|
{
|
|
Assert.True(
|
|
expectedFiles.ContainsKey(entry.Key!),
|
|
$"Unexpected file in archive: {entry.Key}"
|
|
);
|
|
|
|
var expected = expectedFiles[entry.Key!];
|
|
using var entryStream = await entry.OpenEntryStreamAsync();
|
|
using var extractedStream = new MemoryStream();
|
|
await entryStream.CopyToAsync(extractedStream);
|
|
|
|
var extractedData = extractedStream.ToArray();
|
|
var actualCrc = CalculateCrc32(extractedData);
|
|
|
|
Assert.Equal(expected.crc, actualCrc);
|
|
Assert.Equal(expected.data.Length, extractedData.Length);
|
|
|
|
// For larger files, just spot check, for smaller verify full content
|
|
var expectedData = expected.data;
|
|
if (expectedData.Length <= 2 * 1024 * 1024)
|
|
{
|
|
Assert.Equal(expectedData, extractedData);
|
|
}
|
|
else
|
|
{
|
|
VerifyDataSpotCheck(expectedData, extractedData);
|
|
}
|
|
}
|
|
|
|
Assert.Equal(expectedFiles.Count, archive.Entries.Count(e => !e.IsDirectory));
|
|
}
|
|
}
|