Merge branch 'master' into msbuilddll2
[mono.git] / mcs / class / corlib / Test / System.Threading.Tasks / TaskTest.cs
1 //
2 // TaskTest.cs
3 //
4 // Authors:
5 //      Marek Safar  <marek.safar@gmail.com>
6 //
7 // Copyright (c) 2008 Jérémie "Garuma" Laval
8 // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
9 //
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:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
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
26 // THE SOFTWARE.
27 //
28 //
29
30 #if NET_4_0
31
32 using System;
33 using System.Threading;
34 using System.Threading.Tasks;
35 using System.Collections.Generic;
36 using NUnit.Framework;
37
38 #if !MOBILE
39 using NUnit.Framework.SyntaxHelpers;
40 #endif
41
42 namespace MonoTests.System.Threading.Tasks
43 {
44         [TestFixture]
45         public class TaskTests
46         {
47                 class MockScheduler : TaskScheduler
48                 {
49                         public event Action<Task, bool> TryExecuteTaskInlineHandler;
50
51                         protected override IEnumerable<Task> GetScheduledTasks ()
52                         {
53                                 throw new NotImplementedException ();
54                         }
55
56                         protected override void QueueTask (Task task)
57                         {
58                                 return;
59                         }
60
61                         protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
62                         {
63                                 if (TryExecuteTaskInlineHandler != null)
64                                         TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
65
66                                 return base.TryExecuteTask (task);
67                         }
68                 }
69
70                 class NonInlineableScheduler : TaskScheduler
71                 {
72                         protected override IEnumerable<Task> GetScheduledTasks ()
73                         {
74                                 throw new NotImplementedException ();
75                         }
76
77                         protected override void QueueTask (Task task)
78                         {
79                                 if (!base.TryExecuteTask (task))
80                                         throw new ApplicationException ();
81                         }
82
83                         protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
84                         {
85                                 return false;
86                         }
87                 }
88
89
90                 Task[] tasks;
91                 const int max = 6;
92                 
93                 [SetUp]
94                 public void Setup()
95                 {
96                         tasks = new Task[max];                  
97                 }
98                 
99                 void InitWithDelegate(Action action)
100                 {
101                         for (int i = 0; i < max; i++) {
102                                 tasks[i] = Task.Factory.StartNew(action);
103                         }
104                 }
105                 
106                 [Test]
107                 public void WaitAnyTest()
108                 {
109                         ParallelTestHelper.Repeat (delegate {
110                                 int flag = 0;
111                                 int finished = 0;
112                                 
113                                 InitWithDelegate(delegate {
114                                         int times = Interlocked.Exchange (ref flag, 1);
115                                         if (times == 1) {
116                                                 SpinWait sw = new SpinWait ();
117                                                 while (finished == 0) sw.SpinOnce ();
118                                         } else {
119                                                 Interlocked.Increment (ref finished);
120                                         }
121                                 });
122                                 
123                                 int index = Task.WaitAny(tasks, 1000);
124                                 
125                                 Assert.AreNotEqual (-1, index, "#3");
126                                 Assert.AreEqual (1, flag, "#1");
127                                 Assert.AreEqual (1, finished, "#2");
128                         });
129                 }
130
131                 [Test]
132                 public void WaitAny_Empty ()
133                 {
134                         Assert.AreEqual (-1, Task.WaitAny (new Task[0]));
135                 }
136
137                 [Test]
138                 public void WaitAny_Zero ()
139                 {
140                         Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { })}, 0), "#1");
141                         Assert.AreEqual (-1, Task.WaitAny (new[] { new Task (delegate { }) }, 20), "#1");
142                 }
143
144                 [Test]
145                 public void WaitAny_Cancelled ()
146                 {
147                         var cancelation = new CancellationTokenSource ();
148                         var tasks = new Task[] {
149                                 new Task (delegate { }),
150                                 new Task (delegate { }, cancelation.Token)
151                         };
152
153                         cancelation.Cancel ();
154
155                         Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
156                         Assert.IsTrue (tasks[1].IsCompleted, "#2");
157                         Assert.IsTrue (tasks[1].IsCanceled, "#3");
158                 }
159
160                 [Test]
161                 public void WaitAny_CancelledWithoutExecution ()
162                 {
163                         var cancelation = new CancellationTokenSource ();
164                         var tasks = new Task[] {
165                                 new Task (delegate { }),
166                                 new Task (delegate { })
167                         };
168
169                         int res = 0;
170                         var mre = new ManualResetEventSlim (false);
171                         ThreadPool.QueueUserWorkItem (delegate {
172                                 res = Task.WaitAny (tasks, 20);
173                                 mre.Set ();
174                         });
175
176                         cancelation.Cancel ();
177                         Assert.IsTrue (mre.Wait (1000), "#1");
178                         Assert.AreEqual (-1, res);
179                 }
180
181                 [Test]
182                 public void WaitAny_OneException ()
183                 {
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 (); })
188                         };
189
190                         Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
191                         Assert.IsFalse (tasks[0].IsCompleted, "#2");
192                         Assert.IsTrue (tasks[1].IsFaulted, "#3");
193
194                         mre.Set ();
195                 }
196
197                 [Test]
198                 public void WaitAny_SingleCanceled ()
199                 {
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 }));
203                 }
204
205                 public void WaitAny_ManyExceptions ()
206                 {
207                         CountdownEvent cde = new CountdownEvent (3);
208                         var tasks = new [] {
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 (); } })
212                         };
213
214                         Assert.IsTrue (cde.Wait (1000), "#1");
215
216                         try {
217                                 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#2");
218                         } catch (AggregateException e) {
219                                 Assert.AreEqual (3, e.InnerExceptions.Count, "#3");
220                         }
221                 }
222
223                 [Test]
224                 public void WaitAny_ManyCanceled ()
225                 {
226                         var cancellation = new CancellationToken (true);
227                         var tasks = new[] {
228                                 Task.Factory.StartNew (delegate { }, cancellation),
229                                 Task.Factory.StartNew (delegate { }, cancellation),
230                                 Task.Factory.StartNew (delegate { }, cancellation)
231                         };
232
233                         try {
234                                 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#1");
235                         } catch (AggregateException e) {
236                                 Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
237                         }
238                 }
239                 
240                 [Test]
241                 public void WaitAllTest ()
242                 {
243                         ParallelTestHelper.Repeat (delegate {
244                                 int achieved = 0;
245                                 InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
246                                 Task.WaitAll(tasks);
247                                 Assert.AreEqual(max, achieved, "#1");
248                         });
249                 }
250
251                 [Test]
252                 public void WaitAll_ManyTasks ()
253                 {
254                         for (int r = 0; r < 2000; ++r) {
255                                 var tasks = new Task[60];
256
257                                 for (int i = 0; i < tasks.Length; i++) {
258                                         tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
259                                 }
260
261                                 Assert.IsTrue (Task.WaitAll (tasks, 2000));
262                         }
263                 }
264
265                 [Test]
266                 public void WaitAll_Zero ()
267                 {
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");
270                 }
271
272                 [Test]
273                 public void WaitAll_WithExceptions ()
274                 {
275                         InitWithDelegate (delegate { throw new ApplicationException (); });
276
277                         try {
278                                 Task.WaitAll (tasks);
279                                 Assert.Fail ("#1");
280                         } catch (AggregateException e) {
281                                 Assert.AreEqual (6, e.InnerExceptions.Count, "#2");
282                         }
283
284                         Assert.IsNotNull (tasks[0].Exception, "#3");
285                 }
286
287                 [Test]
288                 public void WaitAll_TimeoutWithExceptionsAfter ()
289                 {
290                         CountdownEvent cde = new CountdownEvent (2);
291                         var mre = new ManualResetEvent (false);
292                         var tasks = new[] {
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 (); } })
296                         };
297
298                         Assert.IsTrue (cde.Wait (1000), "#1");
299                         Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
300
301                         mre.Set ();
302
303                         try {
304                                 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
305                                 Assert.Fail ("#4");
306                         } catch (AggregateException e) {
307                                 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
308                         }
309                 }
310
311                 [Test]
312                 public void WaitAll_TimeoutWithExceptionsBefore ()
313                 {
314                         CountdownEvent cde = new CountdownEvent (2);
315                         var mre = new ManualResetEvent (false);
316                         var tasks = new[] {
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 (); })
320                         };
321
322                         Assert.IsTrue (cde.Wait (1000), "#1");
323                         Assert.IsFalse (Task.WaitAll (tasks, 1000), "#2");
324
325                         mre.Set ();
326
327                         try {
328                                 Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
329                                 Assert.Fail ("#4");
330                         } catch (AggregateException e) {
331                                 Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
332                         }
333                 }
334
335                 [Test]
336                 public void WaitAll_Cancelled ()
337                 {
338                         var cancelation = new CancellationTokenSource ();
339                         var tasks = new Task[] {
340                                 new Task (delegate { cancelation.Cancel (); }),
341                                 new Task (delegate { }, cancelation.Token)
342                         };
343
344                         tasks[0].Start ();
345
346                         try {
347                                 Task.WaitAll (tasks);
348                                 Assert.Fail ("#1");
349                         } catch (AggregateException e) {
350                                 var inner = (TaskCanceledException) e.InnerException;
351                                 Assert.AreEqual (tasks[1], inner.Task, "#2");
352                         }
353
354                         Assert.IsTrue (tasks[0].IsCompleted, "#3");
355                         Assert.IsTrue (tasks[1].IsCanceled, "#4");
356                 }
357
358 #if NET_4_5             
359                 [Test]
360                 public void WaitAll_CancelledAndTimeout ()
361                 {
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));
366                 }
367 #endif
368
369                 [Test]
370                 public void WaitAllExceptionThenCancelled ()
371                 {
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)
376                         };
377
378                         tasks[0].Start ();
379
380                         try {
381                                 Task.WaitAll (tasks);
382                                 Assert.Fail ("#1");
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");
387                         }
388
389                         Assert.IsTrue (tasks[0].IsCompleted, "#4");
390                         Assert.IsTrue (tasks[1].IsCanceled, "#5");
391                 }
392
393                 [Test]
394                 public void WaitAll_StartedUnderWait ()
395                 {
396                         var task1 = new Task (delegate { });
397
398                         ThreadPool.QueueUserWorkItem (delegate {
399                                 // Sleep little to let task to start and hit internal wait
400                                 Thread.Sleep (20);
401                                 task1.Start ();
402                         });
403
404                         Assert.IsTrue (Task.WaitAll (new [] { task1 }, 1000), "#1");
405                 }
406
407                 [Test]
408                 public void CancelBeforeStart ()
409                 {
410                         var src = new CancellationTokenSource ();
411
412                         Task t = new Task (delegate { }, src.Token);
413                         src.Cancel ();
414                         Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1");
415
416                         try {
417                                 t.Start ();
418                                 Assert.Fail ("#2");
419                         } catch (InvalidOperationException) {
420                         }
421                 }
422
423                 [Test]
424                 public void Wait_CancelledTask ()
425                 {
426                         var src = new CancellationTokenSource ();
427
428                         Task t = new Task (delegate { }, src.Token);
429                         src.Cancel ();
430
431                         try {
432                                 t.Wait (1000);
433                                 Assert.Fail ("#1");
434                         } catch (AggregateException e) {
435                                 var details = (TaskCanceledException) e.InnerException;
436                                 Assert.AreEqual (t, details.Task, "#1e");
437                         }
438
439                         try {
440                                 t.Wait ();
441                                 Assert.Fail ("#2");
442                         } catch (AggregateException e) {
443                                 var details = (TaskCanceledException) e.InnerException;
444                                 Assert.AreEqual (t, details.Task, "#2e");
445                                 Assert.IsNull (details.Task.Exception, "#2e2");
446                         }
447                 }
448
449                 [Test]
450                 public void Wait_Inlined ()
451                 {
452                         bool? previouslyQueued = null;
453
454                         var scheduler = new MockScheduler ();
455                         scheduler.TryExecuteTaskInlineHandler += (task, b) => {
456                                 previouslyQueued = b;
457                         };
458
459                         var tf = new TaskFactory (scheduler);
460                         var t = tf.StartNew (() => { });
461                         t.Wait ();
462
463                         Assert.AreEqual (true, previouslyQueued);
464                 }
465
466                 [Test, ExpectedException (typeof (InvalidOperationException))]
467                 public void CreationWhileInitiallyCanceled ()
468                 {
469                         var token = new CancellationToken (true);
470                         var task = new Task (() => { }, token);
471                         Assert.AreEqual (TaskStatus.Canceled, task.Status);
472                         task.Start ();
473                 }
474
475                 [Test]
476                 public void ContinueWithInvalidArguments ()
477                 {
478                         var task = new Task (() => { });
479                         try {
480                                 task.ContinueWith (null);
481                                 Assert.Fail ("#1");
482                         } catch (ArgumentException) {
483                         }
484
485                         try {
486                                 task.ContinueWith (delegate { }, null);
487                                 Assert.Fail ("#2");
488                         } catch (ArgumentException) {
489                         }
490
491                         try {
492                                 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
493                                 Assert.Fail ("#3");
494                         } catch (ArgumentException) {
495                         }
496
497                         try {
498                                 task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
499                                 Assert.Fail ("#4");
500                         } catch (ArgumentException) {
501                         }
502                 }
503
504                 [Test]
505                 public void ContinueWithOnAnyTestCase()
506                 {
507                         ParallelTestHelper.Repeat (delegate {
508                                 bool result = false;
509                                 
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");
517                         });
518                 }
519                 
520                 [Test]
521                 public void ContinueWithOnCompletedSuccessfullyTestCase()
522                 {
523                         ParallelTestHelper.Repeat (delegate {
524                                 bool result = false;
525                                 
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");
530                                 
531                                 Assert.IsNull(cont.Exception, "#1");
532                                 Assert.IsNotNull(cont, "#2");
533                                 Assert.IsTrue(result, "#3");
534                         });
535                 }
536                 
537                 [Test]
538                 public void ContinueWithOnAbortedTestCase()
539                 {
540                         bool result = false;
541                         bool taskResult = false;
542
543                         CancellationTokenSource src = new CancellationTokenSource ();
544                         Task t = new Task (delegate { taskResult = true; }, src.Token);
545
546                         Task cont = t.ContinueWith (delegate { result = true; },
547                                 TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
548
549                         src.Cancel ();
550
551                         Assert.AreEqual (TaskStatus.Canceled, t.Status, "#1a");
552                         Assert.IsTrue (cont.IsCompleted, "#1b");
553                         Assert.IsTrue (result, "#1c");
554
555                         try {
556                                 t.Start ();
557                                 Assert.Fail ("#2");
558                         } catch (InvalidOperationException) {
559                         }
560
561                         Assert.IsTrue (cont.Wait (1000), "#3");
562
563                         Assert.IsFalse (taskResult, "#4");
564
565                         Assert.IsNull (cont.Exception, "#5");
566                         Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status, "#6");
567                 }
568                 
569                 [Test]
570                 public void ContinueWithOnFailedTestCase()
571                 {
572                         ParallelTestHelper.Repeat (delegate {
573                                 bool result = false;
574                                 
575                                 Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });       
576                                 Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
577                         
578                                 Assert.IsTrue (cont.Wait(1000), "#0");
579                                 Assert.IsNotNull (t.Exception, "#1");
580                                 Assert.IsNotNull (cont, "#2");
581                                 Assert.IsTrue (result, "#3");
582                         });
583                 }
584
585                 [Test]
586                 public void ContinueWithWithStart ()
587                 {
588                         Task t = new Task<int> (() => 1);
589                         t = t.ContinueWith (l => { });
590                         try {
591                                 t.Start ();
592                                 Assert.Fail ();
593                         } catch (InvalidOperationException) {
594                         }
595                 }
596
597                 [Test]
598                 public void ContinueWithChildren ()
599                 {
600                         ParallelTestHelper.Repeat (delegate {
601                             bool result = false;
602
603                             var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
604
605                                 var mre = new ManualResetEvent (false);
606                             t.ContinueWith (l => {
607                                         result = true;
608                                         mre.Set ();
609                                 });
610
611                                 Assert.IsTrue (mre.WaitOne (1000), "#1");
612                             Assert.IsTrue (result, "#2");
613                         }, 2);
614                 }
615
616                 [Test]
617                 public void ContinueWithDifferentOptionsAreCanceledTest ()
618                 {
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);
624
625                         mre.Set ();
626                         contSuccess.Wait (100);
627
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);
634                 }
635
636                 [Test]
637                 public void MultipleTasks()
638                 {
639                         ParallelTestHelper.Repeat (delegate {
640                                 bool r1 = false, r2 = false, r3 = false;
641                                 
642                                 Task t1 = Task.Factory.StartNew(delegate {
643                                         r1 = true;
644                                 });
645                                 Task t2 = Task.Factory.StartNew(delegate {
646                                         r2 = true;
647                                 });
648                                 Task t3 = Task.Factory.StartNew(delegate {
649                                         r3 = true;
650                                 });
651                                 
652                                 t1.Wait(2000);
653                                 t2.Wait(2000);
654                                 t3.Wait(2000);
655                                 
656                                 Assert.IsTrue(r1, "#1");
657                                 Assert.IsTrue(r2, "#2");
658                                 Assert.IsTrue(r3, "#3");
659                         }, 100);
660                 }
661                 
662                 [Test]
663                 public void WaitChildTestCase()
664                 {
665                         ParallelTestHelper.Repeat (delegate {
666                                 bool r1 = false, r2 = false, r3 = false;
667                                 var mre = new ManualResetEventSlim (false);
668                                 var mreStart = new ManualResetEventSlim (false);
669                                 
670                                 Task t = Task.Factory.StartNew(delegate {
671                                         Task.Factory.StartNew(delegate {
672                                                 mre.Wait (300);
673                                                 r1 = true;
674                                         }, TaskCreationOptions.AttachedToParent);
675                                         Task.Factory.StartNew(delegate {
676                                                 r2 = true;
677                                         }, TaskCreationOptions.AttachedToParent);
678                                         Task.Factory.StartNew(delegate {
679                                                 r3 = true;
680                                         }, TaskCreationOptions.AttachedToParent);
681                                         mreStart.Set ();
682                                 });
683                                 
684                                 mreStart.Wait (300);
685                                 Assert.IsFalse (t.Wait (10), "#0a");
686                                 mre.Set ();
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");
692                         }, 10);
693                 }
694
695                 Task parent_wfc;
696
697                 [Test]
698                 public void WaitingForChildrenToComplete ()
699                 {
700                         Task nested = null;
701                         var mre = new ManualResetEvent (false);
702
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);
712                         });
713
714                         mre.Set ();
715                         Assert.IsTrue (parent_wfc.Wait (2000), "#3");
716                         Assert.IsTrue (nested.Wait (2000), "#4");
717                 }
718
719                 [Test]
720                 public void WaitChildWithContinuationAttachedTest ()
721                 {
722                         bool result = false;
723                         var task = new Task(() =>
724                         {
725                                 Task.Factory.StartNew(() =>     {
726                                         Thread.Sleep (200);
727                                 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
728                                         Thread.Sleep (200);
729                                         result = true;
730                                 }, TaskContinuationOptions.AttachedToParent);
731                         });
732                         task.Start();
733                         task.Wait();
734                         Assert.IsTrue (result);
735                 }
736
737                 [Test]
738                 public void WaitChildWithContinuationNotAttachedTest ()
739                 {
740                         var task = new Task(() =>
741                         {
742                                 Task.Factory.StartNew(() =>     {
743                                         Thread.Sleep (200);
744                                 }, TaskCreationOptions.AttachedToParent).ContinueWith(t => {
745                                         Thread.Sleep (3000);
746                                 });
747                         });
748                         task.Start();
749                         Assert.IsTrue (task.Wait(400));
750                 }
751
752                 [Test]
753                 public void WaitChildWithNesting ()
754                 {
755                         var result = false;
756                         var t = Task.Factory.StartNew (() => {
757                                 Task.Factory.StartNew (() => {
758                                         Task.Factory.StartNew (() => {
759                                                 Thread.Sleep (500);
760                                                 result = true;
761                                         }, TaskCreationOptions.AttachedToParent);
762                                 }, TaskCreationOptions.AttachedToParent);
763                         });
764                         t.Wait ();
765                         Assert.IsTrue (result);
766                 }
767
768                 [Test]
769                 public void DoubleWaitTest ()
770                 {
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);
776
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 (); });
780
781                                 Assert.IsTrue (cntd.Wait (2000), "#1");
782                                 evt.Set ();
783                                 Assert.IsTrue (cntd2.Wait (2000), "#2");
784                                 Assert.IsTrue (r1, "r1");
785                                 Assert.IsTrue (r2, "r2");
786                         }, 10);
787                 }
788
789                 [Test]
790                 public void DoubleTimeoutedWaitTest ()
791                 {
792                         var evt = new ManualResetEventSlim ();
793                         var t = new Task (delegate { });
794                         var cntd = new CountdownEvent (2);
795
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 (); });
799
800                         cntd.Wait (2000);
801                         Assert.IsTrue (r1);
802                         Assert.IsTrue (r2);
803                 }
804
805                 [Test]
806                 public void RunSynchronously ()
807                 {
808                         var val = 0;
809                         Task t = new Task (() => { Thread.Sleep (100); val = 1; });
810                         t.RunSynchronously ();
811
812                         Assert.AreEqual (1, val, "#1");
813
814                         t = new Task (() => { Thread.Sleep (0); val = 2; });
815
816                         bool? previouslyQueued = null;
817
818                         var scheduler = new MockScheduler ();
819                         scheduler.TryExecuteTaskInlineHandler += (task, b) => {
820                                 previouslyQueued = b;
821                         };
822
823                         t.RunSynchronously (scheduler);
824
825                         Assert.AreEqual (2, val, "#2");
826                         Assert.AreEqual (false, previouslyQueued, "#2a");
827                 }
828
829                 [Test]
830                 public void RunSynchronouslyArgumentChecks ()
831                 {
832                         Task t = new Task (() => { });
833                         try {
834                                 t.RunSynchronously (null);
835                                 Assert.Fail ("#1");
836                         } catch (ArgumentNullException) {
837                         }
838                 }
839
840                 [Test]
841                 public void RunSynchronously_SchedulerException ()
842                 {
843                         var scheduler = new MockScheduler ();
844                         scheduler.TryExecuteTaskInlineHandler += (task, b) => {
845                                 throw new ApplicationException ();
846                         };
847
848                         Task t = new Task (() => { });
849                         try {
850                                 t.RunSynchronously (scheduler);
851                                 Assert.Fail ();
852                         } catch (Exception e) {
853                                 Assert.AreEqual (t.Exception.InnerException, e);
854                         }
855                 }
856
857                 [Test]
858                 public void RunSynchronouslyWithAttachedChildren ()
859                 {
860                         var result = false;
861                         var t = new Task (() => {
862                                 Task.Factory.StartNew (() => { Thread.Sleep (500); result = true; }, TaskCreationOptions.AttachedToParent);
863                         });
864                         t.RunSynchronously ();
865                         Assert.IsTrue (result);
866                 }
867
868                 [Test]
869                 public void RunSynchronouslyOnContinuation ()
870                 {
871                         Task t = new Task<int> (() => 1);
872                         t = t.ContinueWith (l => { });
873                         try {
874                                 t.RunSynchronously ();
875                                 Assert.Fail ("#1");
876                         } catch (InvalidOperationException) {
877                         }
878                 }
879
880                 [Test]
881                 public void UnobservedExceptionOnFinalizerThreadTest ()
882                 {
883                         bool wasCalled = false;
884                         TaskScheduler.UnobservedTaskException += (o, args) => {
885                                 wasCalled = true;
886                                 args.SetObserved ();
887                         };
888                         var inner = new ApplicationException ();
889                         Task.Factory.StartNew (() => { throw inner; });
890                         Thread.Sleep (1000);
891                         GC.Collect ();
892                         Thread.Sleep (1000);
893                         GC.WaitForPendingFinalizers ();
894
895                         Assert.IsTrue (wasCalled);
896                 }
897
898                 [Test, ExpectedException (typeof (InvalidOperationException))]
899                 public void StartFinishedTaskTest ()
900                 {
901                         var t = Task.Factory.StartNew (delegate () { });
902                         t.Wait ();
903
904                         t.Start ();
905                 }
906
907                 [Test]
908                 public void Start_NullArgument ()
909                 {
910                         var t = Task.Factory.StartNew (delegate () { });
911                         try {
912                                 t.Start (null);
913                                 Assert.Fail ();
914                         } catch (ArgumentNullException) {
915                         }
916                 }
917
918                 [Test, ExpectedException (typeof (InvalidOperationException))]
919                 public void DisposeUnstartedTest ()
920                 {
921                         var t = new Task (() => { });
922                         t.Dispose ();
923                 }
924
925                 [Test]
926                 public void ThrowingUnrelatedCanceledExceptionTest ()
927                 {
928                         Task t = new Task (() => {
929                                 throw new TaskCanceledException ();
930                         });
931
932                         t.RunSynchronously ();
933                         Assert.IsTrue (t.IsFaulted);
934                         Assert.IsFalse (t.IsCanceled);
935                 }
936
937                 [Test]
938                 public void CanceledContinuationExecuteSynchronouslyTest ()
939                 {
940                         var source = new CancellationTokenSource();
941                         var token = source.Token;
942                         var evt = new ManualResetEventSlim ();
943                         bool result = false;
944                         bool thrown = false;
945
946                         var task = Task.Factory.StartNew (() => evt.Wait (100));
947                         var cont = task.ContinueWith (t => result = true, token, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
948
949                         source.Cancel();
950                         evt.Set ();
951                         task.Wait (100);
952                         try {
953                                 cont.Wait (100);
954                         } catch (Exception ex) {
955                                 thrown = true;
956                         }
957
958                         Assert.IsTrue (task.IsCompleted);
959                         Assert.IsTrue (cont.IsCanceled);
960                         Assert.IsFalse (result);
961                         Assert.IsTrue (thrown);
962                 }
963
964                 [Test]
965                 public void WhenChildTaskErrorIsThrownParentTaskShouldBeFaulted ()
966                 {
967                         Task innerTask = null;
968                         var testTask = new Task (() =>
969                         {
970                                 innerTask = new Task (() => 
971                                 {
972                                         throw new InvalidOperationException ();
973                                 }, TaskCreationOptions.AttachedToParent);
974                                 innerTask.RunSynchronously ();
975                         });
976                         testTask.RunSynchronously ();
977
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);
984                 }
985                 
986                 [Test]
987                 public void WhenChildTaskErrorIsThrownOnlyOnFaultedContinuationShouldExecute ()
988                 {
989                         var continuationRan = false;
990                         var testTask = new Task (() =>
991                         {
992                                 var task = new Task (() => 
993                                 {
994                                         throw new InvalidOperationException();
995                                 }, TaskCreationOptions.AttachedToParent);
996                                 task.RunSynchronously ();
997                         });
998                         var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
999                         testTask.RunSynchronously ();
1000                         onErrorTask.Wait (100);
1001                         Assert.IsTrue (continuationRan);
1002                 }
1003                 
1004                 [Test]
1005                 public void WhenChildTaskErrorIsThrownNotOnFaultedContinuationShouldNotBeExecuted ()
1006                 {
1007                         var continuationRan = false;
1008                         var testTask = new Task (() =>
1009                         {
1010                                 var task = new Task (() => 
1011                                 {
1012                                         throw new InvalidOperationException();
1013                                 }, TaskCreationOptions.AttachedToParent);
1014                                 task.RunSynchronously();
1015                         });
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);
1021                 }       
1022                 
1023                 [Test]
1024                 public void WhenChildTaskSeveralLevelsDeepHandlesAggregateExceptionErrorStillBubblesToParent ()
1025                 {
1026                         var continuationRan = false;
1027                         AggregateException e = null;
1028                         var testTask = new Task (() =>
1029                         {
1030                                 var child1 = new Task (() =>
1031                                 {
1032                                         var child2 = new Task (() => 
1033                                         {
1034                                                 throw new InvalidOperationException();
1035                                         }, TaskCreationOptions.AttachedToParent);
1036                                         child2.RunSynchronously ();
1037                                 }, TaskCreationOptions.AttachedToParent);
1038                                 
1039                                 child1.RunSynchronously();
1040                                 e = child1.Exception;
1041                                 child1.Exception.Handle (ex => true);
1042                         });
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);
1048                 }
1049                 
1050                 [Test]
1051                 public void AlreadyCompletedChildTaskShouldRunContinuationImmediately ()
1052                 {
1053                         string result = "Failed";
1054                         var testTask = new Task (() => 
1055                         {
1056                                 var child = new Task<string> (() =>
1057                                 {
1058                                         return "Success";
1059                                 }, TaskCreationOptions.AttachedToParent);
1060                                 child.RunSynchronously ();
1061                                 child.ContinueWith (x => { Thread.Sleep (50); result = x.Result; }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted);
1062                         });
1063                         testTask.RunSynchronously ();
1064
1065                         Assert.AreEqual ("Success", result);
1066                 }
1067
1068                 [Test]
1069                 public void InlineNotTrashingParentRelationship ()
1070                 {
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);
1075                     });
1076                         t.RunSynchronously ();
1077
1078                         Assert.IsTrue (r1);
1079                         Assert.IsTrue (r2);
1080                 }
1081
1082                 [Test]
1083                 public void AsyncWaitHandleSet ()
1084                 {
1085                         var task = new TaskFactory ().StartNew (() => { });
1086                         var ar = (IAsyncResult)task;
1087                         ar.AsyncWaitHandle.WaitOne ();
1088                 }
1089
1090 #if NET_4_5
1091                 [Test]
1092                 public void Delay_Invalid ()
1093                 {
1094                         try {
1095                                 Task.Delay (-100);
1096                         } catch (ArgumentOutOfRangeException) {
1097                         }
1098                 }
1099
1100                 [Test]
1101                 public void Delay_Start ()
1102                 {
1103                         var t = Task.Delay (5000);
1104                         try {
1105                                 t.Start ();
1106                         } catch (InvalidOperationException) {
1107                         }
1108                 }
1109
1110                 [Test]
1111                 public void Delay_Simple ()
1112                 {
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");
1116                 }
1117
1118                 [Test]
1119                 public void Delay_Cancelled ()
1120                 {
1121                         var cancelation = new CancellationTokenSource ();
1122
1123                         var t = Task.Delay (5000, cancelation.Token);
1124                         Assert.IsTrue (TaskStatus.WaitingForActivation == t.Status || TaskStatus.Running == t.Status, "#1");
1125                         cancelation.Cancel ();
1126                         try {
1127                                 t.Wait (1000);
1128                                 Assert.Fail ("#2");
1129                         } catch (AggregateException) {
1130                                 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#3");
1131                         }
1132                         
1133                         cancelation = new CancellationTokenSource ();
1134                         t = Task.Delay (Timeout.Infinite, cancelation.Token);
1135                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1136                         cancelation.Cancel ();
1137                         try {
1138                                 t.Wait (1000);
1139                                 Assert.Fail ("#12");
1140                         } catch (AggregateException) {
1141                                 Assert.AreEqual (TaskStatus.Canceled, t.Status, "#13");
1142                         }
1143                 }
1144
1145                 [Test]
1146                 public void Delay_TimeManagement ()
1147                 {
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);
1152                 }
1153
1154                 [Test]
1155                 public void WaitAny_WithNull ()
1156                 {
1157                         var tasks = new [] {
1158                                 Task.FromResult (2),
1159                                 null
1160                         };
1161
1162                         try {
1163                                 Task.WaitAny (tasks);
1164                                 Assert.Fail ();
1165                         } catch (ArgumentException) {
1166                         }
1167                 }
1168
1169                 [Test]
1170                 public void WhenAll_Empty ()
1171                 {
1172                         var tasks = new Task[0];
1173
1174                         Task t = Task.WhenAll(tasks);
1175
1176                         Assert.IsTrue(t.Wait(1000), "#1");
1177                 }
1178
1179                 [Test]
1180                 public void WhenAll_WithNull ()
1181                 {
1182                         var tasks = new[] {
1183                                 Task.FromResult (2),
1184                                 null
1185                         };
1186
1187                         try {
1188                                 Task.WhenAll (tasks);
1189                                 Assert.Fail ("#1");
1190                         } catch (ArgumentException) {
1191                         }
1192
1193                         tasks = null;
1194                         try {
1195                                 Task.WhenAll (tasks);
1196                                 Assert.Fail ("#2");
1197                         } catch (ArgumentException) {
1198                         }
1199                 }
1200
1201                 [Test]
1202                 public void WhenAll_Start ()
1203                 {
1204                         Task[] tasks = new[] {
1205                                 Task.FromResult (2),
1206                         };
1207
1208                         var t = Task.WhenAll (tasks);
1209                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1210
1211                         try {
1212                                 t.Start ();
1213                                 Assert.Fail ("#2");
1214                         } catch (InvalidOperationException) {
1215                         }
1216
1217                         tasks = new [] {
1218                                 new Task (delegate { }),
1219                         };
1220
1221                         t = Task.WhenAll (tasks);
1222                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1223
1224                         try {
1225                                 t.Start ();
1226                                 Assert.Fail ("#12");
1227                         } catch (InvalidOperationException) {
1228                         }
1229                 }
1230
1231                 [Test]
1232                 public void WhenAll_Cancelled ()
1233                 {
1234                         var cancelation = new CancellationTokenSource ();
1235                         var tasks = new Task[] {
1236                                 new Task (delegate { }),
1237                                 new Task (delegate { }, cancelation.Token)
1238                         };
1239
1240                         cancelation.Cancel ();
1241
1242                         var t = Task.WhenAll (tasks);
1243                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1244                         tasks[0].Start ();
1245
1246                         try {
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");
1251                         }
1252                 }
1253
1254                 [Test]
1255                 public void WhenAll_Faulted ()
1256                 {
1257                         var tcs = new TaskCompletionSource<object> ();
1258                         tcs.SetException (new ApplicationException ());
1259
1260                         var tcs2 = new TaskCompletionSource<object> ();
1261                         tcs2.SetException (new InvalidTimeZoneException ());
1262
1263                         var cancelation = new CancellationTokenSource ();
1264                         var tasks = new Task[] {
1265                                 new Task (delegate { }),
1266                                 new Task (delegate { }, cancelation.Token),
1267                                 tcs.Task,
1268                                 tcs2.Task
1269                         };
1270
1271                         cancelation.Cancel ();
1272
1273                         var t = Task.WhenAll (tasks);
1274                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1275                         tasks[0].Start ();
1276
1277                         try {
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");
1283                         }
1284                 }
1285
1286                 [Test]
1287                 public void WhenAll ()
1288                 {
1289                         var t1 = new Task (delegate { });
1290                         var t2 = new Task (delegate { t1.Start (); });
1291
1292                         var tasks = new Task[] {
1293                                 t1,
1294                                 t2,
1295                         };
1296
1297                         var t = Task.WhenAll (tasks);
1298                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1299                         t2.Start ();
1300
1301                         Assert.IsTrue (t.Wait (1000), "#2");
1302                 }
1303
1304                 [Test]
1305                 public void WhenAllResult_Empty ()
1306                 {
1307                         var tasks = new Task<int>[0];
1308
1309                         Task<int[]> t = Task.WhenAll(tasks);
1310
1311                         Assert.IsTrue(t.Wait(1000), "#1");
1312                         Assert.IsNotNull(t.Result, "#2");
1313                         Assert.AreEqual(t.Result.Length, 0, "#3");
1314                 }
1315
1316                 [Test]
1317                 public void WhenAllResult_WithNull ()
1318                 {
1319                         var tasks = new[] {
1320                                 Task.FromResult (2),
1321                                 null
1322                         };
1323
1324                         try {
1325                                 Task.WhenAll<int> (tasks);
1326                                 Assert.Fail ("#1");
1327                         } catch (ArgumentException) {
1328                         }
1329
1330                         tasks = null;
1331                         try {
1332                                 Task.WhenAll<int> (tasks);
1333                                 Assert.Fail ("#2");
1334                         } catch (ArgumentException) {
1335                         }
1336                 }
1337
1338                 [Test]
1339                 public void WhenAllResult_Cancelled ()
1340                 {
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)
1345                         };
1346
1347                         cancelation.Cancel ();
1348
1349                         var t = Task.WhenAll (tasks);
1350                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1351                         tasks[0].Start ();
1352
1353                         try {
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");
1358                         }
1359
1360                         try {
1361                                 var r = t.Result;
1362                                 Assert.Fail ("#4");
1363                         } catch (AggregateException) {
1364                         }
1365                 }
1366
1367                 [Test]
1368                 public void WhenAllResult ()
1369                 {
1370                         var t1 = new Task<string> (delegate { return "a"; });
1371                         var t2 = new Task<string> (delegate { t1.Start (); return "b"; });
1372
1373                         var tasks = new [] {
1374                                 t1,
1375                                 t2,
1376                         };
1377
1378                         var t = Task.WhenAll<string> (tasks);
1379                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1380                         t2.Start ();
1381
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");
1386                 }
1387
1388                 [Test]
1389                 public void WhenAllResult_Completed ()
1390                 {
1391                         var tasks = new[] {
1392                                 Task.FromResult (1),
1393                                 Task.FromResult (2)
1394                         };
1395
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");
1401                 }
1402
1403                 [Test]
1404                 public void WhenAny_WithNull ()
1405                 {
1406                         var tasks = new Task[] {
1407                                 Task.FromResult (2),
1408                                 null
1409                         };
1410
1411                         try {
1412                                 Task.WhenAny (tasks);
1413                                 Assert.Fail ("#1");
1414                         } catch (ArgumentException) {
1415                         }
1416
1417                         tasks = null;
1418                         try {
1419                                 Task.WhenAny (tasks);
1420                                 Assert.Fail ("#2");
1421                         } catch (ArgumentException) {
1422                         }
1423
1424                         try {
1425                                 Task.WhenAny (new Task[0]);
1426                                 Assert.Fail ("#3");
1427                         } catch (ArgumentException) {
1428                         }
1429                 }
1430
1431                 [Test]
1432                 public void WhenAny_Start ()
1433                 {
1434                         Task[] tasks = new[] {
1435                                 Task.FromResult (2),
1436                         };
1437
1438                         var t = Task.WhenAny (tasks);
1439                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1440
1441                         try {
1442                                 t.Start ();
1443                                 Assert.Fail ("#2");
1444                         } catch (InvalidOperationException) {
1445                         }
1446
1447                         tasks = new[] {
1448                                 new Task (delegate { }),
1449                         };
1450
1451                         t = Task.WhenAny (tasks);
1452                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1453
1454                         try {
1455                                 t.Start ();
1456                                 Assert.Fail ("#12");
1457                         } catch (InvalidOperationException) {
1458                         }
1459                 }
1460
1461                 [Test]
1462                 public void WhenAny_Cancelled ()
1463                 {
1464                         var cancelation = new CancellationTokenSource ();
1465                         var tasks = new Task[] {
1466                                 new Task (delegate { }),
1467                                 new Task (delegate { }, cancelation.Token)
1468                         };
1469
1470                         cancelation.Cancel ();
1471
1472                         var t = Task.WhenAny (tasks);
1473                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1474                         tasks[0].Start ();
1475
1476                         Assert.IsTrue (t.Wait (1000), "#2");
1477                         Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1478                 }
1479
1480                 [Test]
1481                 public void WhenAny_Faulted ()
1482                 {
1483                         var tcs = new TaskCompletionSource<object> ();
1484                         tcs.SetException (new ApplicationException ());
1485
1486                         var tcs2 = new TaskCompletionSource<object> ();
1487                         tcs2.SetException (new InvalidTimeZoneException ());
1488
1489                         var cancelation = new CancellationTokenSource ();
1490                         var tasks = new Task[] {
1491                                 new Task (delegate { }),
1492                                 tcs.Task,
1493                                 new Task (delegate { }, cancelation.Token),
1494                                 tcs2.Task
1495                         };
1496
1497                         cancelation.Cancel ();
1498
1499                         var t = Task.WhenAny (tasks);
1500                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1501                         tasks[0].Start ();
1502
1503                         Assert.IsTrue (t.Wait (1000), "#2");
1504                         Assert.IsNull (t.Exception, "#3");
1505
1506                         Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1507                 }
1508
1509                 [Test]
1510                 public void WhenAny ()
1511                 {
1512                         var t1 = new Task (delegate { });
1513                         var t2 = new Task (delegate { t1.Start (); });
1514
1515                         var tasks = new Task[] {
1516                                 t1,
1517                                 t2,
1518                         };
1519
1520                         var t = Task.WhenAny (tasks);
1521                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1522                         t2.Start ();
1523
1524                         Assert.IsTrue (t.Wait (1000), "#2");
1525                         Assert.IsNotNull (t.Result, "#3");
1526                 }
1527
1528                 [Test]
1529                 public void WhenAnyResult_WithNull ()
1530                 {
1531                         var tasks = new [] {
1532                                 Task.FromResult (2),
1533                                 null
1534                         };
1535
1536                         try {
1537                                 Task.WhenAny<int> (tasks);
1538                                 Assert.Fail ("#1");
1539                         } catch (ArgumentException) {
1540                         }
1541
1542                         tasks = null;
1543                         try {
1544                                 Task.WhenAny<int> (tasks);
1545                                 Assert.Fail ("#2");
1546                         } catch (ArgumentException) {
1547                         }
1548
1549                         try {
1550                                 Task.WhenAny<short> (new Task<short>[0]);
1551                                 Assert.Fail ("#3");
1552                         } catch (ArgumentException) {
1553                         }
1554                 }
1555
1556                 [Test]
1557                 public void WhenAnyResult_Start ()
1558                 {
1559                         var tasks = new[] {
1560                                 Task.FromResult (2),
1561                         };
1562
1563                         var t = Task.WhenAny<int> (tasks);
1564                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1565
1566                         try {
1567                                 t.Start ();
1568                                 Assert.Fail ("#2");
1569                         } catch (InvalidOperationException) {
1570                         }
1571
1572                         tasks = new[] {
1573                                 new Task<int> (delegate { return 55; }),
1574                         };
1575
1576                         t = Task.WhenAny<int> (tasks);
1577                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#11");
1578
1579                         try {
1580                                 t.Start ();
1581                                 Assert.Fail ("#12");
1582                         } catch (InvalidOperationException) {
1583                         }
1584                 }
1585
1586                 [Test]
1587                 public void WhenAnyResult_Cancelled ()
1588                 {
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)
1593                         };
1594
1595                         cancelation.Cancel ();
1596
1597                         var t = Task.WhenAny<double> (tasks);
1598                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1599                         tasks[0].Start ();
1600
1601                         Assert.IsTrue (t.Wait (1000), "#2");
1602                         Assert.AreEqual (TaskStatus.Canceled, t.Result.Status, "#3");
1603                 }
1604
1605                 [Test]
1606                 public void WhenAnyResult_Faulted ()
1607                 {
1608                         var tcs = new TaskCompletionSource<object> ();
1609                         tcs.SetException (new ApplicationException ());
1610
1611                         var tcs2 = new TaskCompletionSource<object> ();
1612                         tcs2.SetException (new InvalidTimeZoneException ());
1613
1614                         var cancelation = new CancellationTokenSource ();
1615                         var tasks = new Task<object>[] {
1616                                 new Task<object> (delegate { return null; }),
1617                                 tcs.Task,
1618                                 new Task<object> (delegate { return ""; }, cancelation.Token),
1619                                 tcs2.Task
1620                         };
1621
1622                         cancelation.Cancel ();
1623
1624                         var t = Task.WhenAny<object> (tasks);
1625                         Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#1");
1626                         tasks[0].Start ();
1627
1628                         Assert.IsTrue (t.Wait (1000), "#2");
1629                         Assert.IsNull (t.Exception, "#3");
1630
1631                         Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
1632                 }
1633
1634                 [Test]
1635                 public void WhenAnyResult ()
1636                 {
1637                         var t1 = new Task<byte> (delegate { return 3; });
1638                         var t2 = new Task<byte> (delegate { t1.Start (); return 2; });
1639
1640                         var tasks = new [] {
1641                                 t1,
1642                                 t2,
1643                         };
1644
1645                         var t = Task.WhenAny<byte> (tasks);
1646                         Assert.AreEqual (TaskStatus.WaitingForActivation, t.Status, "#1");
1647                         t2.Start ();
1648
1649                         Assert.IsTrue (t.Wait (1000), "#2");
1650                         Assert.IsTrue (t.Result.Result > 1, "#3");
1651                 }
1652
1653                 [Test]
1654                 public void ContinueWith_StateValue ()
1655                 {
1656                         var t = Task.Factory.StartNew (l => {
1657                                 Assert.AreEqual (1, l, "a-1");
1658                         }, 1);
1659
1660                         var c = t.ContinueWith ((a, b) => {
1661                                 Assert.AreEqual (t, a, "c-1");
1662                                 Assert.AreEqual (2, b, "c-2");
1663                         }, 2);
1664
1665                         var d = t.ContinueWith ((a, b) => {
1666                                 Assert.AreEqual (t, a, "d-1");
1667                                 Assert.AreEqual (3, b, "d-2");
1668                                 return 77;
1669                         }, 3);
1670
1671                         Assert.IsTrue (d.Wait (1000), "#1");
1672
1673                         Assert.AreEqual (1, t.AsyncState, "#2");
1674                         Assert.AreEqual (2, c.AsyncState, "#3");
1675                         Assert.AreEqual (3, d.AsyncState, "#4");
1676                 }
1677
1678                 [Test]
1679                 public void ContinueWith_StateValueGeneric ()
1680                 {
1681                         var t = Task<int>.Factory.StartNew (l => {
1682                                 Assert.AreEqual (1, l, "a-1");
1683                                 return 80;
1684                         }, 1);
1685
1686                         var c = t.ContinueWith ((a, b) => {
1687                                 Assert.AreEqual (t, a, "c-1");
1688                                 Assert.AreEqual (2, b, "c-2");
1689                                 return "c";
1690                         }, 2);
1691
1692                         var d = t.ContinueWith ((a, b) => {
1693                                 Assert.AreEqual (t, a, "d-1");
1694                                 Assert.AreEqual (3, b, "d-2");
1695                                 return 'd';
1696                         }, 3);
1697
1698                         Assert.IsTrue (d.Wait (1000), "#1");
1699
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");
1706                 }
1707
1708                 [Test]
1709                 public void ContinueWith_CustomScheduleRejected ()
1710                 {
1711                         var scheduler = new NonInlineableScheduler ();
1712                         var t = Task.Factory.StartNew (delegate { }).
1713                                 ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
1714                         
1715                         Assert.IsTrue (t.Wait (5000));
1716                 }
1717
1718                 [Test]
1719                 public void FromResult ()
1720                 {
1721                         var t = Task.FromResult<object> (null);
1722                         Assert.IsTrue (t.IsCompleted, "#1");
1723                         Assert.AreEqual (null, t.Result, "#2");
1724                         t.Dispose ();
1725                         t.Dispose ();
1726                 }
1727
1728                 [Test]
1729                 public void LongRunning ()
1730                 {
1731                         bool? is_tp = null;
1732                         bool? is_bg = null;
1733                         var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
1734                         t.Start ();
1735                         Assert.IsTrue (t.Wait (100));
1736                         Assert.IsTrue ((bool)is_tp, "#1");
1737                         Assert.IsTrue ((bool)is_bg, "#2");
1738
1739                         is_tp = null;
1740                         is_bg = null;
1741                         t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
1742                         t.Start ();
1743
1744                         Assert.IsTrue (t.Wait (100));
1745                         Assert.IsFalse ((bool) is_tp, "#11");
1746                         Assert.IsTrue ((bool) is_bg, "#12");
1747                 }
1748
1749                 [Test]
1750                 public void Run_ArgumentCheck ()
1751                 {
1752                         try {
1753                                 Task.Run (null as Action);
1754                                 Assert.Fail ("#1");
1755                         } catch (ArgumentNullException) {
1756                         }
1757                 }
1758
1759                 [Test]
1760                 public void Run ()
1761                 {
1762                         bool ranOnDefaultScheduler = false;
1763                         var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
1764                         Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
1765                         t.Wait ();
1766                         Assert.IsTrue (ranOnDefaultScheduler, "#2");
1767                 }
1768
1769                 [Test]
1770                 public void Run_Cancel ()
1771                 {
1772                         var t = Task.Run (() => 1, new CancellationToken (true));
1773                         try {
1774                                 var r = t.Result;
1775                                 Assert.Fail ("#1");
1776                         } catch (AggregateException) {
1777                         }
1778
1779                         Assert.IsTrue (t.IsCanceled, "#2");
1780                 }
1781
1782                 [Test]
1783                 public void Run_ExistingTaskT ()
1784                 {
1785                         var t = new Task<int> (() => 5);
1786                         var t2 = Task.Run (() => { t.Start (); return t; });
1787
1788                         Assert.IsTrue (t2.Wait (1000), "#1");
1789                         Assert.AreEqual (5, t2.Result, "#2");
1790                 }
1791
1792                 [Test]
1793                 public void Run_ExistingTask ()
1794                 {
1795                         var t = new Task (delegate { throw new Exception ("Foo"); });
1796                         var t2 = Task.Run (() => { t.Start (); return t; });
1797
1798                         try {
1799                                 t2.Wait (1000);
1800                                 Assert.Fail ();
1801                         } catch (Exception) {}
1802
1803                         Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
1804                 }
1805
1806                 [Test]
1807                 public void DenyChildAttachTest ()
1808                 {
1809                         var mre = new ManualResetEventSlim ();
1810                         Task nested = null;
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");
1815                         mre.Set ();
1816                         Assert.IsTrue (nested.Wait (2000), "#2");
1817                 }
1818
1819                 class SynchronousScheduler : TaskScheduler
1820                 {
1821                         protected override IEnumerable<Task> GetScheduledTasks ()
1822                         {
1823                                 throw new NotImplementedException ();
1824                         }
1825
1826                         protected override void QueueTask (Task task)
1827                         {
1828                                 TryExecuteTaskInline (task, false);
1829                         }
1830
1831                         protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
1832                         {
1833                                 return base.TryExecuteTask (task);
1834                         }
1835                 }
1836
1837                 [Test]
1838                 public void HideSchedulerTest ()
1839                 {
1840                         var mre = new ManualResetEventSlim ();
1841                         var ranOnDefault = false;
1842                         var scheduler = new SynchronousScheduler ();
1843
1844                         Task parent = Task.Factory.StartNew (() => {
1845                                 Task.Factory.StartNew (() => {
1846                                         ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
1847                                         mre.Set ();
1848                                 });
1849                         }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
1850
1851                         Assert.IsTrue (mre.Wait (1000), "#1");
1852                         Assert.IsTrue (ranOnDefault, "#2");
1853                 }
1854
1855                 [Test]
1856                 public void LazyCancelationTest ()
1857                 {
1858                         var source = new CancellationTokenSource ();
1859                         source.Cancel ();
1860                         var parent = new Task (delegate {});
1861                         var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
1862
1863                         Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
1864                         parent.Start ();
1865                         try {
1866                                 Assert.IsTrue (cont.Wait (1000), "#2");
1867                                 Assert.Fail ();
1868                         } catch (AggregateException ex) {
1869                                 Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
1870                         }
1871                 }
1872 #endif
1873         }
1874 }
1875 #endif