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);
70 class NonInlineableScheduler : TaskScheduler
72 protected override IEnumerable<Task> GetScheduledTasks ()
74 throw new NotImplementedException ();
77 protected override void QueueTask (Task task)
79 if (!base.TryExecuteTask (task))
80 throw new ApplicationException ();
83 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
96 tasks = new Task[max];
99 void InitWithDelegate(Action action)
101 for (int i = 0; i < max; i++) {
102 tasks[i] = Task.Factory.StartNew(action);
107 public void WaitAnyTest()
109 ParallelTestHelper.Repeat (delegate {
113 InitWithDelegate(delegate {
114 int times = Interlocked.Exchange (ref flag, 1);
116 SpinWait sw = new SpinWait ();
117 while (finished == 0) sw.SpinOnce ();
119 Interlocked.Increment (ref finished);
123 int index = Task.WaitAny(tasks, 1000);
125 Assert.AreNotEqual (-1, index, "#3");
126 Assert.AreEqual (1, flag, "#1");
127 Assert.AreEqual (1, finished, "#2");
132 public void WaitAny_Empty ()
134 Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
138 public void WaitAny_Zero ()
140 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
141 Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
145 public void WaitAny_Cancelled ()
147 var cancelation = new CancellationTokenSource ();
148 var tasks = new Task[] {
149 new Task (delegate { }),
150 new Task (delegate { }, cancelation.Token)
153 cancelation.Cancel ();
155 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
156 Assert.IsTrue (tasks[1].IsCompleted, "#2");
157 Assert.IsTrue (tasks[1].IsCanceled, "#3");
161 public void WaitAny_CancelledWithoutExecution ()
163 var cancelation = new CancellationTokenSource ();
164 var tasks = new Task[] {
165 new Task (delegate { }),
166 new Task (delegate { })
170 var mre = new ManualResetEventSlim (false);
171 ThreadPool.QueueUserWorkItem (delegate {
172 res = Task.WaitAny (tasks, 20);
176 cancelation.Cancel ();
177 Assert.IsTrue (mre.Wait (1000), "#1");
178 Assert.AreEqual (-1, res);
182 public void WaitAny_OneException ()
184 var mre = new ManualResetEventSlim (false);
185 var tasks = new Task[] {
186 Task.Factory.StartNew (delegate { mre.Wait (1000); }),
187 Task.Factory.StartNew (delegate { throw new ApplicationException (); })
190 Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
191 Assert.IsFalse (tasks[0].IsCompleted, "#2");
192 Assert.IsTrue (tasks[1].IsFaulted, "#3");
198 public void WaitAny_SingleCanceled ()
200 var src = new CancellationTokenSource ();
201 var t = Task.Factory.StartNew (() => { Thread.Sleep (200); src.Cancel (); src.Token.ThrowIfCancellationRequested (); }, src.Token);
202 Assert.AreEqual (0, Task.WaitAny (new [] { t }));
205 public void WaitAny_ManyExceptions ()
207 CountdownEvent cde = new CountdownEvent (3);
209 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
210 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
211 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
214 Assert.IsTrue (cde.Wait (1000), "#1");
217 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
218 } catch (AggregateException e) {
219 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
224 public void WaitAny_ManyCanceled ()
226 var cancellation = new CancellationToken (true);
228 Task.Factory.StartNew (delegate { }, cancellation),
229 Task.Factory.StartNew (delegate { }, cancellation),
230 Task.Factory.StartNew (delegate { }, cancellation)
234 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
235 } catch (AggregateException e) {
236 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
241 public void WaitAllTest ()
243 ParallelTestHelper.Repeat (delegate {
245 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
247 Assert.AreEqual(max, achieved, "#1");
252 public void WaitAll_ManyTasks ()
254 for (int r = 0; r < 2000; ++r) {
255 var tasks = new Task[60];
257 for (int i = 0; i < tasks.Length; i++) {
258 tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
261 Assert.IsTrue (Task.WaitAll (tasks, 2000));
266 public void WaitAll_Zero ()
268 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 0), "#0");
269 Assert.IsFalse (Task.WaitAll (new Task[1] { new Task (delegate { }) }, 10), "#1");
273 public void WaitAll_WithExceptions ()
275 InitWithDelegate (delegate { throw new ApplicationException (); });
278 Task.WaitAll (tasks);
280 } catch (AggregateException e) {
281 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
284 Assert.IsNotNull (tasks[0].Exception, "#3");
288 public void WaitAll_TimeoutWithExceptionsAfter ()
290 CountdownEvent cde = new CountdownEvent (2);
291 var mre = new ManualResetEvent (false);
293 Task.Factory.StartNew (delegate { mre.WaitOne (); }),
294 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
295 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
298 Assert.IsTrue (cde.Wait (1000), "#1");
299 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
304 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
306 } catch (AggregateException e) {
307 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
312 public void WaitAll_TimeoutWithExceptionsBefore ()
314 CountdownEvent cde = new CountdownEvent (2);
315 var mre = new ManualResetEvent (false);
317 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
318 Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
319 Task.Factory.StartNew (delegate { mre.WaitOne (); })
322 Assert.IsTrue (cde.Wait (1000), "#1");
323 Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
328 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
330 } catch (AggregateException e) {
331 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
336 public void WaitAll_Cancelled ()
338 var cancelation = new CancellationTokenSource ();
339 var tasks = new Task[] {
340 new Task (delegate { cancelation.Cancel (); }),
341 new Task (delegate { }, cancelation.Token)
347 Task.WaitAll (tasks);
349 } catch (AggregateException e) {
350 var inner = (TaskCanceledException) e.InnerException;
351 Assert.AreEqual (tasks[1], inner.Task, "#2");
354 Assert.IsTrue (tasks[0].IsCompleted, "#3");
355 Assert.IsTrue (tasks[1].IsCanceled, "#4");
360 public void WaitAll_CancelledAndTimeout ()
362 var ct = new CancellationToken (true);
363 var t1 = new Task (() => {}, ct);
364 var t2 = Task.Delay (3000);
365 Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
370 public void WaitAllExceptionThenCancelled ()
372 var cancelation = new CancellationTokenSource ();
373 var tasks = new Task[] {
374 new Task (delegate { cancelation.Cancel (); throw new ApplicationException (); }),
375 new Task (delegate { }, cancelation.Token)
381 Task.WaitAll (tasks);
383 } catch (AggregateException e) {
384 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
385 var inner = (TaskCanceledException) e.InnerExceptions[1];
386 Assert.AreEqual (tasks[1], inner.Task, "#3");
389 Assert.IsTrue (tasks[0].IsCompleted, "#4");
390 Assert.IsTrue (tasks[1].IsCanceled, "#5");
394 public void WaitAll_StartedUnderWait ()
396 var task1 = new Task (delegate { });
398 ThreadPool.QueueUserWorkItem (delegate {
399 // Sleep little to let task to start and hit internal wait
404 Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
408 public void CancelBeforeStart ()
410 var src = new CancellationTokenSource ();
412 Task t = new Task (delegate { }, src.Token);
414 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
419 } catch (InvalidOperationException) {
424 public void Wait_CancelledTask ()
426 var src = new CancellationTokenSource ();
428 Task t = new Task (delegate { }, src.Token);
434 } catch (AggregateException e) {
435 var details = (TaskCanceledException) e.InnerException;
436 Assert.AreEqual (t, details.Task, "#1e");
442 } catch (AggregateException e) {
443 var details = (TaskCanceledException) e.InnerException;
444 Assert.AreEqual (t, details.Task, "#2e");
445 Assert.IsNull (details.Task.Exception, "#2e2");
450 public void Wait_Inlined ()
452 bool? previouslyQueued = null;
454 var scheduler = new MockScheduler ();
455 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
456 previouslyQueued = b;
459 var tf = new TaskFactory (scheduler);
460 var t = tf.StartNew (() => { });
463 Assert.AreEqual (true, previouslyQueued);
466 [Test, ExpectedException (typeof (InvalidOperationException))]
467 public void CreationWhileInitiallyCanceled ()
469 var token = new CancellationToken (true);
470 var task = new Task (() => { }, token);
471 Assert.AreEqual (TaskStatus.Canceled, task.Status);
476 public void ContinueWithInvalidArguments ()
478 var task = new Task (() => { });
480 task.ContinueWith (null);
482 } catch (ArgumentException) {
486 task.ContinueWith (delegate { }, null);
488 } catch (ArgumentException) {
492 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
494 } catch (ArgumentException) {
498 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
500 } catch (ArgumentException) {
505 public void ContinueWithOnAnyTestCase()
507 ParallelTestHelper.Repeat (delegate {
510 Task t = Task.Factory.StartNew(delegate { });
511 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
512 Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
513 Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
514 Assert.IsNull(cont.Exception, "#1");
515 Assert.IsNotNull(cont, "#2");
516 Assert.IsTrue(result, "#3");
521 public void ContinueWithOnCompletedSuccessfullyTestCase()
523 ParallelTestHelper.Repeat (delegate {
526 Task t = Task.Factory.StartNew(delegate { });
527 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
528 Assert.IsTrue (t.Wait(1000), "#4");
529 Assert.IsTrue (cont.Wait(1000), "#5");
531 Assert.IsNull(cont.Exception, "#1");
532 Assert.IsNotNull(cont, "#2");
533 Assert.IsTrue(result, "#3");
538 public void ContinueWithOnAbortedTestCase()
541 bool taskResult = false;
543 CancellationTokenSource src = new CancellationTokenSource ();
544 Task t = new Task (delegate { taskResult = true; }, src.Token);
546 Task cont = t.ContinueWith (delegate { result = true; },
547 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
551 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
552 Assert.IsTrue (cont.IsCompleted, "#1b");
553 Assert.IsTrue (result, "#1c");
558 } catch (InvalidOperationException) {
561 Assert.IsTrue (cont.Wait (1000), "#3");
563 Assert.IsFalse (taskResult, "#4");
565 Assert.IsNull (cont.Exception, "#5");
566 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
570 public void ContinueWithOnFailedTestCase()
572 ParallelTestHelper.Repeat (delegate {
575 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
576 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
578 Assert.IsTrue (cont.Wait(1000), "#0");
579 Assert.IsNotNull (t.Exception, "#1");
580 Assert.IsNotNull (cont, "#2");
581 Assert.IsTrue (result, "#3");
586 public void ContinueWithWithStart ()
588 Task t = new Task<int> (() => 1);
589 t = t.ContinueWith (l => { });
593 } catch (InvalidOperationException) {
598 public void ContinueWithChildren ()
600 ParallelTestHelper.Repeat (delegate {
603 var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
605 var mre = new ManualResetEvent (false);
606 t.ContinueWith (l => {
611 Assert.IsTrue (mre.WaitOne (1000), "#1");
612 Assert.IsTrue (result, "#2");
617 public void ContinueWithDifferentOptionsAreCanceledTest ()
619 var mre = new ManualResetEventSlim ();
620 var task = Task.Factory.StartNew (() => mre.Wait (200));
621 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
622 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
623 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
626 contSuccess.Wait (100);
628 Assert.IsTrue (contSuccess.IsCompleted);
629 Assert.IsTrue (contFailed.IsCompleted);
630 Assert.IsTrue (contCanceled.IsCompleted);
631 Assert.IsFalse (contSuccess.IsCanceled);
632 Assert.IsTrue (contFailed.IsCanceled);
633 Assert.IsTrue (contCanceled.IsCanceled);
637 public void MultipleTasks()
639 ParallelTestHelper.Repeat (delegate {
640 bool r1 = false, r2 = false, r3 = false;
642 Task t1 = Task.Factory.StartNew(delegate {
645 Task t2 = Task.Factory.StartNew(delegate {
648 Task t3 = Task.Factory.StartNew(delegate {
656 Assert.IsTrue(r1, "#1");
657 Assert.IsTrue(r2, "#2");
658 Assert.IsTrue(r3, "#3");
663 public void WaitChildTestCase()
665 ParallelTestHelper.Repeat (delegate {
666 bool r1 = false, r2 = false, r3 = false;
667 var mre = new ManualResetEventSlim (false);
668 var mreStart = new ManualResetEventSlim (false);
670 Task t = Task.Factory.StartNew(delegate {
671 Task.Factory.StartNew(delegate {
674 }, TaskCreationOptions.AttachedToParent);
675 Task.Factory.StartNew(delegate {
677 }, TaskCreationOptions.AttachedToParent);
678 Task.Factory.StartNew(delegate {
680 }, TaskCreationOptions.AttachedToParent);
685 Assert.IsFalse (t.Wait (10), "#0a");
687 Assert.IsTrue (t.Wait (500), "#0b");
688 Assert.IsTrue(r2, "#1");
689 Assert.IsTrue(r3, "#2");
690 Assert.IsTrue(r1, "#3");
691 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
698 public void WaitingForChildrenToComplete ()
701 var mre = new ManualResetEvent (false);
703 parent_wfc = Task.Factory.StartNew (() => {
704 nested = Task.Factory.StartNew (() => {
705 Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
706 Assert.IsFalse (parent_wfc.Wait (10), "#1a");
707 Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
708 }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
709 Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
710 Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
711 }, TaskContinuationOptions.ExecuteSynchronously);
715 Assert.IsTrue (parent_wfc.Wait (2000), "#3");
716 Assert.IsTrue (nested.Wait (2000), "#4");
720 public void WaitChildWithContinuationAttachedTest ()
723 var task = new Task(() =>
725 Task.Factory.StartNew(() => {
727 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
730 }, TaskContinuationOptions.AttachedToParent);
734 Assert.IsTrue (result);
738 public void WaitChildWithContinuationNotAttachedTest ()
740 var task = new Task(() =>
742 Task.Factory.StartNew(() => {
744 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
749 Assert.IsTrue (task.Wait(400));
753 public void WaitChildWithNesting ()
756 var t = Task.Factory.StartNew (() => {
757 Task.Factory.StartNew (() => {
758 Task.Factory.StartNew (() => {
761 }, TaskCreationOptions.AttachedToParent);
762 }, TaskCreationOptions.AttachedToParent);
765 Assert.IsTrue (result);
769 public void DoubleWaitTest ()
771 ParallelTestHelper.Repeat (delegate {
772 var evt = new ManualResetEventSlim ();
773 var t = Task.Factory.StartNew (() => evt.Wait (5000));
774 var cntd = new CountdownEvent (2);
775 var cntd2 = new CountdownEvent (2);
777 bool r1 = false, r2 = false;
778 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
779 ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
781 Assert.IsTrue (cntd.Wait (2000), "#1");
783 Assert.IsTrue (cntd2.Wait (2000), "#2");
784 Assert.IsTrue (r1, "r1");
785 Assert.IsTrue (r2, "r2");
790 public void DoubleTimeoutedWaitTest ()
792 var evt = new ManualResetEventSlim ();
793 var t = new Task (delegate { });
794 var cntd = new CountdownEvent (2);
796 bool r1 = false, r2 = false;
797 ThreadPool.QueueUserWorkItem (delegate { r1 = !t.Wait (100); cntd.Signal (); });
798 ThreadPool.QueueUserWorkItem (delegate { r2 = !t.Wait (100); cntd.Signal (); });
806 public void RunSynchronously ()
809 Task t = new Task (() => { Thread.Sleep (100); val = 1; });
810 t.RunSynchronously ();
812 Assert.AreEqual (1, val, "#1");
814 t = new Task (() => { Thread.Sleep (0); val = 2; });
816 bool? previouslyQueued = null;
818 var scheduler = new MockScheduler ();
819 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
820 previouslyQueued = b;
823 t.RunSynchronously (scheduler);
825 Assert.AreEqual (2, val, "#2");
826 Assert.AreEqual (false, previouslyQueued, "#2a");
830 public void RunSynchronouslyArgumentChecks ()
832 Task t = new Task (() => { });
834 t.RunSynchronously (null);
836 } catch (ArgumentNullException) {
841 public void RunSynchronously_SchedulerException ()
843 var scheduler = new MockScheduler ();
844 scheduler.TryExecuteTaskInlineHandler += (task, b) => {
845 throw new ApplicationException ();
848 Task t = new Task (() => { });
850 t.RunSynchronously (scheduler);
852 } catch (Exception e) {
853 Assert.AreEqual (t.Exception.InnerException, e);
858 public void RunSynchronouslyWithAttachedChildren ()
861 var t = new Task (() => {
862 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
864 t.RunSynchronously ();
865 Assert.IsTrue (result);
869 public void RunSynchronouslyOnContinuation ()
871 Task t = new Task<int> (() => 1);
872 t = t.ContinueWith (l => { });
874 t.RunSynchronously ();
876 } catch (InvalidOperationException) {
881 public void UnobservedExceptionOnFinalizerThreadTest ()
883 bool wasCalled = false;
884 TaskScheduler.UnobservedTaskException += (o, args) => {
888 var inner = new ApplicationException ();
889 Task.Factory.StartNew (() => { throw inner; });
893 GC.WaitForPendingFinalizers ();
895 Assert.IsTrue (wasCalled);
898 [Test, ExpectedException (typeof (InvalidOperationException))]
899 public void StartFinishedTaskTest ()
901 var t = Task.Factory.StartNew (delegate () { });
908 public void Start_NullArgument ()
910 var t = Task.Factory.StartNew (delegate () { });
914 } catch (ArgumentNullException) {
918 [Test, ExpectedException (typeof (InvalidOperationException))]
919 public void DisposeUnstartedTest ()
921 var t = new Task (() => { });
926 public void ThrowingUnrelatedCanceledExceptionTest ()
928 Task t = new Task (() => {
929 throw new TaskCanceledException ();
932 t.RunSynchronously ();
933 Assert.IsTrue (t.IsFaulted);
934 Assert.IsFalse (t.IsCanceled);
938 public void CanceledContinuationExecuteSynchronouslyTest ()
940 var source = new CancellationTokenSource();
941 var token = source.Token;
942 var evt = new ManualResetEventSlim ();
946 var task = Task.Factory.StartNew (() => evt.Wait (100));
947 var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
954 } catch (Exception ex) {
958 Assert.IsTrue (task.IsCompleted);
959 Assert.IsTrue (cont.IsCanceled);
960 Assert.IsFalse (result);
961 Assert.IsTrue (thrown);
965 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
967 Task innerTask = null;
968 var testTask = new Task (() =>
970 innerTask = new Task (() =>
972 throw new InvalidOperationException ();
973 }, TaskCreationOptions.AttachedToParent);
974 innerTask.RunSynchronously ();
976 testTask.RunSynchronously ();
978 Assert.AreNotEqual (TaskStatus.Running, testTask.Status);
979 Assert.IsNotNull (innerTask);
980 Assert.IsTrue (innerTask.IsFaulted);
981 Assert.IsNotNull (testTask.Exception);
982 Assert.IsTrue (testTask.IsFaulted);
983 Assert.IsNotNull (innerTask.Exception);
987 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
989 var continuationRan = false;
990 var testTask = new Task (() =>
992 var task = new Task (() =>
994 throw new InvalidOperationException();
995 }, TaskCreationOptions.AttachedToParent);
996 task.RunSynchronously ();
998 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
999 testTask.RunSynchronously ();
1000 onErrorTask.Wait (100);
1001 Assert.IsTrue (continuationRan);
1005 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1007 var continuationRan = false;
1008 var testTask = new Task (() =>
1010 var task = new Task (() =>
1012 throw new InvalidOperationException();
1013 }, TaskCreationOptions.AttachedToParent);
1014 task.RunSynchronously();
1016 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.NotOnFaulted);
1017 testTask.RunSynchronously ();
1018 Assert.IsTrue (onErrorTask.IsCompleted);
1019 Assert.IsFalse (onErrorTask.IsFaulted);
1020 Assert.IsFalse (continuationRan);
1024 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1026 var continuationRan = false;
1027 AggregateException e = null;
1028 var testTask = new Task (() =>
1030 var child1 = new Task (() =>
1032 var child2 = new Task (() =>
1034 throw new InvalidOperationException();
1035 }, TaskCreationOptions.AttachedToParent);
1036 child2.RunSynchronously ();
1037 }, TaskCreationOptions.AttachedToParent);
1039 child1.RunSynchronously();
1040 e = child1.Exception;
1041 child1.Exception.Handle (ex => true);
1043 var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
1044 testTask.RunSynchronously ();
1045 onErrorTask.Wait (100);
1046 Assert.IsNotNull (e);
1047 Assert.IsTrue (continuationRan);
1051 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1053 string result = "Failed";
1054 var testTask = new Task (() =>
1056 var child = new Task<string> (() =>
1059 }, TaskCreationOptions.AttachedToParent);
1060 child.RunSynchronously ();
1061 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1063 testTask.RunSynchronously ();
1065 Assert.AreEqual ("Success", result);
1069 public void InlineNotTrashingParentRelationship ()
1071 bool r1 = false, r2 = false;
1072 var t = new Task (() => {
1073 new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
1074 Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
1076 t.RunSynchronously ();
1083 public void AsyncWaitHandleSet ()
1085 var task = new TaskFactory ().StartNew (() => { });
1086 var ar = (IAsyncResult)task;
1087 ar.AsyncWaitHandle.WaitOne ();
1092 public void Delay_Invalid ()
1096 } catch (ArgumentOutOfRangeException) {
1101 public void Delay_Start ()
1103 var t = Task.Delay (5000);
1106 } catch (InvalidOperationException) {
1111 public void Delay_Simple ()
1113 var t = Task.Delay (300);
1114 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1115 Assert.IsTrue (t.Wait (400), "#2");
1119 public void Delay_Cancelled ()
1121 var cancelation = new CancellationTokenSource ();
1123 var t = Task.Delay (5000, cancelation.Token);
1124 Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1125 cancelation.Cancel ();
1129 } catch (AggregateException) {
1130 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1133 cancelation = new CancellationTokenSource ();
1134 t = Task.Delay (Timeout.Infinite, cancelation.Token);
1135 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1136 cancelation.Cancel ();
1139 Assert.Fail ("#12");
1140 } catch (AggregateException) {
1141 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1146 public void Delay_TimeManagement ()
1148 var delay1 = Task.Delay(50);
1149 var delay2 = Task.Delay(25);
1150 Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
1151 Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
1155 public void WaitAny_WithNull ()
1157 var tasks = new [] {
1158 Task.FromResult (2),
1163 Task.WaitAny (tasks);
1165 } catch (ArgumentException) {
1170 public void WhenAll_Empty ()
1172 var tasks = new Task[0];
1174 Task t = Task.WhenAll(tasks);
1176 Assert.IsTrue(t.Wait(1000), "#1");
1180 public void WhenAll_WithNull ()
1183 Task.FromResult (2),
1188 Task.WhenAll (tasks);
1190 } catch (ArgumentException) {
1195 Task.WhenAll (tasks);
1197 } catch (ArgumentException) {
1202 public void WhenAll_Start ()
1204 Task[] tasks = new[] {
1205 Task.FromResult (2),
1208 var t = Task.WhenAll (tasks);
1209 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1214 } catch (InvalidOperationException) {
1218 new Task (delegate { }),
1221 t = Task.WhenAll (tasks);
1222 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1226 Assert.Fail ("#12");
1227 } catch (InvalidOperationException) {
1232 public void WhenAll_Cancelled ()
1234 var cancelation = new CancellationTokenSource ();
1235 var tasks = new Task[] {
1236 new Task (delegate { }),
1237 new Task (delegate { }, cancelation.Token)
1240 cancelation.Cancel ();
1242 var t = Task.WhenAll (tasks);
1243 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1247 Assert.IsTrue (t.Wait (1000), "#2");
1248 Assert.Fail ("#2a");
1249 } catch (AggregateException e) {
1250 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1255 public void WhenAll_Faulted ()
1257 var tcs = new TaskCompletionSource<object> ();
1258 tcs.SetException (new ApplicationException ());
1260 var tcs2 = new TaskCompletionSource<object> ();
1261 tcs2.SetException (new InvalidTimeZoneException ());
1263 var cancelation = new CancellationTokenSource ();
1264 var tasks = new Task[] {
1265 new Task (delegate { }),
1266 new Task (delegate { }, cancelation.Token),
1271 cancelation.Cancel ();
1273 var t = Task.WhenAll (tasks);
1274 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1278 Assert.IsTrue (t.Wait (1000), "#2");
1279 Assert.Fail ("#2a");
1280 } catch (AggregateException e) {
1281 Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
1282 Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
1287 public void WhenAll ()
1289 var t1 = new Task (delegate { });
1290 var t2 = new Task (delegate { t1.Start (); });
1292 var tasks = new Task[] {
1297 var t = Task.WhenAll (tasks);
1298 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1301 Assert.IsTrue (t.Wait (1000), "#2");
1305 public void WhenAllResult_Empty ()
1307 var tasks = new Task<int>[0];
1309 Task<int[]> t = Task.WhenAll(tasks);
1311 Assert.IsTrue(t.Wait(1000), "#1");
1312 Assert.IsNotNull(t.Result, "#2");
1313 Assert.AreEqual(t.Result.Length, 0, "#3");
1317 public void WhenAllResult_WithNull ()
1320 Task.FromResult (2),
1325 Task.WhenAll<int> (tasks);
1327 } catch (ArgumentException) {
1332 Task.WhenAll<int> (tasks);
1334 } catch (ArgumentException) {
1339 public void WhenAllResult_Cancelled ()
1341 var cancelation = new CancellationTokenSource ();
1342 var tasks = new [] {
1343 new Task<int> (delegate { return 9; }),
1344 new Task<int> (delegate { return 1; }, cancelation.Token)
1347 cancelation.Cancel ();
1349 var t = Task.WhenAll (tasks);
1350 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1354 Assert.IsTrue (t.Wait (1000), "#2");
1355 Assert.Fail ("#2a");
1356 } catch (AggregateException e) {
1357 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1363 } catch (AggregateException) {
1368 public void WhenAllResult ()
1370 var t1 = new Task<string> (delegate { return "a"; });
1371 var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1373 var tasks = new [] {
1378 var t = Task.WhenAll<string> (tasks);
1379 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1382 Assert.IsTrue (t.Wait (1000), "#2");
1383 Assert.AreEqual (2, t.Result.Length, "#3");
1384 Assert.AreEqual ("a", t.Result[0], "#3a");
1385 Assert.AreEqual ("b", t.Result[1], "#3b");
1389 public void WhenAllResult_Completed ()
1392 Task.FromResult (1),
1396 var t = Task.WhenAll<int> (tasks);
1397 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1398 Assert.AreEqual (2, t.Result.Length, "#2");
1399 Assert.AreEqual (1, t.Result[0], "#2a");
1400 Assert.AreEqual (2, t.Result[1], "#2b");
1404 public void WhenAny_WithNull ()
1406 var tasks = new Task[] {
1407 Task.FromResult (2),
1412 Task.WhenAny (tasks);
1414 } catch (ArgumentException) {
1419 Task.WhenAny (tasks);
1421 } catch (ArgumentException) {
1425 Task.WhenAny (new Task[0]);
1427 } catch (ArgumentException) {
1432 public void WhenAny_Start ()
1434 Task[] tasks = new[] {
1435 Task.FromResult (2),
1438 var t = Task.WhenAny (tasks);
1439 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1444 } catch (InvalidOperationException) {
1448 new Task (delegate { }),
1451 t = Task.WhenAny (tasks);
1452 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1456 Assert.Fail ("#12");
1457 } catch (InvalidOperationException) {
1462 public void WhenAny_Cancelled ()
1464 var cancelation = new CancellationTokenSource ();
1465 var tasks = new Task[] {
1466 new Task (delegate { }),
1467 new Task (delegate { }, cancelation.Token)
1470 cancelation.Cancel ();
1472 var t = Task.WhenAny (tasks);
1473 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1476 Assert.IsTrue (t.Wait (1000), "#2");
1477 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1481 public void WhenAny_Faulted ()
1483 var tcs = new TaskCompletionSource<object> ();
1484 tcs.SetException (new ApplicationException ());
1486 var tcs2 = new TaskCompletionSource<object> ();
1487 tcs2.SetException (new InvalidTimeZoneException ());
1489 var cancelation = new CancellationTokenSource ();
1490 var tasks = new Task[] {
1491 new Task (delegate { }),
1493 new Task (delegate { }, cancelation.Token),
1497 cancelation.Cancel ();
1499 var t = Task.WhenAny (tasks);
1500 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1503 Assert.IsTrue (t.Wait (1000), "#2");
1504 Assert.IsNull (t.Exception, "#3");
1506 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1510 public void WhenAny ()
1512 var t1 = new Task (delegate { });
1513 var t2 = new Task (delegate { t1.Start (); });
1515 var tasks = new Task[] {
1520 var t = Task.WhenAny (tasks);
1521 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1524 Assert.IsTrue (t.Wait (1000), "#2");
1525 Assert.IsNotNull (t.Result, "#3");
1529 public void WhenAnyResult_WithNull ()
1531 var tasks = new [] {
1532 Task.FromResult (2),
1537 Task.WhenAny<int> (tasks);
1539 } catch (ArgumentException) {
1544 Task.WhenAny<int> (tasks);
1546 } catch (ArgumentException) {
1550 Task.WhenAny<short> (new Task<short>[0]);
1552 } catch (ArgumentException) {
1557 public void WhenAnyResult_Start ()
1560 Task.FromResult (2),
1563 var t = Task.WhenAny<int> (tasks);
1564 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1569 } catch (InvalidOperationException) {
1573 new Task<int> (delegate { return 55; }),
1576 t = Task.WhenAny<int> (tasks);
1577 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1581 Assert.Fail ("#12");
1582 } catch (InvalidOperationException) {
1587 public void WhenAnyResult_Cancelled ()
1589 var cancelation = new CancellationTokenSource ();
1590 var tasks = new [] {
1591 new Task<double> (delegate { return 1.1; }),
1592 new Task<double> (delegate { return -4.4; }, cancelation.Token)
1595 cancelation.Cancel ();
1597 var t = Task.WhenAny<double> (tasks);
1598 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1601 Assert.IsTrue (t.Wait (1000), "#2");
1602 Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1606 public void WhenAnyResult_Faulted ()
1608 var tcs = new TaskCompletionSource<object> ();
1609 tcs.SetException (new ApplicationException ());
1611 var tcs2 = new TaskCompletionSource<object> ();
1612 tcs2.SetException (new InvalidTimeZoneException ());
1614 var cancelation = new CancellationTokenSource ();
1615 var tasks = new Task<object>[] {
1616 new Task<object> (delegate { return null; }),
1618 new Task<object> (delegate { return ""; }, cancelation.Token),
1622 cancelation.Cancel ();
1624 var t = Task.WhenAny<object> (tasks);
1625 Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1628 Assert.IsTrue (t.Wait (1000), "#2");
1629 Assert.IsNull (t.Exception, "#3");
1631 Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1635 public void WhenAnyResult ()
1637 var t1 = new Task<byte> (delegate { return 3; });
1638 var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1640 var tasks = new [] {
1645 var t = Task.WhenAny<byte> (tasks);
1646 Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1649 Assert.IsTrue (t.Wait (1000), "#2");
1650 Assert.IsTrue (t.Result.Result > 1, "#3");
1654 public void ContinueWith_StateValue ()
1656 var t = Task.Factory.StartNew (l => {
1657 Assert.AreEqual (1, l, "a-1");
1660 var c = t.ContinueWith ((a, b) => {
1661 Assert.AreEqual (t, a, "c-1");
1662 Assert.AreEqual (2, b, "c-2");
1665 var d = t.ContinueWith ((a, b) => {
1666 Assert.AreEqual (t, a, "d-1");
1667 Assert.AreEqual (3, b, "d-2");
1671 Assert.IsTrue (d.Wait (1000), "#1");
1673 Assert.AreEqual (1, t.AsyncState, "#2");
1674 Assert.AreEqual (2, c.AsyncState, "#3");
1675 Assert.AreEqual (3, d.AsyncState, "#4");
1679 public void ContinueWith_StateValueGeneric ()
1681 var t = Task<int>.Factory.StartNew (l => {
1682 Assert.AreEqual (1, l, "a-1");
1686 var c = t.ContinueWith ((a, b) => {
1687 Assert.AreEqual (t, a, "c-1");
1688 Assert.AreEqual (2, b, "c-2");
1692 var d = t.ContinueWith ((a, b) => {
1693 Assert.AreEqual (t, a, "d-1");
1694 Assert.AreEqual (3, b, "d-2");
1698 Assert.IsTrue (d.Wait (1000), "#1");
1700 Assert.AreEqual (1, t.AsyncState, "#2");
1701 Assert.AreEqual (80, t.Result, "#2r");
1702 Assert.AreEqual (2, c.AsyncState, "#3");
1703 Assert.AreEqual ("c", c.Result, "#3r");
1704 Assert.AreEqual (3, d.AsyncState, "#4");
1705 Assert.AreEqual ('d', d.Result, "#3r");
1709 public void ContinueWith_CustomScheduleRejected ()
1711 var scheduler = new NonInlineableScheduler ();
1712 var t = Task.Factory.StartNew (delegate { }).
1713 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1715 Assert.IsTrue (t.Wait (5000));
1719 public void FromResult ()
1721 var t = Task.FromResult<object> (null);
1722 Assert.IsTrue (t.IsCompleted, "#1");
1723 Assert.AreEqual (null, t.Result, "#2");
1729 public void LongRunning ()
1733 var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1735 Assert.IsTrue (t.Wait (100));
1736 Assert.IsTrue ((bool)is_tp, "#1");
1737 Assert.IsTrue ((bool)is_bg, "#2");
1741 t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1744 Assert.IsTrue (t.Wait (100));
1745 Assert.IsFalse ((bool) is_tp, "#11");
1746 Assert.IsTrue ((bool) is_bg, "#12");
1750 public void Run_ArgumentCheck ()
1753 Task.Run (null as Action);
1755 } catch (ArgumentNullException) {
1762 bool ranOnDefaultScheduler = false;
1763 var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1764 Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1766 Assert.IsTrue (ranOnDefaultScheduler, "#2");
1770 public void Run_Cancel ()
1772 var t = Task.Run (() => 1, new CancellationToken (true));
1776 } catch (AggregateException) {
1779 Assert.IsTrue (t.IsCanceled, "#2");
1783 public void Run_ExistingTaskT ()
1785 var t = new Task<int> (() => 5);
1786 var t2 = Task.Run (() => { t.Start (); return t; });
1788 Assert.IsTrue (t2.Wait (1000), "#1");
1789 Assert.AreEqual (5, t2.Result, "#2");
1793 public void Run_ExistingTask ()
1795 var t = new Task (delegate { throw new Exception ("Foo"); });
1796 var t2 = Task.Run (() => { t.Start (); return t; });
1801 } catch (Exception) {}
1803 Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1807 public void DenyChildAttachTest ()
1809 var mre = new ManualResetEventSlim ();
1811 Task parent = Task.Factory.StartNew (() => {
1812 nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
1813 }, TaskCreationOptions.DenyChildAttach);
1814 Assert.IsTrue (parent.Wait (1000), "#1");
1816 Assert.IsTrue (nested.Wait (2000), "#2");
1819 class SynchronousScheduler : TaskScheduler
1821 protected override IEnumerable<Task> GetScheduledTasks ()
1823 throw new NotImplementedException ();
1826 protected override void QueueTask (Task task)
1828 TryExecuteTaskInline (task, false);
1831 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1833 return base.TryExecuteTask (task);
1838 public void HideSchedulerTest ()
1840 var mre = new ManualResetEventSlim ();
1841 var ranOnDefault = false;
1842 var scheduler = new SynchronousScheduler ();
1844 Task parent = Task.Factory.StartNew (() => {
1845 Task.Factory.StartNew (() => {
1846 ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1849 }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1851 Assert.IsTrue (mre.Wait (1000), "#1");
1852 Assert.IsTrue (ranOnDefault, "#2");
1856 public void LazyCancelationTest ()
1858 var source = new CancellationTokenSource ();
1860 var parent = new Task (delegate {});
1861 var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1863 Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1866 Assert.IsTrue (cont.Wait (1000), "#2");
1868 } catch (AggregateException ex) {
1869 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");