[resgen] Implement conditional resources (#if/#ifdef)
[mono.git] / mcs / class / corlib / Test / System.Threading.Tasks / TaskFactoryTest.cs
1 //
2 // TaskFactoryTest.cs
3 //
4 // Authors:
5 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
6 //       Marek Safar <marek.safar@gmail.com>
7 // 
8 // Copyright (c) 2010 Jérémie "Garuma" Laval
9 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29 //
30
31 #if NET_4_0
32
33 using System;
34 using System.Threading;
35 using System.Threading.Tasks;
36 using System.Collections.Generic;
37
38 using NUnit.Framework;
39 #if !MOBILE
40 using NUnit.Framework.SyntaxHelpers;
41 #endif
42
43 namespace MonoTests.System.Threading.Tasks
44 {
45         [TestFixture]
46         public class TaskFactoryTests
47         {
48                 class CompletedAsyncResult : IAsyncResult
49                 {
50                         public object AsyncState
51                         {
52                                 get { throw new NotImplementedException (); }
53                         }
54
55                         public WaitHandle AsyncWaitHandle
56                         {
57                                 get { throw new NotImplementedException (); }
58                         }
59
60                         public bool CompletedSynchronously
61                         {
62                                 get { throw new NotImplementedException (); }
63                         }
64
65                         public bool IsCompleted
66                         {
67                                 get { return true; }
68                         }
69                 }
70
71                 class TestAsyncResult : IAsyncResult
72                 {
73                         WaitHandle wh = new ManualResetEvent (true);
74
75                         public object AsyncState
76                         {
77                                 get { throw new NotImplementedException (); }
78                         }
79
80                         public WaitHandle AsyncWaitHandle
81                         {
82                                 get
83                                 {
84                                         return wh;
85                                 }
86                         }
87
88                         public bool CompletedSynchronously
89                         {
90                                 get { throw new NotImplementedException (); }
91                         }
92
93                         public bool IsCompleted
94                         {
95                                 get { return false; }
96                         }
97                 }
98
99                 class TestScheduler : TaskScheduler
100                 {
101                         public bool ExecutedInline { get; set; }
102
103                         protected override void QueueTask (Task task)
104                         {
105                                 throw new NotImplementedException ();
106                         }
107
108                         protected override bool TryDequeue (Task task)
109                         {
110                                 throw new NotImplementedException ();
111                         }
112
113                         protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
114                         {
115                                 if (taskWasPreviouslyQueued)
116                                         throw new ArgumentException ("taskWasPreviouslyQueued");
117
118                                 if (task.Status != TaskStatus.WaitingToRun)
119                                         throw new ArgumentException ("task.Status");
120
121                                 ExecutedInline = true;
122                                 return TryExecuteTask (task);
123                         }
124
125                         protected override IEnumerable<Task> GetScheduledTasks ()
126                         {
127                                 throw new NotImplementedException ();
128                         }
129                 }
130
131
132                 TaskFactory factory;
133
134                 [SetUp]
135                 public void Setup ()
136                 {
137                         this.factory = Task.Factory;
138                 }
139
140                 [Test]
141                 public void StartNewTest ()
142                 {
143                         bool result = false;
144                         factory.StartNew (() => result = true).Wait ();
145                         Assert.IsTrue (result);
146                 }
147
148                 [Test]
149                 public void NoDefaultScheduler ()
150                 {
151                         Assert.IsNull (factory.Scheduler, "#1");
152                 }
153
154                 [Test]
155                 public void ContinueWhenAll_Simple ()
156                 {
157                         var mre = new ManualResetEventSlim (false);
158
159                         Task[] tasks = new Task[3];
160                         tasks[0] = new Task (() => { Thread.Sleep (0); Assert.IsTrue (mre.Wait (5000)); });
161                         tasks[1] = new Task (() => { Assert.IsTrue (mre.Wait (5000)); });
162                         tasks[2] = new Task (() => { Assert.IsTrue (mre.Wait (5000)); });
163
164                         bool ran = false;
165                         Task cont = factory.ContinueWhenAll (tasks, ts => {
166                                 Assert.AreEqual (tasks, ts, "#0");
167                                 ran = true;
168                         });
169
170                         foreach (Task t in tasks)
171                                 t.Start ();
172
173                         mre.Set ();
174
175                         Assert.IsTrue (cont.Wait (3000), "#1");
176                         Assert.IsTrue (ran, "#2");
177                 }
178
179                 [Test]
180                 public void ContinueWhenAll_WithMixedCompletionState ()
181                 {
182                         var mre = new ManualResetEventSlim ();
183                         var task = Task.Factory.StartNew (() => mre.Wait (1000));
184                         var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
185                         var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
186                         var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
187                         bool ran = false;
188
189                         var cont = Task.Factory.ContinueWhenAll (new Task[] { contFailed, contCanceled, contSuccess }, _ => ran = true);
190
191                         mre.Set ();
192                         cont.Wait (3000);
193
194                         Assert.IsTrue (ran);
195                         Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
196                 }
197
198                 [Test]
199                 public void ContinueWhenAll_InvalidArguments ()
200                 {
201                         try {
202                                 factory.ContinueWhenAll (null, delegate { });
203                                 Assert.Fail ("#1");
204                         } catch (ArgumentNullException) {
205                         }
206
207                         try {
208                                 factory.ContinueWhenAll (new Task[0], delegate { });
209                                 Assert.Fail ("#2");
210                         } catch (ArgumentException) {
211                         }
212
213                         try {
214                                 factory.ContinueWhenAll (new Task[] { null }, delegate { });
215                                 Assert.Fail ("#3");
216                         } catch (ArgumentException) {
217                         }
218
219                         var tasks = new Task [] {
220                                 factory.StartNew (delegate {})
221                         };
222
223                         try {
224                                 factory.ContinueWhenAll (tasks, null);
225                                 Assert.Fail ("#4");
226                         } catch (ArgumentNullException) {
227                         }
228
229                         try {
230                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
231                                 Assert.Fail ("#5");
232                         } catch (ArgumentNullException) {
233                         }
234
235                         try {
236                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
237                                 Assert.Fail ("#6");
238                         } catch (ArgumentNullException) {
239                         } catch (ArgumentOutOfRangeException) {
240                         }
241                 }
242
243                 [Test]
244                 public void ContinueWhenAll_WithExceptions ()
245                 {
246                         var t1 = Task.Factory.StartNew (() => { throw new ApplicationException ("Foo"); });
247                         var t2 = Task.Factory.StartNew (() => { throw new ApplicationException ("Bar"); });
248
249                         var cont = Task.Factory.ContinueWhenAll (new[] { t1, t2 }, delegate {});
250                         cont.Wait (200);
251
252                         Assert.IsTrue (t1.IsFaulted);
253                         Assert.IsTrue (t2.IsFaulted);
254                         Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
255                 }
256
257                 [Test]
258                 public void ContinueWhenAny_Simple ()
259                 {
260                         var t1 = new ManualResetEvent (false);
261                         var t2 = new ManualResetEvent (false);
262
263                         var tasks = new Task[2] {
264                                 Task.Factory.StartNew (() => { t1.WaitOne (5000); }),
265                                 Task.Factory.StartNew (() => { t2.WaitOne (5000); })
266                         };
267
268                         bool ran = false;
269                         var ct = new CancellationToken ();
270                         Task cont = factory.ContinueWhenAny (tasks, t => {
271                                 Assert.AreEqual (tasks[0], t, "#1");
272                                 ran = true;
273                         }, ct);
274
275                         Assert.AreEqual (TaskStatus.WaitingForActivation, cont.Status, "#2");
276
277                         t1.Set ();
278
279                         Assert.IsTrue (cont.Wait (3000), "#10");
280                         Assert.IsTrue (ran, "#11");
281
282                         t2.Set ();
283                 }
284
285                 [Test]
286                 public void ContinueWhenAny_WithResult ()
287                 {
288                         var tcs = new TaskCompletionSource<int>();
289                         tcs.SetResult(1);
290                         Task[] tasks = new[] { tcs.Task };
291                         var res = Task.Factory.ContinueWhenAny (tasks, l => 4);
292                         Assert.AreEqual (4, res.Result);
293                 }
294
295                 [Test]
296                 public void ContinueWhenAny_InvalidArguments ()
297                 {
298                         try {
299                                 factory.ContinueWhenAny (null, delegate { });
300                                 Assert.Fail ("#1");
301                         } catch (ArgumentNullException) {
302                         }
303
304                         try {
305                                 factory.ContinueWhenAny (new Task[0], delegate { });
306                                 Assert.Fail ("#2");
307                         } catch (ArgumentException) {
308                         }
309
310                         try {
311                                 factory.ContinueWhenAny (new Task[] { null }, delegate { });
312                                 Assert.Fail ("#3");
313                         } catch (ArgumentException) {
314                         }
315
316                         var tasks = new Task [] {
317                                 factory.StartNew (delegate {})
318                         };
319
320                         try {
321                                 factory.ContinueWhenAny (tasks, null);
322                                 Assert.Fail ("#4");
323                         } catch (ArgumentNullException) {
324                         }
325
326                         try {
327                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
328                                 Assert.Fail ("#5");
329                         } catch (ArgumentNullException) {
330                         }
331
332                         try {
333                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
334                                 Assert.Fail ("#6");
335                         } catch (ArgumentNullException) {
336                         } catch (ArgumentOutOfRangeException) {
337                         }
338                 }
339
340                 [Test]
341                 public void FromAsyncBeginInvoke_WithResult ()
342                 {
343                         bool result = false;
344
345                         Func<int, int> func = (i) => {
346                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread);
347                                 result = true; return i + 3;
348                         };
349
350                         var task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, "state", TaskCreationOptions.AttachedToParent);
351                         Assert.IsTrue (task.Wait (5000), "#1");
352                         Assert.IsTrue (result, "#2");
353                         Assert.AreEqual (4, task.Result, "#3");
354                         Assert.AreEqual ("state", (string) task.AsyncState, "#4");
355                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#5");
356                 }
357
358                 [Test]
359                 public void FromAsyncBeginMethod_DirectResult ()
360                 {
361                         bool result = false;
362                         bool continuationTest = false;
363
364                         Func<int, int> func = (i) => { result = true; return i + 3; };
365                         Task<int> task = factory.FromAsync<int> (func.BeginInvoke (1, delegate { }, null), func.EndInvoke);
366                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
367                         task.Wait ();
368                         cont.Wait ();
369
370                         Assert.IsTrue (result);
371                         Assert.IsTrue (continuationTest);
372                         Assert.AreEqual (4, task.Result);
373                 }
374
375                 [Test]
376                 public void FromAsyncBeginMethod_Exception ()
377                 {
378                         bool result = false;
379                         bool continuationTest = false;
380
381                         Func<int, int> func = (i) => { result = true; throw new ApplicationException ("bleh"); };
382                         Task<int> task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, null);
383                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
384                         try {
385                                 task.Wait (2000);
386                         } catch { }
387                         Assert.IsTrue (cont.Wait (2000), "#1");
388
389                         Assert.IsTrue (result);
390                         Assert.IsTrue (continuationTest);
391                         Assert.IsNotNull (task.Exception);
392                         var agg = task.Exception;
393                         Assert.AreEqual (1, agg.InnerExceptions.Count);
394                         Assert.That (agg.InnerExceptions[0], Is.TypeOf (typeof (ApplicationException)));
395                         Assert.AreEqual (TaskStatus.Faulted, task.Status);
396
397                         try {
398                                 var a = task.Result;
399                                 Assert.Fail ();
400                         } catch (AggregateException) {
401                         }
402                 }
403
404                 [Test]
405                 public void FromAsync_ArgumentsCheck ()
406                 {
407                         var result = new CompletedAsyncResult ();
408                         try {
409                                 factory.FromAsync (null, l => { });
410                                 Assert.Fail ("#1");
411                         } catch (ArgumentNullException) {
412                         }
413
414                         try {
415                                 factory.FromAsync (result, null);
416                                 Assert.Fail ("#2");
417                         } catch (ArgumentNullException) {
418                         }
419
420                         try {
421                                 factory.FromAsync (result, l => { }, TaskCreationOptions.LongRunning);
422                                 Assert.Fail ("#3");
423                         } catch (ArgumentOutOfRangeException) {
424                         }
425
426                         try {
427                                 factory.FromAsync (result, l => { }, TaskCreationOptions.PreferFairness);
428                                 Assert.Fail ("#4");
429                         } catch (ArgumentOutOfRangeException) {
430                         }
431
432                         try {
433                                 factory.FromAsync (result, l => { }, TaskCreationOptions.None, null);
434                                 Assert.Fail ("#5");
435                         } catch (ArgumentNullException) {
436                         }
437
438                         try {
439                                 factory.FromAsync (null, l => { }, null, TaskCreationOptions.None);
440                                 Assert.Fail ("#6");
441                         } catch (ArgumentNullException) {
442                         }
443
444                         try {
445                                 factory.FromAsync ((a, b) => null, l => { }, null, TaskCreationOptions.LongRunning);
446                                 Assert.Fail ("#7");
447                         } catch (ArgumentOutOfRangeException) {
448                         }
449                 }
450
451                 [Test]
452                 public void FromAsync_Completed ()
453                 {
454                         var completed = new CompletedAsyncResult ();
455                         bool? valid = null;
456
457                         Action<IAsyncResult> end = l => {
458                                 Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#2");
459                                 valid = l == completed;
460                         };
461                         Task task = factory.FromAsync (completed, end);
462                         Assert.IsTrue (valid == true, "#1");
463                 }
464
465                 [Test]
466                 public void FromAsync_CompletedWithException ()
467                 {
468                         var completed = new CompletedAsyncResult ();
469
470                         Action<IAsyncResult> end = l => {
471                                 throw new ApplicationException ();
472                         };
473                         Task task = factory.FromAsync (completed, end);
474                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#1");
475                 }
476
477                 [Test]
478                 public void FromAsync_CompletedCanceled ()
479                 {
480                         var completed = new CompletedAsyncResult ();
481
482                         Action<IAsyncResult> end = l => {
483                                 throw new OperationCanceledException ();
484                         };
485                         Task task = factory.FromAsync (completed, end);
486                         Assert.AreEqual (TaskStatus.Canceled, task.Status, "#1");
487                         Assert.IsNull (task.Exception, "#2");
488                 }
489
490                 [Test]
491                 public void FromAsync_SimpleAsyncResult ()
492                 {
493                         var result = new TestAsyncResult ();
494                         bool called = false;
495
496                         var task = factory.FromAsync (result, l => {
497                                 called = true;
498                         });
499
500                         Assert.IsTrue (task.Wait (1000), "#1");
501                         Assert.IsTrue (called, "#2");
502                 }
503
504                 [Test]
505                 public void FromAsync_ResultException ()
506                 {
507                         var result = new TestAsyncResult ();
508
509                         var task = factory.FromAsync (result, l => {
510                                 throw new ApplicationException ();
511                         });
512
513                         try {
514                                 Assert.IsFalse (task.Wait (1000), "#1");
515                         } catch (AggregateException) {
516                         }
517
518                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#2");
519                 }
520
521                 [Test]
522                 public void FromAsync_ReturnInt ()
523                 {
524                         var result = new TestAsyncResult ();
525                         bool called = false;
526
527                         var task = factory.FromAsync<int> (result, l => {
528                                 called = true;
529                                 return 4;
530                         });
531
532                         Assert.IsTrue (task.Wait (1000), "#1");
533                         Assert.IsTrue (called, "#2");
534                         Assert.AreEqual (4, task.Result, "#3");
535                 }
536
537                 [Test]
538                 public void FromAsync_Scheduler_Explicit ()
539                 {
540                         var result = new TestAsyncResult ();
541                         bool called = false;
542                         var scheduler = new TestScheduler ();
543
544                         var task = factory.FromAsync (result, l => {
545                                 called = true;
546                         }, TaskCreationOptions.None, scheduler);
547
548                         Assert.IsTrue (task.Wait (5000), "#1");
549                         Assert.IsTrue (called, "#2");
550                         Assert.IsTrue (scheduler.ExecutedInline, "#3");
551                 }
552
553                 [Test]
554                 public void FromAsync_Scheduler_Implicit ()
555                 {
556                         var result = new TestAsyncResult ();
557                         bool called = false;
558                         var scheduler = new TestScheduler ();
559
560                         factory = new TaskFactory (scheduler);
561
562                         Task task = factory.FromAsync (result, l => {
563                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread, "#6");
564                                 called = true;
565                         }, TaskCreationOptions.AttachedToParent);
566
567                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#1");
568                         Assert.IsNull (task.AsyncState, "#2");
569                         Assert.IsTrue (task.Wait (5000), "#3");
570                         Assert.IsTrue (called, "#4");
571                         Assert.IsTrue (scheduler.ExecutedInline, "#5");
572                 }
573
574                 [Test]
575                 public void FromAsync_BeginCallback ()
576                 {
577                         bool called = false;
578                         bool called2 = false;
579
580                         var task = factory.FromAsync (
581                                 (a, b, c) => {
582                                         if (a != "h")
583                                                 Assert.Fail ("#10");
584
585                                         if ((TaskCreationOptions) c != TaskCreationOptions.AttachedToParent)
586                                                 Assert.Fail ("#11");
587
588                                         Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#12");
589
590                                         called2 = true;
591                                         b.Invoke (null);
592                                         return null;
593                                 },
594                                 l => {
595                                         called = true;
596                                 },
597                                 "h", TaskCreationOptions.AttachedToParent);
598
599                         Assert.AreEqual (TaskCreationOptions.None, task.CreationOptions, "#1");
600                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, (TaskCreationOptions) task.AsyncState, "#2");
601                         Assert.IsTrue (task.Wait (5000), "#3");
602                         Assert.IsTrue (called, "#4");
603                         Assert.IsTrue (called2, "#5");
604                 }
605
606                 [Test]
607                 public void StartNewCancelled ()
608                 {
609                         var ct = new CancellationToken (true);
610
611                         var task = factory.StartNew (() => Assert.Fail ("Should never be called"), ct);
612                         try {
613                                 task.Start ();
614                                 Assert.Fail ("#1");
615                         } catch (InvalidOperationException) {
616                         }
617
618                         try {
619                                 task.Wait ();
620                                 Assert.Fail ("#2");
621                         } catch (AggregateException e) {
622                                 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
623                         }
624
625                         Assert.IsTrue (task.IsCanceled, "#4");
626                 }
627         }
628 }
629 #endif