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