Files
sharpcompress/tests/SharpCompress.Test/Streams/RewindableStreamAsyncTest.cs
2026-01-28 16:50:35 +00:00

402 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.IO;
using Xunit;
namespace SharpCompress.Test.Streams;
public class RewindableStreamAsyncTest
{
[Fact]
public async ValueTask TestRewindAsync()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(1);
bw.Write(2);
bw.Write(3);
bw.Write(4);
bw.Write(5);
bw.Write(6);
bw.Write(7);
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
stream.StartRecording();
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(3, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(4, await ReadInt32Async(stream).ConfigureAwait(false));
stream.Rewind(true);
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(3, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(4, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(5, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(6, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(7, await ReadInt32Async(stream).ConfigureAwait(false));
}
[Fact]
public async ValueTask TestIncompleteRewindAsync()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(1);
bw.Write(2);
bw.Write(3);
bw.Write(4);
bw.Write(5);
bw.Write(6);
bw.Write(7);
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
stream.StartRecording();
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(3, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(4, await ReadInt32Async(stream).ConfigureAwait(false));
stream.Rewind(true);
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(3, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(4, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(5, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(6, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(7, await ReadInt32Async(stream).ConfigureAwait(false));
}
[Fact]
public async ValueTask TestRecordingAsync()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(1);
bw.Write(2);
bw.Write(3);
bw.Write(4);
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
stream.StartRecording();
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
stream.Rewind(false);
Assert.Equal(1, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(2, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(3, await ReadInt32Async(stream).ConfigureAwait(false));
Assert.Equal(4, await ReadInt32Async(stream).ConfigureAwait(false));
}
[Fact]
public async ValueTask TestAsyncProducesSameResultAsSync()
{
var testData = new byte[100 * 4];
for (int i = 0; i < 100; i++)
{
var bytes = BitConverter.GetBytes(i);
Array.Copy(bytes, 0, testData, i * 4, 4);
}
byte[] syncResult;
byte[] asyncResult;
var ms1 = new MemoryStream(testData);
using (var stream = new RewindableStream(ms1))
{
syncResult = ReadAllSync(stream);
}
var ms2 = new MemoryStream(testData);
using (var stream = new RewindableStream(ms2))
{
asyncResult = await ReadAllAsync(stream).ConfigureAwait(false);
}
Assert.Equal(syncResult, asyncResult);
}
[Fact]
public async ValueTask TestAsyncWithRewind()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
for (int i = 0; i < 50; i++)
{
bw.Write(i);
}
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
stream.StartRecording();
var buffer = new byte[8];
await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
Assert.Equal(0, BitConverter.ToInt32(buffer, 0));
Assert.Equal(1, BitConverter.ToInt32(buffer, 4));
stream.Rewind(false);
await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
Assert.Equal(0, BitConverter.ToInt32(buffer, 0));
Assert.Equal(1, BitConverter.ToInt32(buffer, 4));
await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
Assert.Equal(2, BitConverter.ToInt32(buffer, 0));
Assert.Equal(3, BitConverter.ToInt32(buffer, 4));
}
[Fact]
public async ValueTask TestAsyncCancellationSupport()
{
var ms = new MemoryStream(new byte[10000]);
ms.Position = 0;
var stream = new RewindableStream(ms);
var cts = new CancellationTokenSource();
var buffer = new byte[4096];
// Just verify that cancellation token can be passed without throwing
int bytesRead = await stream
.ReadAsync(buffer, 0, buffer.Length, cts.Token)
.ConfigureAwait(false);
Assert.Equal(buffer.Length, bytesRead);
}
[Fact]
public async ValueTask TestAsyncEmptyBuffer()
{
var ms = new MemoryStream();
ms.Position = 0;
var stream = new RewindableStream(ms);
var buffer = new byte[0];
int bytesRead = await stream.ReadAsync(buffer, 0, 0).ConfigureAwait(false);
Assert.Equal(0, bytesRead);
}
[Fact]
public async ValueTask TestAsyncMultipleReads()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
for (int i = 0; i < 50; i++)
{
bw.Write(i);
}
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
var totalData = new byte[50 * 4];
var buffer = new byte[8];
int offset = 0;
int bytesRead;
while (
(bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0
)
{
Array.Copy(buffer, 0, totalData, offset, bytesRead);
offset += bytesRead;
}
Assert.Equal(50 * 4, offset);
Assert.Equal(0, BitConverter.ToInt32(totalData, 0));
Assert.Equal(49, BitConverter.ToInt32(totalData, 49 * 4));
}
[Fact]
public async ValueTask TestAsyncReturnsZeroAtEndOfStream()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
bw.Write(1);
bw.Write(2);
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
var buffer = new byte[4096];
int bytesRead;
while (
(bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0
) { }
Assert.Equal(0, bytesRead);
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
Assert.Equal(0, bytesRead);
}
[Fact]
public async ValueTask TestAsyncPosition()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
for (int i = 0; i < 10; i++)
{
bw.Write(i);
}
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
Assert.Equal(0, stream.Position);
var buffer = new byte[4];
await stream.ReadAsync(buffer, 0, 4).ConfigureAwait(false);
Assert.Equal(4, stream.Position);
stream.StartRecording();
await stream.ReadAsync(buffer, 0, 4).ConfigureAwait(false);
Assert.Equal(8, stream.Position);
stream.Rewind();
Assert.Equal(4, stream.Position);
}
#if !LEGACY_DOTNET
[Fact]
public async ValueTask TestAsyncMemoryCancellationSupport()
{
var ms = new MemoryStream(new byte[10000]);
ms.Position = 0;
var stream = new RewindableStream(ms);
var cts = new CancellationTokenSource();
var buffer = new byte[4096];
// Just verify that cancellation token can be passed without throwing
int bytesRead = await stream.ReadAsync(buffer.AsMemory(), cts.Token).ConfigureAwait(false);
Assert.Equal(buffer.Length, bytesRead);
}
[Fact]
public async ValueTask TestAsyncMemoryEmptyBuffer()
{
var ms = new MemoryStream();
ms.Position = 0;
var stream = new RewindableStream(ms);
var buffer = Memory<byte>.Empty;
int bytesRead = await stream.ReadAsync(buffer).ConfigureAwait(false);
Assert.Equal(0, bytesRead);
}
[Fact]
public async ValueTask TestAsyncMemoryMultipleReads()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
for (int i = 0; i < 50; i++)
{
bw.Write(i);
}
bw.Flush();
ms.Position = 0;
var stream = new RewindableStream(ms);
var totalData = new byte[50 * 4];
var buffer = new byte[8];
int offset = 0;
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer.AsMemory()).ConfigureAwait(false)) > 0)
{
Array.Copy(buffer, 0, totalData, offset, bytesRead);
offset += bytesRead;
}
Assert.Equal(50 * 4, offset);
Assert.Equal(0, BitConverter.ToInt32(totalData, 0));
Assert.Equal(49, BitConverter.ToInt32(totalData, 49 * 4));
}
#endif
private static async Task<int> ReadInt32Async(Stream stream)
{
var buffer = new byte[4];
var bytesRead = await stream.ReadAsync(buffer, 0, 4).ConfigureAwait(false);
if (bytesRead != 4)
{
throw new EndOfStreamException();
}
return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
}
#if !LEGACY_DOTNET
private static async ValueTask<int> ReadInt32AsyncMemory(Stream stream)
{
var buffer = new byte[4];
var bytesRead = await stream.ReadAsync(buffer.AsMemory()).ConfigureAwait(false);
if (bytesRead != 4)
{
throw new EndOfStreamException();
}
return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
}
#endif
private static byte[] ReadAllSync(RewindableStream stream)
{
var result = new List<byte>();
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
for (int i = 0; i < bytesRead; i++)
{
result.Add(buffer[i]);
}
}
return result.ToArray();
}
private static async Task<byte[]> ReadAllAsync(RewindableStream stream)
{
var result = new List<byte>();
var buffer = new byte[4096];
int bytesRead;
while (
(bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0
)
{
for (int i = 0; i < bytesRead; i++)
{
result.Add(buffer[i]);
}
}
return result.ToArray();
}
#if !LEGACY_DOTNET
private static async ValueTask<byte[]> ReadAllAsyncMemory(RewindableStream stream)
{
var result = new List<byte>();
var buffer = new byte[4096];
int bytesRead;
while ((bytesRead = await stream.ReadAsync(buffer.AsMemory()).ConfigureAwait(false)) > 0)
{
for (int i = 0; i < bytesRead; i++)
{
result.Add(buffer[i]);
}
}
return result.ToArray();
}
#endif
}