예제 #1
0
        public async Task TestReleasingFailsAtCompletion()
        {
            // Create a bounded block that's filled
            var bb = new BufferBlock <int>(new DataflowBlockOptions {
                BoundedCapacity = 1
            });

            bb.Post(1);

            // Create a source that will throw an exception when a message is released,
            // which should happen when the buffer block drops any postponed messages
            var source = new DelegatePropagator <int, int>
            {
                ReserveMessageDelegate = (header, target) => true,
                ReleaseMessageDelegate = delegate { throw new FormatException(); }
            };

            // Offer a message from the source. It'll be postponed.
            ((ITargetBlock <int>)bb).OfferMessage(new DataflowMessageHeader(1), 1, source, consumeToAccept: false);

            // Mark the block as complete.  This should cause the block to reserve/release any postponed messages,
            // which will cause the block to fault.
            bb.Complete();
            await Assert.ThrowsAsync <FormatException>(() => bb.Completion);
        }
예제 #2
0
        public async Task TestNonGreedyFailedConsume()
        {
            foreach (bool exceptionalConsume in DataflowTestHelpers.BooleanValues)
            {
                foreach (bool linkGoodFirst in DataflowTestHelpers.BooleanValues)
                {
                    const int BatchSize = 2;
                    var       bb        = new BatchBlock <int>(BatchSize, new GroupingDataflowBlockOptions {
                        Greedy = false
                    });

                    var goodSource = new BufferBlock <int>();
                    Assert.True(goodSource.Post(1));

                    if (linkGoodFirst)
                    {
                        goodSource.LinkTo(bb);
                    }

                    var badSource = new DelegatePropagator <int, int>
                    {
                        ReserveMessageDelegate = delegate { return(true); },
                        ConsumeMessageDelegate = delegate(DataflowMessageHeader header, ITargetBlock <int> target, out bool messageConsumed)
                        {
                            if (exceptionalConsume)
                            {
                                throw new FormatException();                                 // throw when attempting to consume reserved message
                            }
                            else
                            {
                                messageConsumed = false;                                 // fail when attempting to consume reserved message
                                return(0);
                            }
                        }
                    };
                    Assert.Equal(
                        expected: DataflowMessageStatus.Postponed,
                        actual: ((ITargetBlock <int>)bb).OfferMessage(new DataflowMessageHeader(2), 2, badSource, consumeToAccept: true));

                    if (!linkGoodFirst)
                    {
                        goodSource.LinkTo(bb);
                    }

                    await(exceptionalConsume ?
                          (Task)Assert.ThrowsAsync <FormatException>(() => bb.Completion) :
                          (Task)Assert.ThrowsAsync <InvalidOperationException>(() => bb.Completion));
                }
            }
        }
예제 #3
0
        public async Task TestNonGreedyReleasingFailsAtCompletion()
        {
            var joinBlock = new JoinBlock <int, int>(new GroupingDataflowBlockOptions {
                Greedy = false
            });
            var source = new DelegatePropagator <int, int>
            {
                ReserveMessageDelegate = (header, target) => true,
                ReleaseMessageDelegate = delegate { throw new FormatException(); }
            };

            joinBlock.Target1.OfferMessage(new DataflowMessageHeader(1), 1, source, consumeToAccept: true);
            joinBlock.Complete();

            await Assert.ThrowsAsync <FormatException>(() => joinBlock.Completion);
        }
예제 #4
0
        public async Task TestFaultySource()
        {
            var bb = new BufferBlock <int>(new DataflowBlockOptions {
                BoundedCapacity = 1
            });

            bb.Post(1);
            var source = new DelegatePropagator <int, int> {
                ConsumeMessageDelegate = delegate(DataflowMessageHeader messageHeader, ITargetBlock <int> target, out bool messageConsumed) {
                    throw new FormatException();
                }
            };

            Assert.Equal(
                expected: DataflowMessageStatus.Postponed,
                actual: ((ITargetBlock <int>)bb).OfferMessage(new DataflowMessageHeader(1), 2, source, true));
            Assert.Equal(expected: 1, actual: bb.Receive());
            await Assert.ThrowsAsync <FormatException>(() => bb.Completion);
        }
예제 #5
0
        public async Task TestReleasingFailsAtCompletion()
        {
            var bb = new BufferBlock <int>(new DataflowBlockOptions {
                BoundedCapacity = 1
            });

            bb.Post(1);

            var source = new DelegatePropagator <int, int>
            {
                ReserveMessageDelegate = (header, target) => true,
                ReleaseMessageDelegate = delegate { throw new FormatException(); }
            };

            ((ITargetBlock <int>)bb).OfferMessage(new DataflowMessageHeader(1), 1, source, consumeToAccept: false);

            bb.Complete();
            Assert.Equal(expected: 1, actual: bb.Receive());

            await Assert.ThrowsAsync <FormatException>(() => bb.Completion);
        }
        internal static async Task TestReserveAndRelease <T>(
            IReceivableSourceBlock <T> block, bool reservationIsTargetSpecific = true)
        {
            var tcs = new TaskCompletionSource <bool>();

            // Offer the message to a target and wait until it's postponed
            var offeredMessage = default(DataflowMessageHeader);
            var target         = new DelegatePropagator <T, T>
            {
                OfferMessageDelegate = (messageHeader, value, source, consumeToAccept) =>
                {
                    offeredMessage = messageHeader;
                    tcs.TrySetResult(true);
                    return(DataflowMessageStatus.Postponed);
                }
            };

            block.LinkTo(target);
            await tcs.Task;

            Assert.False(block.ReserveMessage(new DataflowMessageHeader(-99), target)); // reserving a different message should fail
            Assert.True(block.ReserveMessage(offeredMessage, target));                  // reserve the message
            Assert.False(block.ReserveMessage(new DataflowMessageHeader(-99), target)); // reserving a different message should still fail

            if (reservationIsTargetSpecific)
            {
                Assert.False(block.ReserveMessage(offeredMessage, DataflowBlock.NullTarget <T>()));                                        // another block tries to reserve the message
                Assert.Throws <InvalidOperationException>(() => block.ReleaseReservation(offeredMessage, DataflowBlock.NullTarget <T>())); // another block tries to release the message
            }

            T item;

            Assert.Equal(expected: !reservationIsTargetSpecific, actual: block.TryReceive(out item));                          // anyone tries to receive

            Assert.Throws <InvalidOperationException>(() => block.ReleaseReservation(new DataflowMessageHeader(-42), target)); // anyone tries to release a reservation on a different message

            block.ReleaseReservation(offeredMessage, target);                                                                  // release the reservation

            Assert.True(block.TryReceive(out item));                                                                           // now receiving should work
        }
