Files
sharpcompress/tests/SharpCompress.Test/Zip/Zip64Tests.cs

226 lines
6.6 KiB
C#
Raw Permalink Normal View History

2022-12-20 15:06:44 +00:00
using System;
using System.IO;
using System.Linq;
using SharpCompress.Archives;
using SharpCompress.Common;
2024-03-14 08:37:17 +00:00
using SharpCompress.Common.Zip;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Readers;
using SharpCompress.Readers.Zip;
using SharpCompress.Test.Mocks;
using SharpCompress.Writers;
using SharpCompress.Writers.Zip;
using Xunit;
2022-12-20 15:06:44 +00:00
namespace SharpCompress.Test.Zip;
public class Zip64Tests : WriterTests
{
2023-03-21 13:14:08 +00:00
public Zip64Tests()
: base(ArchiveType.Zip) { }
2022-12-20 15:06:44 +00:00
// 4GiB + 1
private const long FOUR_GB_LIMIT = ((long)uint.MaxValue) + 1;
2025-10-28 11:07:53 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
2022-12-20 15:20:49 +00:00
public void Zip64_Single_Large_File() =>
2022-12-20 15:06:44 +00:00
// One single file, requires zip64
2024-03-14 08:53:08 +00:00
RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false);
2022-12-20 15:06:44 +00:00
2025-10-28 11:07:53 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
2022-12-20 15:20:49 +00:00
public void Zip64_Two_Large_Files() =>
2022-12-20 15:06:44 +00:00
// One single file, requires zip64
2024-03-14 08:53:08 +00:00
RunSingleTest(2, FOUR_GB_LIMIT, setZip64: true, forwardOnly: false);
2022-12-20 15:06:44 +00:00
2026-01-08 12:55:16 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
2022-12-20 15:20:49 +00:00
public void Zip64_Two_Small_files() =>
2022-12-20 15:06:44 +00:00
// Multiple files, does not require zip64
2024-03-14 08:53:08 +00:00
RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: false);
2017-03-11 01:05:58 +01:00
2026-01-08 12:55:16 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
2022-12-20 15:20:49 +00:00
public void Zip64_Two_Small_files_stream() =>
2022-12-20 15:06:44 +00:00
// Multiple files, does not require zip64, and works with streams
2024-03-14 08:53:08 +00:00
RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: false, forwardOnly: true);
2026-01-08 12:55:16 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
2022-12-20 15:20:49 +00:00
public void Zip64_Two_Small_Files_Zip64() =>
2022-12-20 15:06:44 +00:00
// Multiple files, use zip64 even though it is not required
2024-03-14 08:53:08 +00:00
RunSingleTest(2, FOUR_GB_LIMIT / 2, setZip64: true, forwardOnly: false);
2022-12-20 15:06:44 +00:00
2026-01-08 12:55:16 +00:00
// [Fact]
2022-12-20 15:06:44 +00:00
[Trait("format", "zip64")]
public void Zip64_Single_Large_File_Fail()
{
try
{
2022-12-20 15:06:44 +00:00
// One single file, should fail
2024-03-14 08:53:08 +00:00
RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: false);
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException("Test did not fail?");
}
2022-12-20 15:06:44 +00:00
catch (NotSupportedException) { }
}
2026-01-08 12:55:16 +00:00
//[Fact]
2022-12-20 15:06:44 +00:00
[Trait("zip64", "true")]
public void Zip64_Single_Large_File_Zip64_Streaming_Fail()
{
try
2021-01-09 13:33:34 +00:00
{
2022-12-20 15:06:44 +00:00
// One single file, should fail (fast) with zip64
2024-03-14 08:53:08 +00:00
RunSingleTest(1, FOUR_GB_LIMIT, setZip64: true, forwardOnly: true);
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException("Test did not fail?");
}
2022-12-20 15:06:44 +00:00
catch (NotSupportedException) { }
}
2026-01-08 12:55:16 +00:00
// [Fact]
2022-12-20 15:06:44 +00:00
[Trait("zip64", "true")]
public void Zip64_Single_Large_File_Streaming_Fail()
{
try
{
2022-12-20 15:06:44 +00:00
// One single file, should fail once the write discovers the problem
2024-03-14 08:53:08 +00:00
RunSingleTest(1, FOUR_GB_LIMIT, setZip64: false, forwardOnly: true);
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException("Test did not fail?");
}
2022-12-20 15:06:44 +00:00
catch (NotSupportedException) { }
}
public void RunSingleTest(
long files,
long filesize,
2024-03-14 08:53:08 +00:00
bool setZip64,
bool forwardOnly,
long writeChunkSize = 1024 * 1024,
2022-12-20 15:06:44 +00:00
string filename = "zip64-test.zip"
)
{
filename = Path.Combine(SCRATCH2_FILES_PATH, filename);
2022-12-20 15:06:44 +00:00
if (File.Exists(filename))
{
2022-12-20 15:06:44 +00:00
File.Delete(filename);
}
2022-12-20 15:06:44 +00:00
if (!File.Exists(filename))
{
2024-03-14 08:53:08 +00:00
CreateZipArchive(filename, files, filesize, writeChunkSize, setZip64, forwardOnly);
}
2022-12-20 15:06:44 +00:00
var resForward = ReadForwardOnly(filename);
if (resForward.Item1 != files)
{
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException(
$"Incorrect number of items reported: {resForward.Item1}, should have been {files}"
);
}
2022-12-20 15:06:44 +00:00
if (resForward.Item2 != files * filesize)
{
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException(
$"Incorrect combined size reported: {resForward.Item2}, should have been {files * filesize}"
);
}
2022-12-20 15:06:44 +00:00
var resArchive = ReadArchive(filename);
if (resArchive.Item1 != files)
{
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException(
$"Incorrect number of items reported: {resArchive.Item1}, should have been {files}"
);
}
2022-12-20 15:06:44 +00:00
if (resArchive.Item2 != files * filesize)
{
2022-12-20 15:06:44 +00:00
throw new InvalidOperationException(
$"Incorrect number of items reported: {resArchive.Item2}, should have been {files * filesize}"
);
}
2022-12-20 15:06:44 +00:00
}
2022-12-20 15:06:44 +00:00
public void CreateZipArchive(
string filename,
long files,
long filesize,
long chunksize,
2024-03-14 08:53:08 +00:00
bool setZip64,
bool forwardOnly
2022-12-20 15:06:44 +00:00
)
{
var data = new byte[chunksize];
2022-12-20 15:06:44 +00:00
// Use deflate for speed
2024-03-14 08:53:08 +00:00
var opts = new ZipWriterOptions(CompressionType.Deflate) { UseZip64 = setZip64 };
2022-12-20 15:06:44 +00:00
// Use no compression to ensure we hit the limits (actually inflates a bit, but seems better than using method==Store)
2026-02-16 11:20:28 +00:00
var eo = new ZipWriterEntryOptions { CompressionLevel = 0 };
2022-12-20 15:06:44 +00:00
using var zip = File.OpenWrite(filename);
2024-03-14 08:53:08 +00:00
using var st = forwardOnly ? (Stream)new ForwardOnlyStream(zip) : zip;
2026-01-15 11:41:30 +00:00
using var zipWriter = (ZipWriter)WriterFactory.OpenWriter(st, ArchiveType.Zip, opts);
2022-12-20 15:06:44 +00:00
for (var i = 0; i < files; i++)
{
using var str = zipWriter.WriteToStream(i.ToString(), eo);
var left = filesize;
while (left > 0)
{
2022-12-20 15:06:44 +00:00
var b = (int)Math.Min(left, data.Length);
str.Write(data, 0, b);
left -= b;
}
}
2022-12-20 15:06:44 +00:00
}
2022-12-20 15:06:44 +00:00
public Tuple<long, long> ReadForwardOnly(string filename)
{
long count = 0;
long size = 0;
2026-01-12 15:01:29 +00:00
IEntry? prev = null;
2022-12-20 15:06:44 +00:00
using (var fs = File.OpenRead(filename))
2026-04-21 10:55:59 +01:00
using (
var rd = ZipReader.OpenReader(
fs,
ReaderOptions.ForExternalStream with
{
LookForHeader = false,
}
)
)
{
2022-12-20 15:06:44 +00:00
while (rd.MoveToNextEntry())
2020-05-14 13:47:21 +01:00
{
2022-12-20 15:14:22 +00:00
using (rd.OpenEntryStream()) { }
2022-12-20 15:06:44 +00:00
count++;
if (prev != null)
{
size += prev.Size;
}
2022-12-20 15:06:44 +00:00
prev = rd.Entry;
}
}
2022-12-20 15:06:44 +00:00
if (prev != null)
{
2022-12-20 15:06:44 +00:00
size += prev.Size;
}
2022-12-20 15:06:44 +00:00
return new Tuple<long, long>(count, size);
}
public Tuple<long, long> ReadArchive(string filename)
{
2026-01-15 11:41:30 +00:00
using var archive = ArchiveFactory.OpenArchive(filename);
2022-12-20 15:06:44 +00:00
return new Tuple<long, long>(
archive.Entries.Count(),
archive.Entries.Select(x => x.Size).Sum()
);
}
}