using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using My.Company;
using My.Company.Common;
using Xunit;
public class TestPatternServicesAsyncCancel
{
[Fact]
public async Task LongRunningCompletesNormally()
{
using var s = ServiceAsyncCancel.Create();
var result = await s.LongRunning(5, 10);
Assert.Equal(5u, result);
}
[Fact]
public async Task LongRunningCancelledByToken()
{
using var s = ServiceAsyncCancel.Create();
using var cts = new CancellationTokenSource();
var task = s.LongRunning(100, 50, cts.Token);
cts.CancelAfter(200);
var sw = Stopwatch.StartNew();
await Assert.ThrowsAnyAsync<Exception>(async () => await task);
sw.Stop();
Assert.True(sw.ElapsedMilliseconds < 3000);
}
[Fact]
public async Task SleepForeverCancelledByToken()
{
using var s = ServiceAsyncCancel.Create();
using var cts = new CancellationTokenSource(300);
var sw = Stopwatch.StartNew();
await Assert.ThrowsAnyAsync<Exception>(async () => await s.SleepForever(cts.Token));
sw.Stop();
Assert.True(sw.ElapsedMilliseconds < 3000);
}
[Fact]
public async Task PreCancelledTokenThrowsImmediately()
{
using var s = ServiceAsyncCancel.Create();
using var cts = new CancellationTokenSource();
cts.Cancel();
var sw = Stopwatch.StartNew();
await Assert.ThrowsAnyAsync<Exception>(async () => await s.LongRunning(1000, 100, cts.Token));
sw.Stop();
Assert.True(sw.ElapsedMilliseconds < 3000);
}
[Fact]
public async Task DefaultTokenDoesNotCancel()
{
using var s = ServiceAsyncCancel.Create();
var result = await s.LongRunning(5, 10, CancellationToken.None);
Assert.Equal(5u, result);
}
[Fact]
public async Task CancelOneOfManyParallelTasks()
{
using var s = ServiceAsyncCancel.Create();
using var cts = new CancellationTokenSource(200);
var cancelledTask = s.LongRunning(1000, 50, cts.Token);
var normalTasks = Enumerable.Range(0, 3)
.Select(_ => s.LongRunning(3, 10))
.ToArray();
var results = await Task.WhenAll(normalTasks);
Assert.All(results, r => Assert.Equal(3u, r));
await Assert.ThrowsAnyAsync<Exception>(async () => await cancelledTask);
}
[Fact]
public async Task CountingWorkStopsAfterCancel()
{
using var s = ServiceAsyncCancel.Create();
using var cts = new CancellationTokenSource();
var task = s.CountingWork(200, 20, cts.Token);
await Task.Delay(500);
cts.Cancel();
await Assert.ThrowsAnyAsync<Exception>(async () => await task);
var counterAtCancel = s.Counter();
await Task.Delay(500);
var counterAfterWait = s.Counter();
Assert.True(counterAtCancel > 0);
Assert.True(counterAtCancel < 200);
Assert.Equal(counterAtCancel, counterAfterWait);
}
[Fact]
public async Task RepeatedCancelAndReuse()
{
using var s = ServiceAsyncCancel.Create();
for (var i = 0; i < 5; i++)
{
using var cts = new CancellationTokenSource(100);
await Assert.ThrowsAnyAsync<Exception>(async () => await s.SleepForever(cts.Token));
}
var result = await s.LongRunning(3, 10);
Assert.Equal(3u, result);
}
}