Pārlūkot izejas kodu

Add tests for ForEachAsync.

Bart De Smet 6 gadi atpakaļ
vecāks
revīzija
89b9338953

+ 99 - 11
Ix.NET/Source/System.Linq.Async.Tests/System/Linq/Operators/ForEachAsync.cs

@@ -14,7 +14,7 @@ namespace Tests
     public class ForEachAsync : AsyncEnumerableTests
     {
         [Fact]
-        public async Task ForEachAsync_Null()
+        public async Task ForEachAsync_Sync_Null()
         {
             await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(default, x => { }));
             await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Action<int>)));
@@ -28,7 +28,7 @@ namespace Tests
         }
 
         [Fact]
-        public async Task ForEachAsync1()
+        public async Task ForEachAsync_Sync_Simple()
         {
             var sum = 0;
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
@@ -38,7 +38,7 @@ namespace Tests
         }
 
         [Fact]
-        public async Task ForEachAsync2()
+        public async Task ForEachAsync_Sync_Indexed()
         {
             var sum = 0;
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
@@ -48,39 +48,127 @@ namespace Tests
         }
 
         [Fact]
-        public async Task ForEachAsync3Async()
+        public async Task ForEachAsync_Sync_Throws_Action()
         {
             var ex = new Exception("Bang");
-            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
+            var xs = Throw<int>(ex);
 
             await AssertThrowsAsync(xs.ForEachAsync(x => { throw ex; }), ex);
         }
 
         [Fact]
-        public async Task ForEachAsync4Async()
+        public async Task ForEachAsync_Sync_Indexed_Throws_Action()
         {
             var ex = new Exception("Bang");
+            var xs = Throw<int>(ex);
+
+            await AssertThrowsAsync(xs.ForEachAsync((int x, int i) => { throw ex; }), ex);
+        }
+
+        // REVIEW: Overloads with (T, int) and (T, CancellationToken) cause ambiguity.
+
+        [Fact]
+        public async Task ForEachAsync_Async_Null()
+        {
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(default, x => Task.CompletedTask));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, Task>)));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, int i) => Task.CompletedTask));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, int, Task>)));
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync<int>(default, x => Task.CompletedTask, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, Task>), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, int i) => Task.CompletedTask, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, int, Task>), CancellationToken.None));
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Async_Simple()
+        {
+            var sum = 0;
             var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
 
-            await AssertThrowsAsync(xs.ForEachAsync((x, i) => { throw ex; }), ex);
+            await xs.ForEachAsync(x => { sum += x; return Task.CompletedTask; });
+            Assert.Equal(10, sum);
         }
 
         [Fact]
-        public async Task ForEachAsync5Async()
+        public async Task ForEachAsync_Async_Indexed()
+        {
+            var sum = 0;
+            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
+
+            await xs.ForEachAsync((x, i) => { sum += x * i; return Task.CompletedTask; });
+            Assert.Equal(1 * 0 + 2 * 1 + 3 * 2 + 4 * 3, sum);
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Async_Throws_Action()
         {
             var ex = new Exception("Bang");
             var xs = Throw<int>(ex);
 
-            await AssertThrowsAsync(xs.ForEachAsync(x => { throw ex; }), ex);
+            await AssertThrowsAsync(xs.ForEachAsync(x => Task.FromException(ex)), ex);
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Async_Indexed_Throws_Action()
+        {
+            var ex = new Exception("Bang");
+            var xs = Throw<int>(ex);
+
+            await AssertThrowsAsync(xs.ForEachAsync((int x, int i) => Task.FromException(ex)), ex);
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Cancel_Async_Cancel_Null()
+        {
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, CancellationToken ct) => Task.CompletedTask));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, CancellationToken, Task>)));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, int i, CancellationToken ct) => Task.CompletedTask));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, int, CancellationToken, Task>)));
+
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, CancellationToken ct) => Task.CompletedTask, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, CancellationToken, Task>), CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(default, (int x, int i, CancellationToken ct) => Task.CompletedTask, CancellationToken.None));
+            await Assert.ThrowsAsync<ArgumentNullException>(() => AsyncEnumerable.ForEachAsync(Return42, default(Func<int, int, CancellationToken, Task>), CancellationToken.None));
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Cancel_Async_Cancel_Simple()
+        {
+            var sum = 0;
+            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
+
+            await xs.ForEachAsync((int x, CancellationToken ct) => { sum += x; return Task.CompletedTask; });
+            Assert.Equal(10, sum);
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Cancel_Async_Cancel_Indexed()
+        {
+            var sum = 0;
+            var xs = new[] { 1, 2, 3, 4 }.ToAsyncEnumerable();
+
+            await xs.ForEachAsync((x, i, ct) => { sum += x * i; return Task.CompletedTask; });
+            Assert.Equal(1 * 0 + 2 * 1 + 3 * 2 + 4 * 3, sum);
+        }
+
+        [Fact]
+        public async Task ForEachAsync_Cancel_Async_Cancel_Throws_Action()
+        {
+            var ex = new Exception("Bang");
+            var xs = Throw<int>(ex);
+
+            await AssertThrowsAsync(xs.ForEachAsync((int x, CancellationToken ct) => Task.FromException(ex)), ex);
         }
 
         [Fact]
-        public async Task ForEachAsync6Async()
+        public async Task ForEachAsync_Cancel_Async_Cancel_Indexed_Throws_Action()
         {
             var ex = new Exception("Bang");
             var xs = Throw<int>(ex);
 
-            await AssertThrowsAsync(xs.ForEachAsync((x, i) => { throw ex; }), ex);
+            await AssertThrowsAsync(xs.ForEachAsync((x, i, ct) => Task.FromException(ex)), ex);
         }
     }
 }

+ 7 - 2
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ForEach.cs

@@ -73,8 +73,13 @@ namespace System.Linq
             }
         }
 
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> action, CancellationToken cancellationToken)
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> action, CancellationToken cancellationToken = default)
         {
+            if (source == null)
+                throw Error.ArgumentNull(nameof(source));
+            if (action == null)
+                throw Error.ArgumentNull(nameof(action));
+
             return Core(source, action, cancellationToken);
 
             static async Task Core(IAsyncEnumerable<TSource> _source, Func<TSource, CancellationToken, Task> _action, CancellationToken _cancellationToken)
@@ -106,7 +111,7 @@ namespace System.Linq
             }
         }
 
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, Task> action, CancellationToken cancellationToken)
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, Task> action, CancellationToken cancellationToken = default)
         {
             if (source == null)
                 throw Error.ArgumentNull(nameof(source));