|
@@ -180,8 +180,7 @@ namespace Tests
|
|
|
[Fact]
|
|
|
public void CanCancelMoveNext()
|
|
|
{
|
|
|
- var evt = new ManualResetEvent(false);
|
|
|
- var xs = Blocking(evt).ToAsyncEnumerable().Select(x => x).Where(x => true);
|
|
|
+ var xs = new CancellationTestEnumerable().Select(x => x).Where(x => true);
|
|
|
|
|
|
var e = xs.GetEnumerator();
|
|
|
var cts = new CancellationTokenSource();
|
|
@@ -198,12 +197,62 @@ namespace Tests
|
|
|
{
|
|
|
Assert.True(t.IsCanceled);
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Waits WaitTimeoutMs or until cancellation is requested. If cancellation was not requested, MoveNext returns true.
|
|
|
+ /// </summary>
|
|
|
+ private sealed class CancellationTestEnumerable : IAsyncEnumerable<object>
|
|
|
+ {
|
|
|
+ public IAsyncEnumerator<object> GetEnumerator() => new TestEnumerator();
|
|
|
+
|
|
|
+ private sealed class TestEnumerator : IAsyncEnumerator<object>
|
|
|
+ {
|
|
|
+ public void Dispose()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public object Current { get; }
|
|
|
+
|
|
|
+ public async Task<bool> MoveNext(CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ await Task.Delay(WaitTimeoutMs, cancellationToken);
|
|
|
+ cancellationToken.ThrowIfCancellationRequested();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ToAsyncEnumeratorCannotCancelOnceRunning()
|
|
|
+ {
|
|
|
+ var evt = new ManualResetEvent(false);
|
|
|
+ var isRunningEvent = new ManualResetEvent(false);
|
|
|
+ var xs = Blocking(evt, isRunningEvent).ToAsyncEnumerable();
|
|
|
+
|
|
|
+ var e = xs.GetEnumerator();
|
|
|
+ var cts = new CancellationTokenSource();
|
|
|
+ var t = e.MoveNext(cts.Token);
|
|
|
+
|
|
|
+ isRunningEvent.WaitOne();
|
|
|
+ cts.Cancel();
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ t.Wait(0);
|
|
|
+ Assert.False(t.IsCanceled);
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ Assert.False(true);
|
|
|
+ }
|
|
|
|
|
|
evt.Set();
|
|
|
}
|
|
|
|
|
|
- static IEnumerable<int> Blocking(ManualResetEvent evt)
|
|
|
+ static IEnumerable<int> Blocking(ManualResetEvent evt, ManualResetEvent blockingStarted)
|
|
|
{
|
|
|
+ blockingStarted.Set();
|
|
|
evt.WaitOne();
|
|
|
yield return 42;
|
|
|
}
|