public async Task ProducesCartesianProductOfInputs()
        {
            var block  = new CartesianProductBlock <int, string>();
            var target = new BufferBlock <Tuple <int, string> >();

            var left  = block.Left;
            var right = block.Right;

            block.LinkTo(target, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            Assert.IsTrue(left.Post(1));
            Assert.IsTrue(right.Post("a"));
            Assert.IsTrue(left.Post(2));
            Assert.IsTrue(right.Post("b"));

            left.Complete();
            right.Complete();

            var actual = await Drain(target);

            var expected = new List <Tuple <int, string> >()
            {
                Tuple.Create(1, "a"),
                Tuple.Create(2, "a"),
                Tuple.Create(1, "b"),
                Tuple.Create(2, "b"),
            };

            Console.WriteLine("Made it to end");

            CollectionAssert.AreEquivalent(expected, actual.ToList());
        }
        public async Task UnlinkingNoLongerPropagatesMessages()
        {
            var block   = new CartesianProductBlock <int, string>();
            var target  = new BufferBlock <Tuple <int, string> >();
            var target2 = new BufferBlock <Tuple <int, string> >();

            var link = block.LinkTo(target, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            link.Dispose();
            block.LinkTo(target2);

            block.Left.Post(1);
            block.Right.Post("a");

            block.Complete();
            await AssertCompletes(block.Completion);

            target.Complete();
            await AssertCompletes(target.Completion);

            Assert.AreEqual(0, target.Count);
            Assert.AreEqual(1, target2.Count);
        }
        public async Task CompletesWhenBothInputsComplete()
        {
            var block = new CartesianProductBlock <int, string>();

            block.Left.Complete();
            block.Right.Complete();

            await AssertCompletes(block.Completion);
        }
        public async Task PropagatesCompletionWhenAsked()
        {
            var block  = new CartesianProductBlock <int, string>();
            var target = new BufferBlock <Tuple <int, string> >();

            block.LinkTo(target, new DataflowLinkOptions()
            {
                PropagateCompletion = true
            });

            block.Complete();
            await AssertCompletes(block.Completion);
            await AssertCompletes(target.Completion);
        }
        public async Task DoesNotPropagateCompletenessWhenNotAsked()
        {
            var block  = new CartesianProductBlock <int, string>();
            var target = new BufferBlock <Tuple <int, string> >();

            block.LinkTo(target, new DataflowLinkOptions()
            {
                PropagateCompletion = false
            });

            block.Complete();
            await AssertCompletes(block.Completion);

            Assert.IsTrue(!target.Completion.IsCompleted);
        }
        public async Task UnlinkingNoLongerPropagatesCompleteness()
        {
            var block  = new CartesianProductBlock <int, string>();
            var target = new BufferBlock <Tuple <int, string> >();

            var link = block.LinkTo(target, new DataflowLinkOptions()
            {
                PropagateCompletion = true
            });

            link.Dispose();

            block.Complete();
            await AssertCompletes(block.Completion);

            Assert.IsFalse(target.Completion.IsCompleted);
        }