Browse Source

allow finer grained details logic on when to release the pause.

pull/1644/head
Scott Williams 5 years ago
parent
commit
5ccfec917e
  1. 56
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  2. 33
      tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
  3. 19
      tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs
  4. 10
      tests/ImageSharp.Tests/TestUtilities/PausedStream.cs

56
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -127,53 +127,53 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException); Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);
} }
[Fact] [Theory]
public async Task Decode_IsCancellable() [InlineData(0)]
[InlineData(0.5)]
[InlineData(0.9)]
public async Task Decode_IsCancellable(int percentageOfStreamReadToCancel)
{ {
var cts = new CancellationTokenSource();
var file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small); var file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file); using var pausedStream = new PausedStream(file);
var cts = new CancellationTokenSource(); pausedStream.OnWaiting(s =>
var testTask = Task.Run(async () =>
{ {
AsyncLocalSwitchableFilesystem.ConfigureFileSystemStream(pausedStream); if (s.Position >= s.Length * percentageOfStreamReadToCancel)
return await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{ {
using Image image = await Image.LoadAsync("someFakeFile", cts.Token); cts.Cancel();
}); pausedStream.Release();
}
else
{
// allows this/next wait to unblock
pausedStream.Next();
}
}); });
await pausedStream.FirstWaitReached; AsyncLocalSwitchableFilesystem.ConfigureFileSystemStream(pausedStream);
cts.Cancel();
// allow testTask to try and continue now we know we have started but canceled
pausedStream.Release();
await testTask; await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{
using Image image = await Image.LoadAsync("someFakeFile", cts.Token);
});
} }
[Fact] [Fact]
public async Task Identify_IsCancellable() public async Task Identify_IsCancellable()
{ {
var file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file);
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var testTask = Task.Run(async () => var file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small);
using var pausedStream = new PausedStream(file);
pausedStream.OnWaiting(s =>
{ {
AsyncLocalSwitchableFilesystem.ConfigureFileSystemStream(pausedStream); cts.Cancel();
pausedStream.Release();
return await Assert.ThrowsAsync<TaskCanceledException>(async () => await Image.IdentifyAsync("someFakeFile", cts.Token));
}); });
await pausedStream.FirstWaitReached; AsyncLocalSwitchableFilesystem.ConfigureFileSystemStream(pausedStream);
cts.Cancel();
// allow testTask to try and continue now we know we have started but canceled
pausedStream.Release();
await testTask; await Assert.ThrowsAsync<TaskCanceledException>(async () => await Image.IdentifyAsync("someFakeFile", cts.Token));
} }
// DEBUG ONLY! // DEBUG ONLY!

33
tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs

@ -315,26 +315,29 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(JpegSubsample.Ratio444)] [InlineData(JpegSubsample.Ratio444)]
public async Task Encode_IsCancellable(JpegSubsample subsample) public async Task Encode_IsCancellable(JpegSubsample subsample)
{ {
using var pausedStream = new PausedStream(new MemoryStream());
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
using var pausedStream = new PausedStream(new MemoryStream());
var testTask = Task.Run(async () => pausedStream.OnWaiting(s =>
{ {
using var image = new Image<Rgba32>(5000, 5000); // after some writing
return await Assert.ThrowsAsync<TaskCanceledException>(async () => if (s.Position >= 500)
{
cts.Cancel();
pausedStream.Release();
}
else
{ {
var encoder = new JpegEncoder() { Subsample = subsample }; // allows this/next wait to unblock
await image.SaveAsync(pausedStream, encoder, cts.Token); pausedStream.Next();
}); }
}); });
await pausedStream.FirstWaitReached; using var image = new Image<Rgba32>(5000, 5000);
cts.Cancel(); await Assert.ThrowsAsync<TaskCanceledException>(async () =>
{
// allow testTask to try and continue now we know we have started but canceled var encoder = new JpegEncoder() { Subsample = subsample };
pausedStream.Release(); await image.SaveAsync(pausedStream, encoder, cts.Token);
});
await testTask;
} }
} }
} }

19
tests/ImageSharp.Tests/Image/ImageTests.SaveAsync.cs

@ -139,25 +139,16 @@ namespace SixLabors.ImageSharp.Tests
var encoder = new PngEncoder() { CompressionLevel = PngCompressionLevel.BestCompression }; var encoder = new PngEncoder() { CompressionLevel = PngCompressionLevel.BestCompression };
using var stream = new MemoryStream(); using var stream = new MemoryStream();
var asyncStream = new AsyncStreamWrapper(stream, () => false); var asyncStream = new AsyncStreamWrapper(stream, () => false);
var pausedStream = new PausedStream(asyncStream);
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var testTask = Task.Run(async () => var pausedStream = new PausedStream(asyncStream);
pausedStream.OnWaiting(s =>
{ {
AsyncLocalSwitchableFilesystem.ConfigureFileSystemStream(pausedStream); cts.Cancel();
pausedStream.Release();
using var image = new Image<Rgba32>(5000, 5000);
return await Assert.ThrowsAsync<TaskCanceledException>(async () => await image.SaveAsync(pausedStream, encoder, cts.Token));
}); });
await pausedStream.FirstWaitReached; await Assert.ThrowsAsync<TaskCanceledException>(async () => await image.SaveAsync(pausedStream, encoder, cts.Token));
cts.Cancel();
// allow testTask to try and continue now we know we have started but canceled
pausedStream.Release();
await testTask;
} }
} }
} }

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

@ -13,11 +13,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities
private readonly SemaphoreSlim slim = new SemaphoreSlim(0); private readonly SemaphoreSlim slim = new SemaphoreSlim(0);
private readonly CancellationTokenSource cancelationTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource cancelationTokenSource = new CancellationTokenSource();
private readonly TaskCompletionSource<object> waitReached = new TaskCompletionSource<object>();
private readonly Stream innerStream; private readonly Stream innerStream;
private Action<Stream> onWaitingCallback;
public Task FirstWaitReached => this.waitReached.Task; public void OnWaiting(Action<Stream> onWaitingCallback) => this.onWaitingCallback = onWaitingCallback;
public void OnWaiting(Action onWaitingCallback) => this.OnWaiting(_ => onWaitingCallback());
public void Release() public void Release()
{ {
@ -29,13 +31,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities
private void Wait() private void Wait()
{ {
this.waitReached.TrySetResult(null);
if (this.cancelationTokenSource.IsCancellationRequested) if (this.cancelationTokenSource.IsCancellationRequested)
{ {
return; return;
} }
this.onWaitingCallback?.Invoke(this.innerStream);
try try
{ {
this.slim.Wait(this.cancelationTokenSource.Token); this.slim.Wait(this.cancelationTokenSource.Token);

Loading…
Cancel
Save