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