Tar and Xz mostly work

This commit is contained in:
Adam Hathcock
2021-02-07 18:58:24 +00:00
parent 9738b812c4
commit f40d3342c8
11 changed files with 171 additions and 154 deletions

View File

@@ -1,5 +1,8 @@
using System;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.BZip2
{
@@ -65,12 +68,17 @@ namespace SharpCompress.Compressors.BZip2
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
throw new NotImplementedException();
}
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
return stream.ReadAsync(buffer, cancellationToken);
}
public override int ReadByte()
{
return stream.ReadByte();
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
@@ -83,28 +91,19 @@ namespace SharpCompress.Compressors.BZip2
stream.SetLength(value);
}
#if !NET461 && !NETSTANDARD2_0
public override int Read(Span<byte> buffer)
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = new CancellationToken())
{
return stream.Read(buffer);
return stream.WriteAsync(buffer, cancellationToken);
}
public override void Write(ReadOnlySpan<byte> buffer)
{
stream.Write(buffer);
}
#endif
public override void Write(byte[] buffer, int offset, int count)
{
stream.Write(buffer, offset, count);
throw new NotImplementedException();
}
public override void WriteByte(byte value)
{
stream.WriteByte(value);
throw new NotImplementedException();
}
/// <summary>
@@ -112,11 +111,12 @@ namespace SharpCompress.Compressors.BZip2
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static bool IsBZip2(Stream stream)
public static async ValueTask<bool> IsBZip2Async(Stream stream, CancellationToken cancellationToken)
{
BinaryReader br = new BinaryReader(stream);
byte[] chars = br.ReadBytes(2);
if (chars.Length < 2 || chars[0] != 'B' || chars[1] != 'Z')
using var rented = MemoryPool<byte>.Shared.Rent(2);
var chars = rented.Memory.Slice(0, 2);
await stream.ReadAsync(chars, cancellationToken);
if (chars.Length < 2 || chars.Span[0] != 'B' || chars.Span[1] != 'Z')
{
return false;
}

View File

@@ -1,5 +1,8 @@
using System;
using System.Buffers;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.Xz
{
@@ -15,20 +18,20 @@ namespace SharpCompress.Compressors.Xz
{
return unchecked((uint)ReadLittleEndianInt32(reader));
}
public static int ReadLittleEndianInt32(this Stream stream)
public static async ValueTask<int> ReadLittleEndianInt32(this Stream stream, CancellationToken cancellationToken)
{
byte[] bytes = new byte[4];
var read = stream.ReadFully(bytes);
if (!read)
using var buffer = MemoryPool<byte>.Shared.Rent(4);
var read = await stream.ReadAsync(buffer.Memory.Slice(0, 4), cancellationToken);
if (read != 4)
{
throw new EndOfStreamException();
}
return (bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24));
return (buffer.Memory.Span[0] + (buffer.Memory.Span[1] << 8) + (buffer.Memory.Span[2] << 16) + (buffer.Memory.Span[3] << 24));
}
internal static uint ReadLittleEndianUInt32(this Stream stream)
internal static async ValueTask<uint> ReadLittleEndianUInt32(this Stream stream, CancellationToken cancellationToken)
{
return unchecked((uint)ReadLittleEndianInt32(stream));
return unchecked((uint)await ReadLittleEndianInt32(stream, cancellationToken));
}
internal static byte[] ToBigEndianBytes(this uint uint32)

View File

@@ -12,17 +12,17 @@ namespace SharpCompress.Compressors.Xz
private static UInt32[] defaultTable;
public static UInt32 Compute(byte[] buffer)
public static UInt32 Compute(ReadOnlyMemory<byte> buffer)
{
return Compute(DefaultSeed, buffer);
}
public static UInt32 Compute(UInt32 seed, byte[] buffer)
public static UInt32 Compute(UInt32 seed, ReadOnlyMemory<byte> buffer)
{
return Compute(DefaultPolynomial, seed, buffer);
}
public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
public static UInt32 Compute(UInt32 polynomial, UInt32 seed, ReadOnlyMemory<byte> buffer)
{
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
}
@@ -61,12 +61,12 @@ namespace SharpCompress.Compressors.Xz
return createTable;
}
private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, IList<byte> buffer, int start, int size)
private static UInt32 CalculateHash(UInt32[] table, UInt32 seed, ReadOnlyMemory<byte> buffer, int start, int size)
{
var crc = seed;
for (var i = start; i < size - start; i++)
{
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
crc = (crc >> 8) ^ table[buffer.Span[i] ^ crc & 0xff];
}
return crc;

View File

@@ -23,6 +23,11 @@ namespace SharpCompress.Compressors.Xz
set => throw new NotSupportedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override void Flush()
{
throw new NotSupportedException();

View File

@@ -1,8 +1,10 @@
#nullable disable
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Compressors.Xz.Filters;
namespace SharpCompress.Compressors.Xz
@@ -19,7 +21,7 @@ namespace SharpCompress.Compressors.Xz
private bool _streamConnected;
private int _numFilters;
private byte _blockHeaderSizeByte;
private Stream _decomStream;
private Stream? _decomStream;
private bool _endOfStream;
private bool _paddingSkipped;
private bool _crcChecked;
@@ -32,12 +34,12 @@ namespace SharpCompress.Compressors.Xz
_checkSize = checkSize;
}
public override int Read(byte[] buffer, int offset, int count)
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
int bytesRead = 0;
if (!HeaderIsLoaded)
{
LoadHeader();
await LoadHeader(cancellationToken);
}
if (!_streamConnected)
@@ -45,12 +47,12 @@ namespace SharpCompress.Compressors.Xz
ConnectStream();
}
if (!_endOfStream)
if (!_endOfStream && _decomStream is not null)
{
bytesRead = _decomStream.Read(buffer, offset, count);
bytesRead = await _decomStream.ReadAsync(buffer, cancellationToken);
}
if (bytesRead != count)
if (bytesRead != buffer.Length)
{
_endOfStream = true;
}
@@ -105,12 +107,15 @@ namespace SharpCompress.Compressors.Xz
_streamConnected = true;
}
private void LoadHeader()
private async ValueTask LoadHeader(CancellationToken cancellationToken)
{
ReadHeaderSize();
byte[] headerCache = CacheHeader();
await ReadHeaderSize(cancellationToken);
using var blockHeaderWithoutCrc = MemoryPool<byte>.Shared.Rent(BlockHeaderSize - 4);
var headerCache = blockHeaderWithoutCrc.Memory.Slice(0, BlockHeaderSize - 4);
await CacheHeader(headerCache, cancellationToken);
using (var cache = new MemoryStream(headerCache))
//TODO: memory-size this
await using (var cache = new MemoryStream(headerCache.ToArray()))
using (var cachedReader = new BinaryReader(cache))
{
cachedReader.BaseStream.Position = 1; // skip the header size byte
@@ -120,33 +125,32 @@ namespace SharpCompress.Compressors.Xz
HeaderIsLoaded = true;
}
private void ReadHeaderSize()
private async ValueTask ReadHeaderSize(CancellationToken cancellationToken)
{
_blockHeaderSizeByte = (byte)BaseStream.ReadByte();
using var buffer = MemoryPool<byte>.Shared.Rent(1);
await BaseStream.ReadAsync(buffer.Memory.Slice(0, 1), cancellationToken);
_blockHeaderSizeByte = buffer.Memory.Span[0];
if (_blockHeaderSizeByte == 0)
{
throw new XZIndexMarkerReachedException();
}
}
private byte[] CacheHeader()
private async ValueTask CacheHeader(Memory<byte> blockHeaderWithoutCrc, CancellationToken cancellationToken)
{
byte[] blockHeaderWithoutCrc = new byte[BlockHeaderSize - 4];
blockHeaderWithoutCrc[0] = _blockHeaderSizeByte;
var read = BaseStream.Read(blockHeaderWithoutCrc, 1, BlockHeaderSize - 5);
blockHeaderWithoutCrc.Span[0] = _blockHeaderSizeByte;
var read = await BaseStream.ReadAsync(blockHeaderWithoutCrc.Slice( 1, BlockHeaderSize - 5), cancellationToken);
if (read != BlockHeaderSize - 5)
{
throw new EndOfStreamException("Reached end of stream unexectedly");
}
uint crc = BaseStream.ReadLittleEndianUInt32();
uint crc = await BaseStream.ReadLittleEndianUInt32(cancellationToken);
uint calcCrc = Crc32.Compute(blockHeaderWithoutCrc);
if (crc != calcCrc)
{
throw new InvalidDataException("Block header corrupt");
}
return blockHeaderWithoutCrc;
}
private void ReadBlockFlags(BinaryReader reader)

View File

@@ -1,58 +1,65 @@
using System;
using System.Buffers;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.IO;
namespace SharpCompress.Compressors.Xz
{
public class XZHeader
{
private readonly BinaryReader _reader;
private readonly byte[] MagicHeader = { 0xFD, 0x37, 0x7A, 0x58, 0x5a, 0x00 };
private readonly Stream _stream;
private static readonly ReadOnlyMemory<byte> MagicHeader = new(new byte[]{ 0xFD, 0x37, 0x7A, 0x58, 0x5a, 0x00 });
public CheckType BlockCheckType { get; private set; }
public int BlockCheckSize => ((((int)BlockCheckType) + 2) / 3) * 4;
public XZHeader(BinaryReader reader)
public XZHeader(Stream reader)
{
_reader = reader;
_stream = reader;
}
public static XZHeader FromStream(Stream stream)
public static async ValueTask<XZHeader> FromStream(Stream stream, CancellationToken cancellationToken = default)
{
var header = new XZHeader(new BinaryReader(new NonDisposingStream(stream), Encoding.UTF8));
header.Process();
var header = new XZHeader(new NonDisposingStream(stream));
await header.Process(cancellationToken);
return header;
}
public void Process()
public async ValueTask Process(CancellationToken cancellationToken = default)
{
CheckMagicBytes(_reader.ReadBytes(6));
ProcessStreamFlags();
using var header = MemoryPool<byte>.Shared.Rent(6);
await _stream.ReadAsync(header.Memory.Slice(0, 6), cancellationToken);
CheckMagicBytes(header.Memory.Slice(0, 6));
await ProcessStreamFlags(cancellationToken);
}
private void ProcessStreamFlags()
private async ValueTask ProcessStreamFlags(CancellationToken cancellationToken)
{
byte[] streamFlags = _reader.ReadBytes(2);
UInt32 crc = _reader.ReadLittleEndianUInt32();
UInt32 calcCrc = Crc32.Compute(streamFlags);
using var header = MemoryPool<byte>.Shared.Rent(6);
await _stream.ReadAsync(header.Memory.Slice(0, 2), cancellationToken);
BlockCheckType = (CheckType)(header.Memory.Span[1] & 0x0F);
byte futureUse = (byte)(header.Memory.Span[1] & 0xF0);
if (futureUse != 0 || header.Memory.Span[0] != 0)
{
throw new InvalidDataException("Unknown XZ Stream Version");
}
UInt32 crc = await _stream.ReadLittleEndianUInt32(cancellationToken);
UInt32 calcCrc = Crc32.Compute(header.Memory.Slice(0, 2));
if (crc != calcCrc)
{
throw new InvalidDataException("Stream header corrupt");
}
BlockCheckType = (CheckType)(streamFlags[1] & 0x0F);
byte futureUse = (byte)(streamFlags[1] & 0xF0);
if (futureUse != 0 || streamFlags[0] != 0)
{
throw new InvalidDataException("Unknown XZ Stream Version");
}
}
private void CheckMagicBytes(byte[] header)
private void CheckMagicBytes(ReadOnlyMemory<byte> header)
{
if (!header.SequenceEqual(MagicHeader))
if (!header.Equals(MagicHeader))
{
throw new InvalidDataException("Invalid XZ Stream");
}

View File

@@ -1,18 +1,18 @@
#nullable disable
using System;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace SharpCompress.Compressors.Xz
{
[CLSCompliant(false)]
public sealed class XZStream : XZReadOnlyStream
{
public static bool IsXZStream(Stream stream)
public static async ValueTask<bool> IsXZStreamAsync(Stream stream, CancellationToken cancellationToken = default)
{
try
{
return null != XZHeader.FromStream(stream);
return null != await XZHeader.FromStream(stream, cancellationToken);
}
catch (Exception)
{
@@ -22,7 +22,7 @@ namespace SharpCompress.Compressors.Xz
private void AssertBlockCheckTypeIsSupported()
{
switch (Header.BlockCheckType)
switch (Header?.BlockCheckType)
{
case CheckType.NONE:
break;
@@ -36,11 +36,11 @@ namespace SharpCompress.Compressors.Xz
throw new NotSupportedException("Check Type unknown to this version of decoder.");
}
}
public XZHeader Header { get; private set; }
public XZIndex Index { get; private set; }
public XZFooter Footer { get; private set; }
public XZHeader? Header { get; private set; }
public XZIndex? Index { get; private set; }
public XZFooter? Footer { get; private set; }
public bool HeaderIsRead { get; private set; }
private XZBlock _currentBlock;
private XZBlock? _currentBlock;
private bool _endOfStream;
@@ -48,7 +48,7 @@ namespace SharpCompress.Compressors.Xz
{
}
public override int Read(byte[] buffer, int offset, int count)
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
int bytesRead = 0;
if (_endOfStream)
@@ -58,11 +58,11 @@ namespace SharpCompress.Compressors.Xz
if (!HeaderIsRead)
{
ReadHeader();
await ReadHeader();
}
bytesRead = ReadBlocks(buffer, offset, count);
if (bytesRead < count)
bytesRead = await ReadBlocks(buffer, cancellationToken);
if (bytesRead < buffer.Length)
{
_endOfStream = true;
ReadIndex();
@@ -71,9 +71,9 @@ namespace SharpCompress.Compressors.Xz
return bytesRead;
}
private void ReadHeader()
private async ValueTask ReadHeader()
{
Header = XZHeader.FromStream(BaseStream);
Header = await XZHeader.FromStream(BaseStream);
AssertBlockCheckTypeIsSupported();
HeaderIsRead = true;
}
@@ -90,29 +90,29 @@ namespace SharpCompress.Compressors.Xz
// TODO verify footer
}
private int ReadBlocks(byte[] buffer, int offset, int count)
private async ValueTask<int> ReadBlocks(Memory<byte> buffer, CancellationToken cancellationToken)
{
int bytesRead = 0;
if (_currentBlock is null)
{
NextBlock();
_currentBlock = NextBlock();
}
for (; ; )
{
try
{
if (bytesRead >= count)
if (bytesRead >= buffer.Length)
{
break;
}
int remaining = count - bytesRead;
int newOffset = offset + bytesRead;
int justRead = _currentBlock.Read(buffer, newOffset, remaining);
int remaining = buffer.Length - bytesRead;
int newOffset = bytesRead;
int justRead = await _currentBlock.ReadAsync(buffer.Slice(newOffset, remaining), cancellationToken);
if (justRead < remaining)
{
NextBlock();
_currentBlock = NextBlock();
}
bytesRead += justRead;
@@ -125,9 +125,9 @@ namespace SharpCompress.Compressors.Xz
return bytesRead;
}
private void NextBlock()
private XZBlock NextBlock()
{
_currentBlock = new XZBlock(BaseStream, Header.BlockCheckType, Header.BlockCheckSize);
return new XZBlock(BaseStream, Header!.BlockCheckType, Header!.BlockCheckSize);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Archives.GZip;
//using SharpCompress.Archives.Rar;
@@ -27,7 +28,7 @@ namespace SharpCompress.Readers
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static async ValueTask<IReader> OpenAsync(Stream stream, ReaderOptions? options = null)
public static async ValueTask<IReader> OpenAsync(Stream stream, ReaderOptions? options = null, CancellationToken cancellationToken = default)
{
stream.CheckNotNull(nameof(stream));
options ??= new ReaderOptions()
@@ -42,11 +43,11 @@ namespace SharpCompress.Readers
return ZipReader.Open(rewindableStream, options);
}
rewindableStream.Rewind(false);
if (await GZipArchive.IsGZipFileAsync(rewindableStream))
if (await GZipArchive.IsGZipFileAsync(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream))
GZipStream testStream = new(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.GZip);
@@ -56,11 +57,11 @@ namespace SharpCompress.Readers
}
rewindableStream.Rewind(false);
if (BZip2Stream.IsBZip2(rewindableStream))
if (await BZip2Stream.IsBZip2Async(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
BZip2Stream testStream = new BZip2Stream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress, false);
if (await TarArchive.IsTarFileAsync(testStream))
BZip2Stream testStream = new(new NonDisposingStream(rewindableStream), CompressionMode.Decompress, false);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.BZip2);
@@ -71,8 +72,8 @@ namespace SharpCompress.Readers
if (LZipStream.IsLZipFile(rewindableStream))
{
rewindableStream.Rewind(false);
LZipStream testStream = new LZipStream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream))
LZipStream testStream = new(new NonDisposingStream(rewindableStream), CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.LZip);
@@ -86,17 +87,17 @@ namespace SharpCompress.Readers
} */
rewindableStream.Rewind(false);
if (await TarArchive.IsTarFileAsync(rewindableStream))
if (await TarArchive.IsTarFileAsync(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(true);
return await TarReader.OpenAsync(rewindableStream, options);
return await TarReader.OpenAsync(rewindableStream, options, cancellationToken);
}
rewindableStream.Rewind(false);
if (XZStream.IsXZStream(rewindableStream))
if (await XZStream.IsXZStreamAsync(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(true);
XZStream testStream = new XZStream(rewindableStream);
if (await TarArchive.IsTarFileAsync(testStream))
XZStream testStream = new(rewindableStream);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.Xz);

View File

@@ -69,17 +69,17 @@ namespace SharpCompress.Readers.Tar
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static async ValueTask<TarReader> OpenAsync(Stream stream, ReaderOptions? options = null)
public static async ValueTask<TarReader> OpenAsync(Stream stream, ReaderOptions? options = null, CancellationToken cancellationToken = default)
{
stream.CheckNotNull(nameof(stream));
options = options ?? new ReaderOptions();
RewindableStream rewindableStream = new RewindableStream(stream);
options ??= new ReaderOptions();
RewindableStream rewindableStream = new(stream);
rewindableStream.StartRecording();
if (await GZipArchive.IsGZipFileAsync(rewindableStream))
if (await GZipArchive.IsGZipFileAsync(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
GZipStream testStream = new GZipStream(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream))
GZipStream testStream = new(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.GZip);
@@ -88,11 +88,11 @@ namespace SharpCompress.Readers.Tar
}
rewindableStream.Rewind(false);
if (BZip2Stream.IsBZip2(rewindableStream))
if (await BZip2Stream.IsBZip2Async(rewindableStream, cancellationToken))
{
rewindableStream.Rewind(false);
BZip2Stream testStream = new BZip2Stream(rewindableStream, CompressionMode.Decompress, false);
if (await TarArchive.IsTarFileAsync(testStream))
BZip2Stream testStream = new(rewindableStream, CompressionMode.Decompress, false);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.BZip2);
@@ -104,8 +104,8 @@ namespace SharpCompress.Readers.Tar
if (LZipStream.IsLZipFile(rewindableStream))
{
rewindableStream.Rewind(false);
LZipStream testStream = new LZipStream(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream))
LZipStream testStream = new(rewindableStream, CompressionMode.Decompress);
if (await TarArchive.IsTarFileAsync(testStream, cancellationToken))
{
rewindableStream.Rewind(true);
return new TarReader(rewindableStream, options, CompressionType.LZip);

View File

@@ -1,5 +1,6 @@
using SharpCompress.Compressors.Xz;
using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace SharpCompress.Test.Xz
@@ -7,35 +8,33 @@ namespace SharpCompress.Test.Xz
public class XZHeaderTests : XZTestsBase
{
[Fact]
public void ChecksMagicNumber()
public async ValueTask ChecksMagicNumber()
{
var bytes = Compressed.Clone() as byte[];
bytes[3]++;
using (Stream badMagicNumberStream = new MemoryStream(bytes))
await using (Stream badMagicNumberStream = new MemoryStream(bytes))
{
BinaryReader br = new BinaryReader(badMagicNumberStream);
var header = new XZHeader(br);
var ex = Assert.Throws<InvalidDataException>(() => { header.Process(); });
var header = new XZHeader(badMagicNumberStream);
var ex = await Assert.ThrowsAsync<InvalidDataException>(async () => { await header.Process(); });
Assert.Equal("Invalid XZ Stream", ex.Message);
}
}
[Fact]
public void CorruptHeaderThrows()
public async ValueTask CorruptHeaderThrows()
{
var bytes = Compressed.Clone() as byte[];
bytes[8]++;
using (Stream badCrcStream = new MemoryStream(bytes))
{
BinaryReader br = new BinaryReader(badCrcStream);
var header = new XZHeader(br);
var ex = Assert.Throws<InvalidDataException>(() => { header.Process(); });
var header = new XZHeader(badCrcStream);
var ex = await Assert.ThrowsAsync<InvalidDataException>(async () => { await header.Process(); });
Assert.Equal("Stream header corrupt", ex.Message);
}
}
[Fact]
public void BadVersionIfCrcOkButStreamFlagUnknown()
public async ValueTask BadVersionIfCrcOkButStreamFlagUnknown()
{
var bytes = Compressed.Clone() as byte[];
byte[] streamFlags = { 0x00, 0xF4 };
@@ -44,35 +43,32 @@ namespace SharpCompress.Test.Xz
crc.CopyTo(bytes, 8);
using (Stream badFlagStream = new MemoryStream(bytes))
{
BinaryReader br = new BinaryReader(badFlagStream);
var header = new XZHeader(br);
var ex = Assert.Throws<InvalidDataException>(() => { header.Process(); });
var header = new XZHeader(badFlagStream);
var ex = await Assert.ThrowsAsync<InvalidDataException>(async () => { await header.Process(); });
Assert.Equal("Unknown XZ Stream Version", ex.Message);
}
}
[Fact]
public void ProcessesBlockCheckType()
public async ValueTask ProcessesBlockCheckType()
{
BinaryReader br = new BinaryReader(CompressedStream);
var header = new XZHeader(br);
header.Process();
var header = new XZHeader(CompressedStream);
await header.Process();
Assert.Equal(CheckType.CRC64, header.BlockCheckType);
}
[Fact]
public void CanCalculateBlockCheckSize()
public async ValueTask CanCalculateBlockCheckSize()
{
BinaryReader br = new BinaryReader(CompressedStream);
var header = new XZHeader(br);
header.Process();
var header = new XZHeader(CompressedStream);
await header.Process();
Assert.Equal(8, header.BlockCheckSize);
}
[Fact]
public void ProcessesStreamHeaderFromFactory()
public async ValueTask ProcessesStreamHeaderFromFactory()
{
var header = XZHeader.FromStream(CompressedStream);
var header = await XZHeader.FromStream(CompressedStream);
Assert.Equal(CheckType.CRC64, header.BlockCheckType);
}
}

View File

@@ -1,5 +1,6 @@
using SharpCompress.Compressors.Xz;
using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace SharpCompress.Test.Xz
@@ -7,34 +8,34 @@ namespace SharpCompress.Test.Xz
public class XZStreamTests : XZTestsBase
{
[Fact]
public void CanReadEmptyStream()
public async ValueTask CanReadEmptyStream()
{
XZStream xz = new XZStream(CompressedEmptyStream);
using (var sr = new StreamReader(xz))
{
string uncompressed = sr.ReadToEnd();
string uncompressed = await sr.ReadToEndAsync();
Assert.Equal(OriginalEmpty, uncompressed);
}
}
[Fact]
public void CanReadStream()
public async ValueTask CanReadStream()
{
XZStream xz = new XZStream(CompressedStream);
using (var sr = new StreamReader(xz))
{
string uncompressed = sr.ReadToEnd();
string uncompressed = await sr.ReadToEndAsync();
Assert.Equal(Original, uncompressed);
}
}
[Fact]
public void CanReadIndexedStream()
public async ValueTask CanReadIndexedStream()
{
XZStream xz = new XZStream(CompressedIndexedStream);
using (var sr = new StreamReader(xz))
{
string uncompressed = sr.ReadToEnd();
string uncompressed = await sr.ReadToEndAsync();
Assert.Equal(OriginalIndexed, uncompressed);
}
}