Browse Source

fix Decode_Cancellation tests

pull/2301/head
Anton Firszov 3 years ago
parent
commit
3a7c4f442d
  1. 42
      tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs
  2. 50
      tests/ImageSharp.Tests/TestUtilities/PausedStream.cs

42
tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs

@ -16,7 +16,7 @@ public partial class ImageTests
public Decode_Cancellation() => this.TopLevelConfiguration.StreamProcessingBufferSize = 128;
public static readonly TheoryData<string> TestFiles = new()
private static readonly string[] TestFiles = new[]
{
TestImages.Png.BikeSmall,
TestImages.Jpeg.Baseline.Jpeg420Small,
@ -28,17 +28,30 @@ public partial class ImageTests
TestImages.Pbm.RgbPlainMagick
};
private static readonly double[] CancellationPercentages = new[] { 0, 0.5, 0.9 };
public static readonly object[][] TestFilesWithPercentages = TestFiles
.SelectMany(f => CancellationPercentages.Select(p => new object[] { f, p }))
.ToArray();
[Theory]
[MemberData(nameof(TestFiles))]
public async Task IdentifyAsync_IsCancellable(string file)
[MemberData(nameof(TestFilesWithPercentages))]
public async Task IdentifyAsync_IsCancellable(string file, double percentageOfStreamReadToCancel)
{
CancellationTokenSource cts = new();
string path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, file);
using PausedStream pausedStream = new(path);
pausedStream.OnWaiting(_ =>
pausedStream.OnWaiting(s =>
{
cts.Cancel();
pausedStream.Release();
if (s.Position >= s.Length * percentageOfStreamReadToCancel)
{
cts.Cancel();
pausedStream.Release();
}
else
{
pausedStream.Next();
}
});
Configuration configuration = Configuration.CreateDefaultInstance();
@ -52,16 +65,23 @@ public partial class ImageTests
}
[Theory]
[MemberData(nameof(TestFiles))]
public async Task DecodeAsync_IsCancellable(string file)
[MemberData(nameof(TestFilesWithPercentages))]
public async Task LoadAsync_IsCancellable(string file, double percentageOfStreamReadToCancel)
{
CancellationTokenSource cts = new();
string path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, file);
using PausedStream pausedStream = new(path);
pausedStream.OnWaiting(_ =>
pausedStream.OnWaiting(s =>
{
cts.Cancel();
pausedStream.Release();
if (s.Position >= s.Length * percentageOfStreamReadToCancel)
{
cts.Cancel();
pausedStream.Release();
}
else
{
pausedStream.Next();
}
});
Configuration configuration = Configuration.CreateDefaultInstance();

50
tests/ImageSharp.Tests/TestUtilities/PausedStream.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Buffers;
namespace SixLabors.ImageSharp.Tests.TestUtilities;
public class PausedStream : Stream
@ -85,7 +87,25 @@ public class PausedStream : Stream
public override void Close() => this.Await(() => this.innerStream.Close());
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) => this.Await(() => this.innerStream.CopyToAsync(destination, bufferSize, cancellationToken));
public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
// To make sure the copy operation is buffered and pausable, we should override innerStream's strategy
// with the default Stream copy logic based from System.IO.Stream:
// https://github.com/dotnet/runtime/blob/4f53c2f7e62df44f07cf410df8a0d439f42a0a71/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs#L104-L116
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
try
{
int bytesRead;
while ((bytesRead = await this.ReadAsync(new Memory<byte>(buffer), cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, bytesRead), cancellationToken).ConfigureAwait(false);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
public override bool CanRead => this.innerStream.CanRead;
@ -115,9 +135,33 @@ public class PausedStream : Stream
public override int ReadByte() => this.Await(() => this.innerStream.ReadByte());
protected override void Dispose(bool disposing) => this.innerStream.Dispose();
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
this.innerStream.Dispose();
}
}
public override void CopyTo(Stream destination, int bufferSize) => this.Await(() => this.innerStream.CopyTo(destination, bufferSize));
public override void CopyTo(Stream destination, int bufferSize)
{
// See comments on CopyToAsync.
byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
try
{
int bytesRead;
while ((bytesRead = this.Read(buffer, 0, buffer.Length)) != 0)
{
destination.Write(buffer, 0, bytesRead);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
public override int Read(Span<byte> buffer)
{

Loading…
Cancel
Save