예제 #7
0
        internal static async Task TestOfferMessage_AcceptsViaLinking <T>(ITargetBlock <T> target, int messages = 3)
        {
            var src = new BufferBlock <T>();

            var stingySource = new DelegatePropagator <T, T>
            {
                ConsumeMessageDelegate = (DataflowMessageHeader _, ITargetBlock <T> __, out bool messageConsumed) => {
                    messageConsumed = false;
                    return(default(T));
                }
            };

            Assert.Equal(
                expected: DataflowMessageStatus.NotAvailable,
                actual: target.OfferMessage(new DataflowMessageHeader(1), default(T), stingySource, consumeToAccept: true));

            src.PostRange(1, messages + 1, i => default(T));
            Assert.Equal(expected: messages, actual: src.Count);
            src.LinkTo(target);
            src.Complete();
            await src.Completion;
        }
예제 #8
0
        public async Task TestNonGreedyConsumingFailsWhileJoining()
        {
            var joinBlock = new JoinBlock <int, int>(new GroupingDataflowBlockOptions {
                Greedy = false
            });
            var source1 = new DelegatePropagator <int, int>
            {
                ReserveMessageDelegate = (header, target) => true,
                ConsumeMessageDelegate = delegate(DataflowMessageHeader messageHeader, ITargetBlock <int> target, out bool messageConsumed) {
                    throw new FormatException();
                }
            };

            joinBlock.Target1.OfferMessage(new DataflowMessageHeader(1), 1, source1, consumeToAccept: true);

            var source2 = new BufferBlock <int>();

            source2.Post(2);
            source2.LinkTo(joinBlock.Target2);

            await Assert.ThrowsAsync <FormatException>(() => joinBlock.Completion);
        }
예제 #9
0
        public async Task TestReleaseOnReserveException()
        {
            foreach (bool linkBadFirst in DataflowTestHelpers.BooleanValues)
            {
                var goodSource = new BufferBlock <int>();
                goodSource.Post(1);

                DelegatePropagator <int, int> badSource = null;
                badSource = new DelegatePropagator <int, int>
                {
                    LinkToDelegate = (target, options) =>
                    {
                        target.OfferMessage(new DataflowMessageHeader(1), 2, badSource, consumeToAccept: true);
                        return(new DelegateDisposable());
                    },
                    ReserveMessageDelegate = delegate { throw new InvalidCastException(); }
                };

                var batch = new BatchBlock <int>(2, new GroupingDataflowBlockOptions {
                    Greedy = false
                });

                if (linkBadFirst)                 // Each linking will offer a message
                {
                    badSource.LinkTo(batch);
                    goodSource.LinkTo(batch);
                }
                else
                {
                    goodSource.LinkTo(batch);
                    badSource.LinkTo(batch);
                }

                await Assert.ThrowsAnyAsync <InvalidCastException>(() => batch.Completion);

                int item;
                Assert.True(goodSource.TryReceive(out item));                 // The good message must not be Reserved
            }
        }
        internal static async Task TestReserveAndConsume <T>(
            ISourceBlock <T> block, bool reservationIsTargetSpecific = true)
        {
            bool consumed;

            block.ConsumeMessage(new DataflowMessageHeader(-99), new ActionBlock <T>(i => { }), out consumed);
            Assert.False(consumed);

            var tcs            = new TaskCompletionSource <bool>();
            var offeredMessage = default(DataflowMessageHeader);
            var target         = new DelegatePropagator <T, T>
            {
                OfferMessageDelegate = (messageHeader, value, source, consumeToAccept) =>
                {
                    offeredMessage = messageHeader;
                    tcs.TrySetResult(true);
                    return(DataflowMessageStatus.Postponed);
                }
            };

            block.LinkTo(target);
            await tcs.Task;

            Assert.True(block.ReserveMessage(offeredMessage, target));             // reserve the message

            if (reservationIsTargetSpecific)
            {
                block.ConsumeMessage(offeredMessage, new ActionBlock <T>(delegate { }), out consumed);                // different target tries to consume
                Assert.False(consumed);
            }

            block.ConsumeMessage(new DataflowMessageHeader(-99), target, out consumed);             // right target, wrong message
            Assert.False(consumed);

            block.ConsumeMessage(offeredMessage, target, out consumed);             // right target, right message
            Assert.True(consumed);
        }