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