5 // Marek Safar <marek.safar@gmail.com>
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33 using System.Threading;
34 using System.Threading.Tasks;
35 using System.Collections.Generic;
36 using NUnit.Framework;
39 using NUnit.Framework.SyntaxHelpers;
42 namespace MonoTests.System.Threading.Tasks
45 public class TaskTests
47 class MockScheduler : TaskScheduler
49 public event Action<Task, bool> TryExecuteTaskInlineHandler;
51 protected override IEnumerable<Task> GetScheduledTasks ()
53 throw new NotImplementedException ();
56 protected override void QueueTask (Task task)
61 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
63 if (TryExecuteTaskInlineHandler != null)
64 TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
66 return base.TryExecuteTask (task);
77 tasks = new Task[max];
80 void InitWithDelegate(Action action)
82 for (int i = 0; i < max; i++) {
83 tasks[i] = Task.Factory.StartNew(action);
88 public void WaitAnyTest()
90 ParallelTestHelper.Repeat (delegate {
94 InitWithDelegate(delegate {
95 int times = Interlocked.Exchange (ref flag, 1);
97 SpinWait sw = new SpinWait ();
98 while (finished == 0) sw.SpinOnce ();
100 Interlocked.Increment (ref finished);
104 int index = Task.WaitAny(tasks, 1000);
106 Assert.AreNotEqual (-1, index, "#3");
107 Assert.AreEqual (1, flag, "#1");
108 Assert.AreEqual (1, finished, "#2");
113 public void WaitAny_Empty ()
115 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
119 public void WaitAny_Zero ()
121 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
122 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
126 public void WaitAny_Cancelled ()
128 var cancelation = new CancellationTokenSource ();
129 var tasks = new Task[] {
130 new Task (delegate { }),
131 new Task (delegate { }, cancelation.Token)
134 cancelation.Cancel ();
136 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
137 Assert.IsTrue (tasks[1].IsCompleted, "#2");
138 Assert.IsTrue (tasks[1].IsCanceled, "#3");
142 public void WaitAny_CancelledWithoutExecution ()
144 var cancelation = new CancellationTokenSource ();
145 var tasks = new Task[] {
146 new Task (delegate { }),
147 new Task (delegate { })
151 var mre = new ManualResetEventSlim (false);
152 ThreadPool.QueueUserWorkItem (delegate {
153 res = Task.WaitAny (tasks, 20);
157 cancelation.Cancel ();
158 Assert.IsTrue (mre.Wait (1000), "#1");
159 Assert.AreEqual (-1, res);
163 public void WaitAny_OneException ()
165 var mre = new ManualResetEventSlim (false);
166 var tasks = new Task[] {
167 Task.Factory.StartNew (delegate { mre.Wait (1000); }),
168 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
171 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
172 Assert.IsFalse (tasks[0].IsCompleted, "#2");
173 Assert.IsTrue (tasks[1].IsFaulted, "#3");
179 public void WaitAny_SingleCanceled ()
181 var src = new CancellationTokenSource ();
182 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
183 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
186 public void WaitAny_ManyExceptions ()
188 CountdownEvent cde = new CountdownEvent (3);
190 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
191 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
192 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
195 Assert.IsTrue (cde.Wait (1000), "#1");
198 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
199 } catch (AggregateException e) {
200 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
205 public void WaitAny_ManyCanceled ()
207 var cancellation = new CancellationToken (true);
209 Task.Factory.StartNew (delegate { }, cancellation),
210 Task.Factory.StartNew (delegate { }, cancellation),
211 Task.Factory.StartNew (delegate { }, cancellation)
215 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
216 } catch (AggregateException e) {
217 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
222 public void WaitAllTest ()
224 ParallelTestHelper.Repeat (delegate {
226 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
228 Assert.AreEqual(max, achieved, "#1");
233 public void WaitAll_ManyTasks ()
235 for (int r = 0; r < 2000; ++r) {
236 var tasks = new Task[60];
238 for (int i = 0; i < tasks.Length; i++) {
239 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
242 Assert.IsTrue (Task.WaitAll (tasks, 2000));
247 public void WaitAll_Zero ()
249 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
250 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
254 public void WaitAll_WithExceptions ()
256 InitWithDelegate (delegate { throw new ApplicationException (); });
259 Task.WaitAll (tasks);
261 } catch (AggregateException e) {
262 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
265 Assert.IsNotNull (tasks[0].Exception, "#3");
269 public void WaitAll_TimeoutWithExceptionsAfter ()
271 CountdownEvent cde = new CountdownEvent (2);
272 var mre = new ManualResetEvent (false);
274 Task.Factory.StartNew (delegate { mre.WaitOne (); }),
275 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
276 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
279 Assert.IsTrue (cde.Wait (1000), "#1");
280 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
285 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
287 } catch (AggregateException e) {
288 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
293 public void WaitAll_TimeoutWithExceptionsBefore ()
295 CountdownEvent cde = new CountdownEvent (2);
296 var mre = new ManualResetEvent (false);
298 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
299 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
300 Task.Factory.StartNew (delegate { mre.WaitOne (); })
303 Assert.IsTrue (cde.Wait (1000), "#1");
304 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
309 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
311 } catch (AggregateException e) {
312 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
317 public void WaitAll_Cancelled ()
319 var cancelation = new CancellationTokenSource ();
320 var tasks = new Task[] {
321 new Task (delegate { cancelation.Cancel (); }),
322 new Task (delegate { }, cancelation.Token)
328 Task.WaitAll (tasks);
330 } catch (AggregateException e) {
331 var inner = (TaskCanceledException) e.InnerException;
332 Assert.AreEqual (tasks[1], inner.Task, "#2");
335 Assert.IsTrue (tasks[0].IsCompleted, "#3");
336 Assert.IsTrue (tasks[1].IsCanceled, "#4");
341 public void WaitAll_CancelledAndTimeout ()
343 var ct = new CancellationToken (true);
344 var t1 = new Task (() => {}, ct);
345 var t2 = Task.Delay (3000);
346 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
351 public void WaitAllExceptionThenCancelled ()
353 var cancelation = new CancellationTokenSource ();
354 var tasks = new Task[] {
355 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
356 new Task (delegate { }, cancelation.Token)
362 Task.WaitAll (tasks);
364 } catch (AggregateException e) {
365 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
366 var inner = (TaskCanceledException) e.InnerExceptions[1];
367 Assert.AreEqual (tasks[1], inner.Task, "#3");
370 Assert.IsTrue (tasks[0].IsCompleted, "#4");
371 Assert.IsTrue (tasks[1].IsCanceled, "#5");
375 public void WaitAll_StartedUnderWait ()
377 var task1 = new Task (delegate { });
379 ThreadPool.QueueUserWorkItem (delegate {
380 // Sleep little to let task to start and hit internal wait
385 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
389 public void CancelBeforeStart ()
391 var src = new CancellationTokenSource ();
393 Task t = new Task (delegate { }, src.Token);
395 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
400 } catch (InvalidOperationException) {
405 public void Wait_CancelledTask ()
407 var src = new CancellationTokenSource ();
409 Task t = new Task (delegate { }, src.Token);
415 } catch (AggregateException e) {
416 var details = (TaskCanceledException) e.InnerException;
417 Assert.AreEqual (t, details.Task, "#1e");
423 } catch (AggregateException e) {
424 var details = (TaskCanceledException) e.InnerException;
425 Assert.AreEqual (t, details.Task, "#2e");
426 Assert.IsNull (details.Task.Exception, "#2e2");
431 public void Wait_Inlined ()
433 bool? previouslyQueued = null;
435 var scheduler = new MockScheduler ();
436 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
437 previouslyQueued = b;
440 var tf = new TaskFactory (scheduler);
441 var t = tf.StartNew (() => { });
444 Assert.AreEqual (true, previouslyQueued);
447 [Test, ExpectedException (typeof (InvalidOperationException))]
448 public void CreationWhileInitiallyCanceled ()
450 var token = new CancellationToken (true);
451 var task = new Task (() => { }, token);
452 Assert.AreEqual (TaskStatus.Canceled, task.Status);
457 public void ContinueWithInvalidArguments ()
459 var task = new Task (() => { });
461 task.ContinueWith (null);
463 } catch (ArgumentException) {
467 task.ContinueWith (delegate { }, null);
469 } catch (ArgumentException) {
473 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
475 } catch (ArgumentException) {
479 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
481 } catch (ArgumentException) {
486 public void ContinueWithOnAnyTestCase()
488 ParallelTestHelper.Repeat (delegate {
491 Task t = Task.Factory.StartNew(delegate { });
492 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
493 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
494 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
495 Assert.IsNull(cont.Exception, "#1");
496 Assert.IsNotNull(cont, "#2");
497 Assert.IsTrue(result, "#3");
502 public void ContinueWithOnCompletedSuccessfullyTestCase()
504 ParallelTestHelper.Repeat (delegate {
507 Task t = Task.Factory.StartNew(delegate { });
508 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
509 Assert.IsTrue (t.Wait(1000), "#4");
510 Assert.IsTrue (cont.Wait(1000), "#5");
512 Assert.IsNull(cont.Exception, "#1");
513 Assert.IsNotNull(cont, "#2");
514 Assert.IsTrue(result, "#3");
519 public void ContinueWithOnAbortedTestCase()
522 bool taskResult = false;
524 CancellationTokenSource src = new CancellationTokenSource ();
525 Task t = new Task (delegate { taskResult = true; }, src.Token);
527 Task cont = t.ContinueWith (delegate { result = true; },
528 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
532 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
533 Assert.IsTrue (cont.IsCompleted, "#1b");
534 Assert.IsTrue (result, "#1c");
539 } catch (InvalidOperationException) {
542 Assert.IsTrue (cont.Wait (1000), "#3");
544 Assert.IsFalse (taskResult, "#4");
546 Assert.IsNull (cont.Exception, "#5");
547 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
551 public void ContinueWithOnFailedTestCase()
553 ParallelTestHelper.Repeat (delegate {
556 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
557 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
559 Assert.IsTrue (cont.Wait(1000), "#0");
560 Assert.IsNotNull (t.Exception, "#1");
561 Assert.IsNotNull (cont, "#2");
562 Assert.IsTrue (result, "#3");
567 public void ContinueWithWithStart ()
569 Task t = new Task<int> (() => 1);
570 t = t.ContinueWith (l => { });
574 } catch (InvalidOperationException) {
579 public void ContinueWithChildren ()
581 ParallelTestHelper.Repeat (delegate {
584 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
586 var mre = new ManualResetEvent (false);
587 t.ContinueWith (l => {
592 Assert.IsTrue (mre.WaitOne (1000), "#1");
593 Assert.IsTrue (result, "#2");
598 public void ContinueWithDifferentOptionsAreCanceledTest ()
600 var mre = new ManualResetEventSlim ();
601 var task = Task.Factory.StartNew (() => mre.Wait (200));
602 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
603 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
604 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
607 contSuccess.Wait (100);
609 Assert.IsTrue (contSuccess.IsCompleted);
610 Assert.IsTrue (contFailed.IsCompleted);
611 Assert.IsTrue (contCanceled.IsCompleted);
612 Assert.IsFalse (contSuccess.IsCanceled);
613 Assert.IsTrue (contFailed.IsCanceled);
614 Assert.IsTrue (contCanceled.IsCanceled);
618 public void MultipleTasks()
620 ParallelTestHelper.Repeat (delegate {
621 bool r1 = false, r2 = false, r3 = false;
623 Task t1 = Task.Factory.StartNew(delegate {
626 Task t2 = Task.Factory.StartNew(delegate {
629 Task t3 = Task.Factory.StartNew(delegate {
637 Assert.IsTrue(r1, "#1");
638 Assert.IsTrue(r2, "#2");
639 Assert.IsTrue(r3, "#3");
644 public void WaitChildTestCase()
646 ParallelTestHelper.Repeat (delegate {
647 bool r1 = false, r2 = false, r3 = false;
648 var mre = new ManualResetEventSlim (false);
649 var mreStart = new ManualResetEventSlim (false);
651 Task t = Task.Factory.StartNew(delegate {
652 Task.Factory.StartNew(delegate {
655 }, TaskCreationOptions.AttachedToParent);
656 Task.Factory.StartNew(delegate {
658 }, TaskCreationOptions.AttachedToParent);
659 Task.Factory.StartNew(delegate {
661 }, TaskCreationOptions.AttachedToParent);
666 Assert.IsFalse (t.Wait (10), "#0a");
668 Assert.IsTrue (t.Wait (500), "#0b");
669 Assert.IsTrue(r2, "#1");
670 Assert.IsTrue(r3, "#2");
671 Assert.IsTrue(r1, "#3");
672 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
679 public void WaitingForChildrenToComplete ()
683 parent_wfc = Task.Factory.StartNew (() => {
684 nested = Task.Factory.StartNew (() => {
685 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
686 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
687 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
688 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
689 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
690 }, TaskContinuationOptions.ExecuteSynchronously);
693 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
694 Assert.IsTrue (nested.Wait (2000), "#4");
698 public void WaitChildWithContinuationAttachedTest ()
701 var task = new Task(() =>
703 Task.Factory.StartNew(() => {
705 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
708 }, TaskContinuationOptions.AttachedToParent);
712 Assert.IsTrue (result);
716 public void WaitChildWithContinuationNotAttachedTest ()
718 var task = new Task(() =>
720 Task.Factory.StartNew(() => {
722 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
727 Assert.IsTrue (task.Wait(400));
731 public void WaitChildWithNesting ()
734 var t = Task.Factory.StartNew (() => {
735 Task.Factory.StartNew (() => {
736 Task.Factory.StartNew (() => {
739 }, TaskCreationOptions.AttachedToParent);
740 }, TaskCreationOptions.AttachedToParent);
743 Assert.IsTrue (result);
747 public void DoubleWaitTest ()
749 ParallelTestHelper.Repeat (delegate {
750 var evt = new ManualResetEventSlim ();
751 var t = Task.Factory.StartNew (() => evt.Wait (5000));
752 var cntd = new CountdownEvent (2);
753 var cntd2 = new CountdownEvent (2);
755 bool r1 = false, r2 = false;
756 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
757 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
759 Assert.IsTrue (cntd.Wait (2000), "#1");
761 Assert.IsTrue (cntd2.Wait (2000), "#2");
762 Assert.IsTrue (r1, "r1");
763 Assert.IsTrue (r2, "r2");
768 public void DoubleTimeoutedWaitTest ()
770 var evt = new ManualResetEventSlim ();
771 var t = new Task (delegate { });
772 var cntd = new CountdownEvent (2);
774 bool r1 = false, r2 = false;
775 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
776 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
784 public void RunSynchronously ()
787 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
788 t.RunSynchronously ();
790 Assert.AreEqual (1, val, "#1");
792 t = new Task (() => { Thread.Sleep (0); val = 2; });
794 bool? previouslyQueued = null;
796 var scheduler = new MockScheduler ();
797 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
798 previouslyQueued = b;
801 t.RunSynchronously (scheduler);
803 Assert.AreEqual (2, val, "#2");
804 Assert.AreEqual (false, previouslyQueued, "#2a");
808 public void RunSynchronouslyArgumentChecks ()
810 Task t = new Task (() => { });
812 t.RunSynchronously (null);
814 } catch (ArgumentNullException) {
819 public void RunSynchronouslyWithAttachedChildren ()
822 var t = new Task (() => {
823 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
825 t.RunSynchronously ();
826 Assert.IsTrue (result);
830 public void RunSynchronouslyOnContinuation ()
832 Task t = new Task<int> (() => 1);
833 t = t.ContinueWith (l => { });
835 t.RunSynchronously ();
837 } catch (InvalidOperationException) {
842 public void UnobservedExceptionOnFinalizerThreadTest ()
844 bool wasCalled = false;
845 TaskScheduler.UnobservedTaskException += (o, args) => {
849 var inner = new ApplicationException ();
850 Task.Factory.StartNew (() => { throw inner; });
854 GC.WaitForPendingFinalizers ();
856 Assert.IsTrue (wasCalled);
859 [Test, ExpectedException (typeof (InvalidOperationException))]
860 public void StartFinishedTaskTest ()
862 var t = Task.Factory.StartNew (delegate () { });
869 public void Start_NullArgument ()
871 var t = Task.Factory.StartNew (delegate () { });
875 } catch (ArgumentNullException) {
879 [Test, ExpectedException (typeof (InvalidOperationException))]
880 public void DisposeUnstartedTest ()
882 var t = new Task (() => { });
887 public void ThrowingUnrelatedCanceledExceptionTest ()
889 Task t = new Task (() => {
890 throw new TaskCanceledException ();
893 t.RunSynchronously ();
894 Assert.IsTrue (t.IsFaulted);
895 Assert.IsFalse (t.IsCanceled);
899 public void CanceledContinuationExecuteSynchronouslyTest ()
901 var source = new CancellationTokenSource();
902 var token = source.Token;
903 var evt = new ManualResetEventSlim ();
907 var task = Task.Factory.StartNew (() => evt.Wait (100));
908 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
915 } catch (Exception ex) {
919 Assert.IsTrue (task.IsCompleted);
920 Assert.IsTrue (cont.IsCanceled);
921 Assert.IsFalse (result);
922 Assert.IsTrue (thrown);
926 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
928 Task innerTask = null;
929 var testTask = new Task (() =>
931 innerTask = new Task (() =>
933 throw new InvalidOperationException ();
934 }, TaskCreationOptions.AttachedToParent);
935 innerTask.RunSynchronously ();
937 testTask.RunSynchronously ();
939 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
940 Assert.IsNotNull (innerTask);
941 Assert.IsTrue (innerTask.IsFaulted);
942 Assert.IsNotNull (testTask.Exception);
943 Assert.IsTrue (testTask.IsFaulted);
944 Assert.IsNotNull (innerTask.Exception);
948 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
950 var continuationRan = false;
951 var testTask = new Task (() =>
953 var task = new Task (() =>
955 throw new InvalidOperationException();
956 }, TaskCreationOptions.AttachedToParent);
957 task.RunSynchronously ();
959 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
960 testTask.RunSynchronously ();
961 onErrorTask.Wait (100);
962 Assert.IsTrue (continuationRan);
966 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
968 var continuationRan = false;
969 var testTask = new Task (() =>
971 var task = new Task (() =>
973 throw new InvalidOperationException();
974 }, TaskCreationOptions.AttachedToParent);
975 task.RunSynchronously();
977 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
978 testTask.RunSynchronously ();
979 Assert.IsTrue (onErrorTask.IsCompleted);
980 Assert.IsFalse (onErrorTask.IsFaulted);
981 Assert.IsFalse (continuationRan);
985 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
987 var continuationRan = false;
988 AggregateException e = null;
989 var testTask = new Task (() =>
991 var child1 = new Task (() =>
993 var child2 = new Task (() =>
995 throw new InvalidOperationException();
996 }, TaskCreationOptions.AttachedToParent);
997 child2.RunSynchronously ();
998 }, TaskCreationOptions.AttachedToParent);
1000 child1.RunSynchronously();
1001 e = child1.Exception;
1002 child1.Exception.Handle (ex => true);
1004 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1005 testTask.RunSynchronously ();
1006 onErrorTask.Wait (100);
1007 Assert.IsNotNull (e);
1008 Assert.IsTrue (continuationRan);
1012 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1014 string result = "Failed";
1015 var testTask = new Task (() =>
1017 var child = new Task<string> (() =>
1020 }, TaskCreationOptions.AttachedToParent);
1021 child.RunSynchronously ();
1022 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1024 testTask.RunSynchronously ();
1026 Assert.AreEqual ("Success", result);
1030 public void InlineNotTrashingParentRelationship ()
1032 bool r1 = false, r2 = false;
1033 var t = new Task (() => {
1034 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1035 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1037 t.RunSynchronously ();
1045 public void Delay_Invalid ()
1049 } catch (ArgumentOutOfRangeException) {
1054 public void Delay_Start ()
1056 var t = Task.Delay (5000);
1059 } catch (InvalidOperationException) {
1064 public void Delay_Simple ()
1066 var t = Task.Delay (300);
1067 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1068 Assert.IsTrue (t.Wait (400), "#2");
1072 public void Delay_Cancelled ()
1074 var cancelation = new CancellationTokenSource ();
1076 var t = Task.Delay (5000, cancelation.Token);
1077 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1078 cancelation.Cancel ();
1082 } catch (AggregateException) {
1083 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1086 cancelation = new CancellationTokenSource ();
1087 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1088 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1089 cancelation.Cancel ();
1092 Assert.Fail ("#12");
1093 } catch (AggregateException) {
1094 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1099 public void WaitAny_WithNull ()
1101 var tasks = new [] {
1102 Task.FromResult (2),
1107 Task.WaitAny (tasks);
1109 } catch (ArgumentException) {
1114 public void WhenAll_WithNull ()
1117 Task.FromResult (2),
1122 Task.WhenAll (tasks);
1124 } catch (ArgumentException) {
1129 Task.WhenAll (tasks);
1131 } catch (ArgumentException) {
1136 public void WhenAll_Start ()
1138 Task[] tasks = new[] {
1139 Task.FromResult (2),
1142 var t = Task.WhenAll (tasks);
1143 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1148 } catch (InvalidOperationException) {
1152 new Task (delegate { }),
1155 t = Task.WhenAll (tasks);
1156 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1160 Assert.Fail ("#12");
1161 } catch (InvalidOperationException) {
1166 public void WhenAll_Cancelled ()
1168 var cancelation = new CancellationTokenSource ();
1169 var tasks = new Task[] {
1170 new Task (delegate { }),
1171 new Task (delegate { }, cancelation.Token)
1174 cancelation.Cancel ();
1176 var t = Task.WhenAll (tasks);
1177 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1181 Assert.IsTrue (t.Wait (1000), "#2");
1182 Assert.Fail ("#2a");
1183 } catch (AggregateException e) {
1184 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1189 public void WhenAll_Faulted ()
1191 var tcs = new TaskCompletionSource<object> ();
1192 tcs.SetException (new ApplicationException ());
1194 var tcs2 = new TaskCompletionSource<object> ();
1195 tcs2.SetException (new InvalidTimeZoneException ());
1197 var cancelation = new CancellationTokenSource ();
1198 var tasks = new Task[] {
1199 new Task (delegate { }),
1200 new Task (delegate { }, cancelation.Token),
1205 cancelation.Cancel ();
1207 var t = Task.WhenAll (tasks);
1208 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1212 Assert.IsTrue (t.Wait (1000), "#2");
1213 Assert.Fail ("#2a");
1214 } catch (AggregateException e) {
1215 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1216 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1221 public void WhenAll ()
1223 var t1 = new Task (delegate { });
1224 var t2 = new Task (delegate { t1.Start (); });
1226 var tasks = new Task[] {
1231 var t = Task.WhenAll (tasks);
1232 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1235 Assert.IsTrue (t.Wait (1000), "#2");
1239 public void WhenAllResult_WithNull ()
1242 Task.FromResult (2),
1247 Task.WhenAll<int> (tasks);
1249 } catch (ArgumentException) {
1254 Task.WhenAll<int> (tasks);
1256 } catch (ArgumentException) {
1261 public void WhenAllResult_Cancelled ()
1263 var cancelation = new CancellationTokenSource ();
1264 var tasks = new [] {
1265 new Task<int> (delegate { return 9; }),
1266 new Task<int> (delegate { return 1; }, cancelation.Token)
1269 cancelation.Cancel ();
1271 var t = Task.WhenAll (tasks);
1272 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1276 Assert.IsTrue (t.Wait (1000), "#2");
1277 Assert.Fail ("#2a");
1278 } catch (AggregateException e) {
1279 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1285 } catch (AggregateException) {
1290 public void WhenAllResult ()
1292 var t1 = new Task<string> (delegate { return "a"; });
1293 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1295 var tasks = new [] {
1300 var t = Task.WhenAll<string> (tasks);
1301 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1304 Assert.IsTrue (t.Wait (1000), "#2");
1305 Assert.AreEqual (2, t.Result.Length, "#3");
1306 Assert.AreEqual ("a", t.Result[0], "#3a");
1307 Assert.AreEqual ("b", t.Result[1], "#3b");
1311 public void WhenAllResult_Completed ()
1314 Task.FromResult (1),
1318 var t = Task.WhenAll<int> (tasks);
1319 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1320 Assert.AreEqual (2, t.Result.Length, "#2");
1321 Assert.AreEqual (1, t.Result[0], "#2a");
1322 Assert.AreEqual (2, t.Result[1], "#2b");
1326 public void WhenAny_WithNull ()
1328 var tasks = new Task[] {
1329 Task.FromResult (2),
1334 Task.WhenAny (tasks);
1336 } catch (ArgumentException) {
1341 Task.WhenAny (tasks);
1343 } catch (ArgumentException) {
1347 Task.WhenAny (new Task[0]);
1349 } catch (ArgumentException) {
1354 public void WhenAny_Start ()
1356 Task[] tasks = new[] {
1357 Task.FromResult (2),
1360 var t = Task.WhenAny (tasks);
1361 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1366 } catch (InvalidOperationException) {
1370 new Task (delegate { }),
1373 t = Task.WhenAny (tasks);
1374 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1378 Assert.Fail ("#12");
1379 } catch (InvalidOperationException) {
1384 public void WhenAny_Cancelled ()
1386 var cancelation = new CancellationTokenSource ();
1387 var tasks = new Task[] {
1388 new Task (delegate { }),
1389 new Task (delegate { }, cancelation.Token)
1392 cancelation.Cancel ();
1394 var t = Task.WhenAny (tasks);
1395 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1398 Assert.IsTrue (t.Wait (1000), "#2");
1399 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1403 public void WhenAny_Faulted ()
1405 var tcs = new TaskCompletionSource<object> ();
1406 tcs.SetException (new ApplicationException ());
1408 var tcs2 = new TaskCompletionSource<object> ();
1409 tcs2.SetException (new InvalidTimeZoneException ());
1411 var cancelation = new CancellationTokenSource ();
1412 var tasks = new Task[] {
1413 new Task (delegate { }),
1415 new Task (delegate { }, cancelation.Token),
1419 cancelation.Cancel ();
1421 var t = Task.WhenAny (tasks);
1422 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1425 Assert.IsTrue (t.Wait (1000), "#2");
1426 Assert.IsNull (t.Exception, "#3");
1428 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1432 public void WhenAny ()
1434 var t1 = new Task (delegate { });
1435 var t2 = new Task (delegate { t1.Start (); });
1437 var tasks = new Task[] {
1442 var t = Task.WhenAny (tasks);
1443 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1446 Assert.IsTrue (t.Wait (1000), "#2");
1447 Assert.IsNotNull (t.Result, "#3");
1451 public void WhenAnyResult_WithNull ()
1453 var tasks = new [] {
1454 Task.FromResult (2),
1459 Task.WhenAny<int> (tasks);
1461 } catch (ArgumentException) {
1466 Task.WhenAny<int> (tasks);
1468 } catch (ArgumentException) {
1472 Task.WhenAny<short> (new Task<short>[0]);
1474 } catch (ArgumentException) {
1479 public void WhenAnyResult_Start ()
1482 Task.FromResult (2),
1485 var t = Task.WhenAny<int> (tasks);
1486 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1491 } catch (InvalidOperationException) {
1495 new Task<int> (delegate { return 55; }),
1498 t = Task.WhenAny<int> (tasks);
1499 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1503 Assert.Fail ("#12");
1504 } catch (InvalidOperationException) {
1509 public void WhenAnyResult_Cancelled ()
1511 var cancelation = new CancellationTokenSource ();
1512 var tasks = new [] {
1513 new Task<double> (delegate { return 1.1; }),
1514 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1517 cancelation.Cancel ();
1519 var t = Task.WhenAny<double> (tasks);
1520 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1523 Assert.IsTrue (t.Wait (1000), "#2");
1524 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1528 public void WhenAnyResult_Faulted ()
1530 var tcs = new TaskCompletionSource<object> ();
1531 tcs.SetException (new ApplicationException ());
1533 var tcs2 = new TaskCompletionSource<object> ();
1534 tcs2.SetException (new InvalidTimeZoneException ());
1536 var cancelation = new CancellationTokenSource ();
1537 var tasks = new Task<object>[] {
1538 new Task<object> (delegate { return null; }),
1540 new Task<object> (delegate { return ""; }, cancelation.Token),
1544 cancelation.Cancel ();
1546 var t = Task.WhenAny<object> (tasks);
1547 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1550 Assert.IsTrue (t.Wait (1000), "#2");
1551 Assert.IsNull (t.Exception, "#3");
1553 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1557 public void WhenAnyResult ()
1559 var t1 = new Task<byte> (delegate { return 3; });
1560 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1562 var tasks = new [] {
1567 var t = Task.WhenAny<byte> (tasks);
1568 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1571 Assert.IsTrue (t.Wait (1000), "#2");
1572 Assert.IsTrue (t.Result.Result > 1, "#3");
1576 public void ContinueWith_StateValue ()
1578 var t = Task.Factory.StartNew (l => {
1579 Assert.AreEqual (1, l, "a-1");
1582 var c = t.ContinueWith ((a, b) => {
1583 Assert.AreEqual (t, a, "c-1");
1584 Assert.AreEqual (2, b, "c-2");
1587 var d = t.ContinueWith ((a, b) => {
1588 Assert.AreEqual (t, a, "d-1");
1589 Assert.AreEqual (3, b, "d-2");
1593 Assert.IsTrue (d.Wait (1000), "#1");
1595 Assert.AreEqual (1, t.AsyncState, "#2");
1596 Assert.AreEqual (2, c.AsyncState, "#3");
1597 Assert.AreEqual (3, d.AsyncState, "#4");
1601 public void ContinueWith_StateValueGeneric ()
1603 var t = Task<int>.Factory.StartNew (l => {
1604 Assert.AreEqual (1, l, "a-1");
1608 var c = t.ContinueWith ((a, b) => {
1609 Assert.AreEqual (t, a, "c-1");
1610 Assert.AreEqual (2, b, "c-2");
1614 var d = t.ContinueWith ((a, b) => {
1615 Assert.AreEqual (t, a, "d-1");
1616 Assert.AreEqual (3, b, "d-2");
1620 Assert.IsTrue (d.Wait (1000), "#1");
1622 Assert.AreEqual (1, t.AsyncState, "#2");
1623 Assert.AreEqual (80, t.Result, "#2r");
1624 Assert.AreEqual (2, c.AsyncState, "#3");
1625 Assert.AreEqual ("c", c.Result, "#3r");
1626 Assert.AreEqual (3, d.AsyncState, "#4");
1627 Assert.AreEqual ('d', d.Result, "#3r");
1631 public void FromResult ()
1633 var t = Task.FromResult<object> (null);
1634 Assert.IsTrue (t.IsCompleted, "#1");
1635 Assert.AreEqual (null, t.Result, "#2");
1641 public void LongRunning ()
1645 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1647 Assert.IsTrue (t.Wait (100));
1648 Assert.IsTrue ((bool)is_tp, "#1");
1649 Assert.IsTrue ((bool)is_bg, "#2");
1653 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1656 Assert.IsTrue (t.Wait (100));
1657 Assert.IsFalse ((bool) is_tp, "#11");
1658 Assert.IsTrue ((bool) is_bg, "#12");
1662 public void Run_ArgumentCheck ()
1665 Task.Run (null as Action);
1667 } catch (ArgumentNullException) {
1674 bool ranOnDefaultScheduler = false;
1675 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1676 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1678 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1682 public void Run_Cancel ()
1684 var t = Task.Run (() => 1, new CancellationToken (true));
1688 } catch (AggregateException) {
1691 Assert.IsTrue (t.IsCanceled, "#2");
1695 public void Run_ExistingTaskT ()
1697 var t = new Task<int> (() => 5);
1698 var t2 = Task.Run (() => { t.Start (); return t; });
1700 Assert.IsTrue (t2.Wait (1000), "#1");
1701 Assert.AreEqual (5, t2.Result, "#2");
1705 public void Run_ExistingTask ()
1707 var t = new Task (delegate { throw new Exception ("Foo"); });
1708 var t2 = Task.Run (() => { t.Start (); return t; });
1713 } catch (Exception) {}
1715 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1719 public void DenyChildAttachTest ()
1721 var mre = new ManualResetEventSlim ();
1723 Task parent = Task.Factory.StartNew (() => {
1724 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1725 }, TaskCreationOptions.DenyChildAttach);
1726 Assert.IsTrue (parent.Wait (1000), "#1");
1728 Assert.IsTrue (nested.Wait (2000), "#2");
1731 class SynchronousScheduler : TaskScheduler
1733 protected override IEnumerable<Task> GetScheduledTasks ()
1735 throw new NotImplementedException ();
1738 protected override void QueueTask (Task task)
1740 TryExecuteTaskInline (task, false);
1743 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1745 return base.TryExecuteTask (task);
1750 public void HideSchedulerTest ()
1752 var mre = new ManualResetEventSlim ();
1753 var ranOnDefault = false;
1754 var scheduler = new SynchronousScheduler ();
1756 Task parent = Task.Factory.StartNew (() => {
1757 Task.Factory.StartNew (() => {
1758 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1761 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1763 Assert.IsTrue (mre.Wait (1000), "#1");
1764 Assert.IsTrue (ranOnDefault, "#2");
1768 public void LazyCancelationTest ()
1770 var source = new CancellationTokenSource ();
1772 var parent = new Task (delegate {});
1773 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1775 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1778 Assert.IsTrue (cont.Wait (1000), "#2");
1780 } catch (AggregateException ex) {
1781 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");