public void TestJoinWithFaultedTarget() { bool passed = true; var nonGreedyOptions = new GroupingDataflowBlockOptions { Greedy = false }; var goodSource = new ThrowerBlock(); var badSource = new ThrowerBlock(); var join = new JoinBlock <ThrowOn, ThrowOn>(nonGreedyOptions); var terminator = new ActionBlock <Tuple <ThrowOn, ThrowOn> >(xy => { Console.WriteLine("Terminator: We shouldn't be here - FAILED"); passed = false; }); // Pre-load the sources goodSource.Post(ThrowOn.TryReceive); // Will not throw in this test badSource.Post(ThrowOn.ConsumeMessage); // Link join.LinkTo(terminator); goodSource.LinkTo(join.Target1); badSource.LinkTo(join.Target2); Task.Delay(500).Wait(); // The Join must be faulted now passed &= TaskHasFaulted(join.Completion, "ConsumeMessage"); Assert.True(passed, string.Format("{0}", passed ? "Passed" : "FAILED")); }
private static bool TestQuickStop(bool testThrow) { bool passed = true; CancellationTokenSource cts = new CancellationTokenSource(); var options = new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }; var propagator = new TransformBlock <ThrowOn, ThrowOn>(x => { Task.Delay(200).Wait(); return(x); }, options); var thrower = new ThrowerBlock(); // Post enough messages to require long processing for (int i = 0; i < 2; i++) { propagator.Post(testThrow && i == 1 ? ThrowOn.OfferMessage : ThrowOn.TryReceive); // Throw on the second message } // Link the thrower propagator.LinkTo(thrower); // Once a message has been processed, cancel the propagator (if we are testing cancellation) SpinWait.SpinUntil(() => thrower.LastOperation == ThrowOn.OfferMessage); if (!testThrow) { cts.Cancel(); } // Wait for the propagator to complete try { var ranToCompletion = propagator.Completion.Wait(10000); passed = false; Console.WriteLine("Task is faulted or canceled (finished: {0}) - FAILED", ranToCompletion ? "ran to copmpletion" : "still running"); } catch (AggregateException ae) { passed = testThrow ? ae.InnerException is InvalidOperationException : ae.InnerException is TaskCanceledException; ae.Handle(e => true); Console.WriteLine("Task is faulted or canceled (exception) - {0}", passed ? "Passed" : "FAILED"); } return(passed); }
private static bool TestReleaseOnReserveException(bool linkBadFirst) { bool passed = true; // Bad source throws on ReserveMessage var badSource = new ThrowerBlock(); badSource.Post(ThrowOn.ReserveMessage); // Good source never throws var goodSource = new ThrowerBlock(); goodSource.Post(ThrowOn.TryReceive); // Any value unrelated to the offer/consume protocol var batch = new BatchBlock <ThrowOn>(2, new GroupingDataflowBlockOptions { Greedy = false }); // Each linking will offer a message if (linkBadFirst) { badSource.LinkTo(batch); goodSource.LinkTo(batch); } else { goodSource.LinkTo(batch); badSource.LinkTo(batch); } // The batch must be faulted Task.Delay(1).Wait(); Assert.True(TaskHasFaulted(batch.Completion, "ReserveMessage")); // The good message must not be Reserved Task.Delay(1).Wait(); Assert.True(goodSource.LastOperation != ThrowOn.ReserveMessage); Assert.True(passed, string.Format("Good message not reserved ({0}) - {1}", goodSource.LastOperation, passed ? "Passed" : "FAILED")); Assert.True(passed, string.Format("{0}", passed ? "Passed" : "FAILED")); return(passed); }
private static bool TestQuickStop(bool testThrow) { bool passed = true; CancellationTokenSource cts = new CancellationTokenSource(); var options = new ExecutionDataflowBlockOptions { CancellationToken = cts.Token }; var propagator = new TransformBlock<ThrowOn, ThrowOn>(x => { Task.Delay(200).Wait(); return x; }, options); var thrower = new ThrowerBlock(); // Post enough messages to require long processing for (int i = 0; i < 2; i++) propagator.Post(testThrow && i == 1 ? ThrowOn.OfferMessage : ThrowOn.TryReceive); // Throw on the second message // Link the thrower propagator.LinkTo(thrower); // Once a message has been processed, cancel the propagator (if we are testing cancellation) SpinWait.SpinUntil(() => thrower.LastOperation == ThrowOn.OfferMessage); if (!testThrow) cts.Cancel(); // Wait for the propagator to complete try { var ranToCompletion = propagator.Completion.Wait(10000); passed = false; Console.WriteLine("Task is faulted or canceled (finished: {0}) - FAILED", ranToCompletion ? "ran to copmpletion" : "still running"); } catch (AggregateException ae) { passed = testThrow ? ae.InnerException is InvalidOperationException : ae.InnerException is TaskCanceledException; ae.Handle(e => true); Console.WriteLine("Task is faulted or canceled (exception) - {0}", passed ? "Passed" : "FAILED"); } return passed; }
private static bool TestReleaseOnReserveException(bool linkBadFirst) { bool passed = true; // Bad source throws on ReserveMessage var badSource = new ThrowerBlock(); badSource.Post(ThrowOn.ReserveMessage); // Good source never throws var goodSource = new ThrowerBlock(); goodSource.Post(ThrowOn.TryReceive); // Any value unrelated to the offer/consume protocol var batch = new BatchBlock<ThrowOn>(2, new GroupingDataflowBlockOptions { Greedy = false }); // Each linking will offer a message if (linkBadFirst) { badSource.LinkTo(batch); goodSource.LinkTo(batch); } else { goodSource.LinkTo(batch); badSource.LinkTo(batch); } // The batch must be faulted Task.Delay(1).Wait(); Assert.True(TaskHasFaulted(batch.Completion, "ReserveMessage")); // The good message must not be Reserved Task.Delay(1).Wait(); Assert.True(goodSource.LastOperation != ThrowOn.ReserveMessage); Assert.True(passed, string.Format("Good message not reserved ({0}) - {1}", goodSource.LastOperation, passed ? "Passed" : "FAILED")); Assert.True(passed, string.Format("{0}", passed ? "Passed" : "FAILED")); return passed; }