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