Example #1
0
        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;
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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;
            }
        }
Example #5
0
        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;
            }
        }
Example #6
0
        [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;
        }
Example #7
0
        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;
        }
Example #8
0
        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();
                                    }));
                                }
                            }
                        }
                    }
                }
            }
        }
Example #10
0
        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;
        }