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