public async Task TestOrdering_Sync_OrderedDisabled(bool trustedEnumeration) { // If ordering were enabled, this test would hang. var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2, EnsureOrdered = false }; var mres = new ManualResetEventSlim(); var tb = new TransformManyBlock <int, int>(i => { if (i == 0) { mres.Wait(); } return(trustedEnumeration ? new[] { i } : Enumerable.Repeat(i, 1)); }, options); tb.Post(0); tb.Post(1); Assert.Equal(1, await tb.ReceiveAsync()); mres.Set(); Assert.Equal(0, await tb.ReceiveAsync()); tb.Complete(); await tb.Completion; }
public async Task TestOrdering_Sync_BlockingEnumeration_NoDeadlock(bool ensureOrdered) { // If iteration of the yielded enumerables happened while holding a lock, this would deadlock. var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2, EnsureOrdered = ensureOrdered }; ManualResetEventSlim mres1 = new ManualResetEventSlim(), mres2 = new ManualResetEventSlim(); var tb = new TransformManyBlock <int, int>(i => i == 0 ? BlockableIterator(mres1, mres2) : BlockableIterator(mres2, mres1), options); tb.Post(0); tb.Post(1); Assert.Equal(42, await tb.ReceiveAsync()); Assert.Equal(42, await tb.ReceiveAsync()); tb.Complete(); await tb.Completion; IEnumerable <int> BlockableIterator(ManualResetEventSlim wait, ManualResetEventSlim release) { release.Set(); wait.Wait(); yield return(42); } }
public async Task TestFaultingAndCancellation() { foreach (bool fault in DataflowTestHelpers.BooleanValues) { var cts = new CancellationTokenSource(); var tb = new TransformManyBlock <int, int>(DataflowTestHelpers.ToEnumerable, new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }); tb.PostRange(0, 4); Assert.Equal(expected: 0, actual: await tb.ReceiveAsync()); Assert.Equal(expected: 1, actual: await tb.ReceiveAsync()); if (fault) { Assert.Throws <ArgumentNullException>(() => ((IDataflowBlock)tb).Fault(null)); ((IDataflowBlock)tb).Fault(new InvalidCastException()); await Assert.ThrowsAsync <InvalidCastException>(() => tb.Completion); } else { cts.Cancel(); await Assert.ThrowsAnyAsync <OperationCanceledException>(() => tb.Completion); } Assert.Equal(expected: 0, actual: tb.InputCount); Assert.Equal(expected: 0, actual: tb.OutputCount); } }
public async Task TestCancellationExceptionsIgnored() { foreach (bool sync in DataflowTestHelpers.BooleanValues) { Func <int, IEnumerable <int> > body = i => { if ((i % 2) == 0) { throw new OperationCanceledException(); } return(new[] { i }); }; TransformManyBlock <int, int> t = sync ? new TransformManyBlock <int, int>(body) : new TransformManyBlock <int, int>(async i => await Task.Run(() => body(i))); t.PostRange(0, 2); t.Complete(); for (int i = 0; i < 2; i++) { if ((i % 2) != 0) { Assert.Equal(expected: i, actual: await t.ReceiveAsync()); } } await t.Completion; } }
public async Task TestNullTasksIgnored() { foreach (int dop in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { var tb = new TransformManyBlock <int, int>(i => { if ((i % 2) == 0) { return(null); } return(Task.Run(() => (IEnumerable <int>) new[] { i })); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop }); const int Iters = 100; tb.PostRange(0, Iters); tb.Complete(); for (int i = 0; i < Iters; i++) { if ((i % 2) != 0) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } } await tb.Completion; } }
[InlineData(2, 1, false)] // no force ordered, but dop == 1, so it doesn't matter public async Task TestOrdering_Async_OrderedEnabled(int mmpt, int dop, bool?EnsureOrdered) { const int iters = 1000; var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, MaxMessagesPerTask = mmpt }; if (EnsureOrdered == null) { Assert.True(options.EnsureOrdered); } else { options.EnsureOrdered = EnsureOrdered.Value; } var tb = new TransformManyBlock <int, int>(i => Task.FromResult(Enumerable.Repeat(i, 1)), options); tb.PostRange(0, iters); for (int i = 0; i < iters; i++) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; }
public async Task TestOrdering_Async_OrderedDisabled(bool trustedEnumeration) { // If ordering were enabled, this test would hang. var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, EnsureOrdered = false }; var tasks = new TaskCompletionSource <IEnumerable <int> > [10]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = new TaskCompletionSource <IEnumerable <int> >(); } var tb = new TransformManyBlock <int, int>(i => tasks[i].Task, options); tb.PostRange(0, tasks.Length); for (int i = tasks.Length - 1; i >= 0; i--) { tasks[i].SetResult(trustedEnumeration ? new[] { i } : Enumerable.Repeat(i, 1)); Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; }
public async Task TestOrdering() { const int iters = 9999; foreach (int mmpt in new[] { DataflowBlockOptions.Unbounded, 1 }) { foreach (int dop in new[] { 1, 2, DataflowBlockOptions.Unbounded }) { var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, MaxMessagesPerTask = mmpt }; var tb = new TransformManyBlock <int, int>(i => new[] { i, i + 1, i + 2 }, options); for (int i = 0; i < iters; i += 3) { Assert.True(tb.Post(i)); } for (int i = 0; i < iters; i++) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; } } }
public async Task TestProducerConsumer() { foreach (TaskScheduler scheduler in new[] { TaskScheduler.Default, new ConcurrentExclusiveSchedulerPair().ConcurrentScheduler }) { foreach (int maxMessagesPerTask in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { foreach (int boundedCapacity in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { foreach (int dop in new[] { 1, 2 }) { foreach (int elementsPerItem in new[] { 1, 3, 5 }) { foreach (bool sync in DataflowTestHelpers.BooleanValues) { const int Messages = 50; var options = new ExecutionDataflowBlockOptions { BoundedCapacity = boundedCapacity, MaxDegreeOfParallelism = dop, MaxMessagesPerTask = maxMessagesPerTask, TaskScheduler = scheduler }; TransformManyBlock <int, int> tb = sync ? new TransformManyBlock <int, int>(i => Enumerable.Repeat(i, elementsPerItem), options) : new TransformManyBlock <int, int>(i => TaskShim.Run(() => Enumerable.Repeat(i, elementsPerItem)), options); await TaskShim.WhenAll( TaskShim.Run(async delegate { // consumer int i = 0; int processed = 0; while (await tb.OutputAvailableAsync()) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); processed++; if (processed % elementsPerItem == 0) { i++; } } }), TaskShim.Run(async delegate { // producer for (int i = 0; i < Messages; i++) { await tb.SendAsync(i); } tb.Complete(); })); } } } } } } }
public async Task TestMultipleYields() { const int Messages = 10; var t = new TransformManyBlock <int, int>(i => Enumerable.Range(0, Messages)); t.Post(42); t.Complete(); for (int i = 0; i < Messages; i++) { Assert.False(t.Completion.IsCompleted); Assert.Equal(expected: i, actual: await t.ReceiveAsync()); } await t.Completion; }
public async Task TestReceivesAsyncEnumerable() { for (int test = 0; test < 2; test++) { var tb = new TransformManyBlock <int, int>(i => AsyncEnumerable.Repeat(i * 2, 1)); tb.PostRange(0, 5); for (int i = 0; i < 5; i++) { Assert.Equal(expected: i * 2, actual: await tb.ReceiveAsync()); } Assert.False(tb.TryReceive(out _)); Assert.False(tb.TryReceiveAll(out _)); } }
public async Task TestYieldingNoResults() { foreach (int dop in new[] { 1, Environment.ProcessorCount }) { foreach (int boundedCapacity in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { const int Modes = 3, Iters = 100; var tb = new TransformManyBlock <int, int>(i => { switch (i % Modes) { default: case 0: return(new List <int> { i }); case 1: return(new int[0]); case 2: return(new Collection <int> { i, i + 1 }); } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, BoundedCapacity = boundedCapacity }); var source = new BufferBlock <int>(); source.PostRange(0, Modes * Iters); source.Complete(); source.LinkTo(tb, new DataflowLinkOptions { PropagateCompletion = true }); int received = 0; while (await tb.OutputAvailableAsync()) { await tb.ReceiveAsync(); received++; } Assert.Equal(expected: Modes * Iters, actual: received); } } }
public async Task TestProducerConsumerAsyncEnumerable() { foreach (TaskScheduler scheduler in new[] { TaskScheduler.Default, new ConcurrentExclusiveSchedulerPair().ConcurrentScheduler }) { foreach (int maxMessagesPerTask in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { foreach (int boundedCapacity in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { foreach (int dop in new[] { 1, 2, 8 }) { foreach (int elementsPerItem in new[] { 1, 5, 100 }) { foreach (bool ensureOrdered in DataflowTestHelpers.BooleanValues) { const int Messages = 100; var options = new ExecutionDataflowBlockOptions { BoundedCapacity = boundedCapacity, MaxDegreeOfParallelism = dop, MaxMessagesPerTask = maxMessagesPerTask, TaskScheduler = scheduler, EnsureOrdered = ensureOrdered, }; TransformManyBlock <int, int> tb = new TransformManyBlock <int, int>(i => AsyncEnumerable.Repeat(i, elementsPerItem), options); await Task.WhenAll( Task.Run(async delegate // consumer { if (ensureOrdered) { int i = 0; int processed = 0; while (await tb.OutputAvailableAsync()) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); processed++; if (processed % elementsPerItem == 0) { i++; } } } else { var results = new List <int>(); await foreach (int result in tb.ReceiveAllAsync()) { results.Add(result); } IEnumerable <IGrouping <int, int> > messages = results.GroupBy(i => i); Assert.Equal(Messages, messages.Count()); Assert.All(messages, m => Assert.Equal(elementsPerItem, m.Count())); } }),
public async Task TestOrdering() { const int iters = 9999; foreach (int mmpt in new[] { DataflowBlockOptions.Unbounded, 1 }) foreach (int dop in new[] { 1, 2, DataflowBlockOptions.Unbounded }) { var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, MaxMessagesPerTask = mmpt }; var tb = new TransformManyBlock<int, int>(i => new[] { i, i + 1, i + 2 }, options); for (int i = 0; i < iters; i += 3) { Assert.True(tb.Post(i)); } for (int i = 0; i < iters; i++) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; } }
public async Task TestMultipleYields() { const int Messages = 10; var t = new TransformManyBlock<int, int>(i => Enumerable.Range(0, Messages)); t.Post(42); t.Complete(); for (int i = 0; i < Messages; i++) { Assert.False(t.Completion.IsCompleted); Assert.Equal(expected: i, actual: await t.ReceiveAsync()); } await t.Completion; }
public async Task TestFaultingAndCancellation() { foreach (bool fault in DataflowTestHelpers.BooleanValues) { var cts = new CancellationTokenSource(); var tb = new TransformManyBlock<int, int>(DataflowTestHelpers.ToEnumerable, new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }); tb.PostRange(0, 4); Assert.Equal(expected: 0, actual: await tb.ReceiveAsync()); Assert.Equal(expected: 1, actual: await tb.ReceiveAsync()); if (fault) { Assert.Throws<ArgumentNullException>(() => ((IDataflowBlock)tb).Fault(null)); ((IDataflowBlock)tb).Fault(new InvalidCastException()); await Assert.ThrowsAsync<InvalidCastException>(() => tb.Completion); } else { cts.Cancel(); await Assert.ThrowsAnyAsync<OperationCanceledException>(() => tb.Completion); } Assert.Equal(expected: 0, actual: tb.InputCount); Assert.Equal(expected: 0, actual: tb.OutputCount); } }
public async Task TestNullTasksIgnored() { foreach (int dop in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { var tb = new TransformManyBlock<int, int>(i => { if ((i % 2) == 0) return null; return Task.Run(() => (IEnumerable<int>)new[] { i }); }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop }); const int Iters = 100; tb.PostRange(0, Iters); tb.Complete(); for (int i = 0; i < Iters; i++) { if ((i % 2) != 0) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } } await tb.Completion; } }
public async Task TestYieldingNoResults() { foreach (int dop in new[] { 1, Environment.ProcessorCount }) foreach (int boundedCapacity in new[] { DataflowBlockOptions.Unbounded, 1, 2 }) { const int Modes = 3, Iters = 100; var tb = new TransformManyBlock<int, int>(i => { switch (i % Modes) { default: case 0: return new List<int> { i }; case 1: return new int[0]; case 2: return new Collection<int> { i, i + 1 }; } }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, BoundedCapacity = boundedCapacity }); var source = new BufferBlock<int>(); source.PostRange(0, Modes * Iters); source.Complete(); source.LinkTo(tb, new DataflowLinkOptions { PropagateCompletion = true }); int received = 0; while (await tb.OutputAvailableAsync()) { await tb.ReceiveAsync(); received++; } Assert.Equal(expected: Modes * Iters, actual: received); } }
[InlineData(2, 1, false)] // no force ordered, but dop == 1, so it doesn't matter public async Task TestOrdering_Async_OrderedEnabled(int mmpt, int dop, bool? EnsureOrdered) { const int iters = 1000; var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = dop, MaxMessagesPerTask = mmpt }; if (EnsureOrdered == null) { Assert.True(options.EnsureOrdered); } else { options.EnsureOrdered = EnsureOrdered.Value; } var tb = new TransformManyBlock<int, int>(i => Task.FromResult(Enumerable.Repeat(i, 1)), options); tb.PostRange(0, iters); for (int i = 0; i < iters; i++) { Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; }
public async Task TestOrdering_Async_OrderedDisabled(bool trustedEnumeration) { // If ordering were enabled, this test would hang. var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded, EnsureOrdered = false }; var tasks = new TaskCompletionSource<IEnumerable<int>>[10]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = new TaskCompletionSource<IEnumerable<int>>(); } var tb = new TransformManyBlock<int, int>(i => tasks[i].Task, options); tb.PostRange(0, tasks.Length); for (int i = tasks.Length - 1; i >= 0; i--) { tasks[i].SetResult(trustedEnumeration ? new[] { i } : Enumerable.Repeat(i, 1)); Assert.Equal(expected: i, actual: await tb.ReceiveAsync()); } tb.Complete(); await tb.Completion; }
public async Task TestOrdering_Sync_OrderedDisabled(bool trustedEnumeration) { // If ordering were enabled, this test would hang. var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2, EnsureOrdered = false }; var mres = new ManualResetEventSlim(); var tb = new TransformManyBlock<int, int>(i => { if (i == 0) mres.Wait(); return trustedEnumeration ? new[] { i } : Enumerable.Repeat(i, 1); }, options); tb.Post(0); tb.Post(1); Assert.Equal(1, await tb.ReceiveAsync()); mres.Set(); Assert.Equal(0, await tb.ReceiveAsync()); tb.Complete(); await tb.Completion; }