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