mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 07:25:11 +00:00
252 lines
9.2 KiB
C#
252 lines
9.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using SharpCompress.Archives;
|
|
using SharpCompress.Archives.GZip;
|
|
using SharpCompress.Archives.Tar;
|
|
using SharpCompress.Common;
|
|
using SharpCompress.Compressors;
|
|
using SharpCompress.Compressors.Deflate;
|
|
using SharpCompress.Readers;
|
|
using SharpCompress.Test.Mocks;
|
|
using SharpCompress.Writers;
|
|
using SharpCompress.Writers.GZip;
|
|
using SharpCompress.Writers.Tar;
|
|
using Xunit;
|
|
|
|
namespace SharpCompress.Test.GZip;
|
|
|
|
public class GZipArchiveTests : ArchiveTests
|
|
{
|
|
public GZipArchiveTests() => UseExtensionInsteadOfNameToVerify = true;
|
|
|
|
[Fact]
|
|
public void GZip_Archive_Generic()
|
|
{
|
|
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
|
|
using (var archive = GZipArchive.OpenArchive(stream))
|
|
{
|
|
var entry = archive.Entries.First();
|
|
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
|
|
|
var size = entry.Size;
|
|
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"));
|
|
var test = new FileInfo(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
|
|
|
Assert.Equal(size, scratch.Length);
|
|
Assert.Equal(size, test.Length);
|
|
}
|
|
CompareArchivesByPath(
|
|
Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void GZip_Archive()
|
|
{
|
|
using (Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
|
|
using (var archive = GZipArchive.OpenArchive(stream))
|
|
{
|
|
var entry = archive.Entries.First();
|
|
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
|
|
|
var size = entry.Size;
|
|
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"));
|
|
var test = new FileInfo(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"));
|
|
|
|
Assert.Equal(size, scratch.Length);
|
|
Assert.Equal(size, test.Length);
|
|
}
|
|
CompareArchivesByPath(
|
|
Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"),
|
|
Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar")
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void GZip_Archive_NoAdd()
|
|
{
|
|
var jpg = Path.Combine(ORIGINAL_FILES_PATH, "jpg", "test.jpg");
|
|
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
|
using var archive = GZipArchive.OpenArchive(stream);
|
|
Assert.Throws<InvalidFormatException>(() => archive.AddEntry("jpg\\test.jpg", jpg));
|
|
archive.SaveTo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar.gz"), new GZipWriterOptions());
|
|
}
|
|
|
|
[Fact]
|
|
public void GZip_Archive_Multiple_Reads()
|
|
{
|
|
var inputStream = new MemoryStream();
|
|
using (var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz")))
|
|
{
|
|
fileStream.CopyTo(inputStream);
|
|
inputStream.Position = 0;
|
|
}
|
|
using var archive = GZipArchive.OpenArchive(inputStream);
|
|
var archiveEntry = archive.Entries.First();
|
|
|
|
MemoryStream tarStream;
|
|
using (var entryStream = archiveEntry.OpenEntryStream())
|
|
{
|
|
tarStream = new MemoryStream();
|
|
entryStream.CopyTo(tarStream);
|
|
}
|
|
var size = tarStream.Length;
|
|
using (var entryStream = archiveEntry.OpenEntryStream())
|
|
{
|
|
tarStream = new MemoryStream();
|
|
entryStream.CopyTo(tarStream);
|
|
}
|
|
Assert.Equal(size, tarStream.Length);
|
|
using (var entryStream = archiveEntry.OpenEntryStream())
|
|
{
|
|
var result = TarArchive.IsTarFile(entryStream);
|
|
Assert.True(result);
|
|
}
|
|
Assert.Equal(size, tarStream.Length);
|
|
using (var entryStream = archiveEntry.OpenEntryStream())
|
|
{
|
|
tarStream = new MemoryStream();
|
|
entryStream.CopyTo(tarStream);
|
|
}
|
|
Assert.Equal(size, tarStream.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void GZip_Archive_EntryStream_Can_Be_Opened_As_Tar_Reader()
|
|
{
|
|
var sourceDirectory = Path.Combine(SCRATCH_FILES_PATH, "srcdir");
|
|
Directory.CreateDirectory(sourceDirectory);
|
|
File.WriteAllText(Path.Combine(sourceDirectory, "a.txt"), "i am a.txt");
|
|
|
|
var subDirectory = Path.Combine(sourceDirectory, "sub");
|
|
Directory.CreateDirectory(subDirectory);
|
|
File.WriteAllText(Path.Combine(subDirectory, "suba.txt"), "i am suba.txt");
|
|
|
|
var archivePath = Path.Combine(SCRATCH_FILES_PATH, "srcdir.tar.gz");
|
|
using (var fileStream = File.Create(archivePath))
|
|
using (var gzipStream = new GZipStream(fileStream, CompressionMode.Compress))
|
|
using (var tarArchive = TarArchive.CreateArchive())
|
|
{
|
|
tarArchive.AddAllFromDirectory(sourceDirectory, "*", SearchOption.AllDirectories);
|
|
tarArchive.SaveTo(gzipStream, new TarWriterOptions(CompressionType.None, false));
|
|
}
|
|
|
|
var destinationDirectory = Path.Combine(SCRATCH_FILES_PATH, "destdir");
|
|
Directory.CreateDirectory(destinationDirectory);
|
|
using var archive = GZipArchive.OpenArchive(archivePath);
|
|
using var entryStream = archive.Entries.First().OpenEntryStream();
|
|
using var reader = ReaderFactory.OpenReader(entryStream);
|
|
while (reader.MoveToNextEntry())
|
|
{
|
|
if (!reader.Entry.IsDirectory && reader.Entry.Size > 0)
|
|
{
|
|
reader.WriteEntryToDirectory(
|
|
destinationDirectory,
|
|
new ExtractionOptions { ExtractFullPath = true, Overwrite = true }
|
|
);
|
|
}
|
|
}
|
|
|
|
Assert.Equal("i am a.txt", File.ReadAllText(Path.Combine(destinationDirectory, "a.txt")));
|
|
Assert.Equal(
|
|
"i am suba.txt",
|
|
File.ReadAllText(Path.Combine(destinationDirectory, "sub", "suba.txt"))
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void TestGzCrcWithMostSignificantBitNotNegative()
|
|
{
|
|
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
|
using var archive = GZipArchive.OpenArchive(stream);
|
|
//process all entries in solid archive until the one we want to test
|
|
foreach (var entry in archive.Entries.Where(entry => !entry.IsDirectory))
|
|
{
|
|
Assert.InRange(entry.Crc, 0L, 0xFFFFFFFFL);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void TestGzArchiveTypeGzip()
|
|
{
|
|
using var stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
|
using var archive = GZipArchive.OpenArchive(stream);
|
|
Assert.Equal(archive.Type, ArchiveType.GZip);
|
|
}
|
|
|
|
[Fact]
|
|
public void GZipArchive_StreamCollection_Throws_On_NonSeekable_Stream()
|
|
{
|
|
using var nonSeekable = new ForwardOnlyStream(new MemoryStream());
|
|
using var seekable = new MemoryStream();
|
|
|
|
Assert.Throws<ArgumentException>(() => GZipArchive.OpenArchive([nonSeekable, seekable]));
|
|
}
|
|
|
|
[Fact]
|
|
public void GZipArchive_Stream_Throws_On_Unreadable_Stream()
|
|
{
|
|
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
|
|
|
Assert.Throws<ArgumentException>(() => GZipArchive.OpenArchive(unreadable));
|
|
}
|
|
|
|
[Fact]
|
|
public void GZip_Archive_NonSeekableStream()
|
|
{
|
|
// Test that GZip extraction works with non-seekable streams (like HttpBaseStream)
|
|
using var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
|
|
var buffer = new MemoryStream();
|
|
fileStream.CopyTo(buffer);
|
|
buffer.Position = 0;
|
|
|
|
// Create a non-seekable wrapper around the MemoryStream
|
|
using var nonSeekableStream = new NonSeekableStream(buffer);
|
|
using var reader = SharpCompress.Readers.GZip.GZipReader.OpenReader(nonSeekableStream);
|
|
|
|
// Verify we can move to the first entry and read it without exceptions
|
|
Assert.True(reader.MoveToNextEntry());
|
|
Assert.NotNull(reader.Entry);
|
|
|
|
// Extract and verify the entry can be read
|
|
using var outputStream = new MemoryStream();
|
|
reader.WriteEntryTo(outputStream);
|
|
|
|
Assert.True(outputStream.Length > 0);
|
|
}
|
|
|
|
// Helper class to simulate a non-seekable stream like HttpBaseStream
|
|
private class NonSeekableStream : Stream
|
|
{
|
|
private readonly Stream _baseStream;
|
|
|
|
public NonSeekableStream(Stream baseStream) => _baseStream = baseStream;
|
|
|
|
public override bool CanRead => _baseStream.CanRead;
|
|
public override bool CanSeek => false; // Simulate non-seekable stream
|
|
public override bool CanWrite => false;
|
|
public override long Length => throw new NotSupportedException();
|
|
|
|
public override long Position
|
|
{
|
|
get => throw new NotSupportedException();
|
|
set => throw new NotSupportedException();
|
|
}
|
|
|
|
public override void Flush() => _baseStream.Flush();
|
|
|
|
public override int Read(byte[] buffer, int offset, int count) =>
|
|
_baseStream.Read(buffer, offset, count);
|
|
|
|
public override long Seek(long offset, SeekOrigin origin) =>
|
|
throw new NotSupportedException();
|
|
|
|
public override void SetLength(long value) => throw new NotSupportedException();
|
|
|
|
public override void Write(byte[] buffer, int offset, int count) =>
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|