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