Update PointConverter.cs
[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 (3000)); });
161                         tasks[1] = new Task (() => { Assert.IsTrue (mre.Wait (3000)); });
162                         tasks[2] = new Task (() => { Assert.IsTrue (mre.Wait (3000)); });
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 (1000), "#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 (200));
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 (200);
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 (ArgumentException) {
227                         }
228
229                         try {
230                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
231                                 Assert.Fail ("#5");
232                         } catch (ArgumentException) {
233                         }
234
235                         try {
236                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
237                                 Assert.Fail ("#6");
238                         } catch (ArgumentException) {
239                         }
240                 }
241
242                 [Test]
243                 public void ContinueWhenAll_WithExceptions ()
244                 {
245                         var t1 = Task.Factory.StartNew (() => { throw new ApplicationException ("Foo"); });
246                         var t2 = Task.Factory.StartNew (() => { throw new ApplicationException ("Bar"); });
247
248                         var cont = Task.Factory.ContinueWhenAll (new[] { t1, t2 }, delegate {});
249                         cont.Wait (200);
250
251                         Assert.IsTrue (t1.IsFaulted);
252                         Assert.IsTrue (t2.IsFaulted);
253                         Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
254                 }
255
256                 [Test]
257                 public void ContinueWhenAny_Simple ()
258                 {
259                         var t1 = new ManualResetEvent (false);
260                         var t2 = new ManualResetEvent (false);
261
262                         var tasks = new Task[2] {
263                                 Task.Factory.StartNew (() => { t1.WaitOne (3000); }),
264                                 Task.Factory.StartNew (() => { t2.WaitOne (3000); })
265                         };
266
267                         bool ran = false;
268                         var ct = new CancellationToken ();
269                         Task cont = factory.ContinueWhenAny (tasks, t => {
270                                 Assert.AreEqual (tasks[0], t, "#1");
271                                 ran = true;
272                         }, ct);
273
274                         Assert.AreEqual (TaskStatus.WaitingForActivation, cont.Status, "#2");
275
276                         t1.Set ();
277
278                         Assert.IsTrue (cont.Wait (2000), "#10");
279                         Assert.IsTrue (ran, "#11");
280
281                         t2.Set ();
282                 }
283
284                 [Test]
285                 public void ContinueWhenAny_InvalidArguments ()
286                 {
287                         try {
288                                 factory.ContinueWhenAny (null, delegate { });
289                                 Assert.Fail ("#1");
290                         } catch (ArgumentNullException) {
291                         }
292
293                         try {
294                                 factory.ContinueWhenAny (new Task[0], delegate { });
295                                 Assert.Fail ("#2");
296                         } catch (ArgumentException) {
297                         }
298
299                         try {
300                                 factory.ContinueWhenAny (new Task[] { null }, delegate { });
301                                 Assert.Fail ("#3");
302                         } catch (ArgumentException) {
303                         }
304
305                         var tasks = new Task [] {
306                                 factory.StartNew (delegate {})
307                         };
308
309                         try {
310                                 factory.ContinueWhenAny (tasks, null);
311                                 Assert.Fail ("#4");
312                         } catch (ArgumentException) {
313                         }
314
315                         try {
316                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
317                                 Assert.Fail ("#5");
318                         } catch (ArgumentException) {
319                         }
320
321                         try {
322                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
323                                 Assert.Fail ("#6");
324                         } catch (ArgumentException) {
325                         }
326                 }
327
328                 [Test]
329                 public void FromAsyncBeginInvoke_WithResult ()
330                 {
331                         bool result = false;
332
333                         Func<int, int> func = (i) => {
334                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread);
335                                 result = true; return i + 3;
336                         };
337
338                         var task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, "state", TaskCreationOptions.AttachedToParent);
339                         Assert.IsTrue (task.Wait (5000), "#1");
340                         Assert.IsTrue (result, "#2");
341                         Assert.AreEqual (4, task.Result, "#3");
342                         Assert.AreEqual ("state", (string) task.AsyncState, "#4");
343                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#5");
344                 }
345
346                 [Test]
347                 public void FromAsyncBeginMethod_DirectResult ()
348                 {
349                         bool result = false;
350                         bool continuationTest = false;
351
352                         Func<int, int> func = (i) => { result = true; return i + 3; };
353                         Task<int> task = factory.FromAsync<int> (func.BeginInvoke (1, delegate { }, null), func.EndInvoke);
354                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
355                         task.Wait ();
356                         cont.Wait ();
357
358                         Assert.IsTrue (result);
359                         Assert.IsTrue (continuationTest);
360                         Assert.AreEqual (4, task.Result);
361                 }
362
363                 [Test]
364                 public void FromAsyncBeginMethod_Exception ()
365                 {
366                         bool result = false;
367                         bool continuationTest = false;
368
369                         Func<int, int> func = (i) => { result = true; throw new ApplicationException ("bleh"); };
370                         Task<int> task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, null);
371                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
372                         try {
373                                 task.Wait (2000);
374                         } catch { }
375                         Assert.IsTrue (cont.Wait (2000), "#1");
376
377                         Assert.IsTrue (result);
378                         Assert.IsTrue (continuationTest);
379                         Assert.IsNotNull (task.Exception);
380                         var agg = task.Exception;
381                         Assert.AreEqual (1, agg.InnerExceptions.Count);
382                         Assert.That (agg.InnerExceptions[0], Is.TypeOf (typeof (ApplicationException)));
383                         Assert.AreEqual (TaskStatus.Faulted, task.Status);
384
385                         try {
386                                 var a = task.Result;
387                                 Assert.Fail ();
388                         } catch (AggregateException) {
389                         }
390                 }
391
392                 [Test]
393                 public void FromAsync_ArgumentsCheck ()
394                 {
395                         var result = new CompletedAsyncResult ();
396                         try {
397                                 factory.FromAsync (null, l => { });
398                                 Assert.Fail ("#1");
399                         } catch (ArgumentNullException) {
400                         }
401
402                         try {
403                                 factory.FromAsync (result, null);
404                                 Assert.Fail ("#2");
405                         } catch (ArgumentNullException) {
406                         }
407
408                         try {
409                                 factory.FromAsync (result, l => { }, TaskCreationOptions.LongRunning);
410                                 Assert.Fail ("#3");
411                         } catch (ArgumentOutOfRangeException) {
412                         }
413
414                         try {
415                                 factory.FromAsync (result, l => { }, TaskCreationOptions.PreferFairness);
416                                 Assert.Fail ("#4");
417                         } catch (ArgumentOutOfRangeException) {
418                         }
419
420                         try {
421                                 factory.FromAsync (result, l => { }, TaskCreationOptions.None, null);
422                                 Assert.Fail ("#5");
423                         } catch (ArgumentNullException) {
424                         }
425
426                         try {
427                                 factory.FromAsync (null, l => { }, null, TaskCreationOptions.None);
428                                 Assert.Fail ("#6");
429                         } catch (ArgumentNullException) {
430                         }
431
432                         try {
433                                 factory.FromAsync ((a, b) => null, l => { }, null, TaskCreationOptions.LongRunning);
434                                 Assert.Fail ("#7");
435                         } catch (ArgumentOutOfRangeException) {
436                         }
437                 }
438
439                 [Test]
440                 public void FromAsync_Completed ()
441                 {
442                         var completed = new CompletedAsyncResult ();
443                         bool? valid = null;
444
445                         Action<IAsyncResult> end = l => {
446                                 Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#2");
447                                 valid = l == completed;
448                         };
449                         Task task = factory.FromAsync (completed, end);
450                         Assert.IsTrue (valid == true, "#1");
451                 }
452
453                 [Test]
454                 public void FromAsync_CompletedWithException ()
455                 {
456                         var completed = new CompletedAsyncResult ();
457
458                         Action<IAsyncResult> end = l => {
459                                 throw new ApplicationException ();
460                         };
461                         Task task = factory.FromAsync (completed, end);
462                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#1");
463                 }
464
465                 [Test]
466                 public void FromAsync_CompletedCanceled ()
467                 {
468                         var completed = new CompletedAsyncResult ();
469
470                         Action<IAsyncResult> end = l => {
471                                 throw new OperationCanceledException ();
472                         };
473                         Task task = factory.FromAsync (completed, end);
474                         Assert.AreEqual (TaskStatus.Canceled, task.Status, "#1");
475                         Assert.IsNull (task.Exception, "#2");
476                 }
477
478                 [Test]
479                 public void FromAsync_SimpleAsyncResult ()
480                 {
481                         var result = new TestAsyncResult ();
482                         bool called = false;
483
484                         var task = factory.FromAsync (result, l => {
485                                 called = true;
486                         });
487
488                         Assert.IsTrue (task.Wait (1000), "#1");
489                         Assert.IsTrue (called, "#2");
490                 }
491
492                 [Test]
493                 public void FromAsync_ResultException ()
494                 {
495                         var result = new TestAsyncResult ();
496
497                         var task = factory.FromAsync (result, l => {
498                                 throw new ApplicationException ();
499                         });
500
501                         try {
502                                 Assert.IsFalse (task.Wait (1000), "#1");
503                         } catch (AggregateException) {
504                         }
505
506                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#2");
507                 }
508
509                 [Test]
510                 public void FromAsync_ReturnInt ()
511                 {
512                         var result = new TestAsyncResult ();
513                         bool called = false;
514
515                         var task = factory.FromAsync<int> (result, l => {
516                                 called = true;
517                                 return 4;
518                         });
519
520                         Assert.IsTrue (task.Wait (1000), "#1");
521                         Assert.IsTrue (called, "#2");
522                         Assert.AreEqual (4, task.Result, "#3");
523                 }
524
525                 [Test]
526                 public void FromAsync_Scheduler_Explicit ()
527                 {
528                         var result = new TestAsyncResult ();
529                         bool called = false;
530                         var scheduler = new TestScheduler ();
531
532                         var task = factory.FromAsync (result, l => {
533                                 called = true;
534                         }, TaskCreationOptions.None, scheduler);
535
536                         Assert.IsTrue (task.Wait (5000), "#1");
537                         Assert.IsTrue (called, "#2");
538                         Assert.IsTrue (scheduler.ExecutedInline, "#3");
539                 }
540
541                 [Test]
542                 public void FromAsync_Scheduler_Implicit ()
543                 {
544                         var result = new TestAsyncResult ();
545                         bool called = false;
546                         var scheduler = new TestScheduler ();
547
548                         factory = new TaskFactory (scheduler);
549
550                         Task task = factory.FromAsync (result, l => {
551                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread, "#6");
552                                 called = true;
553                         }, TaskCreationOptions.AttachedToParent);
554
555                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#1");
556                         Assert.IsNull (task.AsyncState, "#2");
557                         Assert.IsTrue (task.Wait (5000), "#3");
558                         Assert.IsTrue (called, "#4");
559                         Assert.IsTrue (scheduler.ExecutedInline, "#5");
560                 }
561
562                 [Test]
563                 public void FromAsync_BeginCallback ()
564                 {
565                         bool called = false;
566                         bool called2 = false;
567
568                         var task = factory.FromAsync (
569                                 (a, b, c) => {
570                                         if (a != "h")
571                                                 Assert.Fail ("#10");
572
573                                         if ((TaskCreationOptions) c != TaskCreationOptions.AttachedToParent)
574                                                 Assert.Fail ("#11");
575
576                                         Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#12");
577
578                                         called2 = true;
579                                         b.Invoke (null);
580                                         return null;
581                                 },
582                                 l => {
583                                         called = true;
584                                 },
585                                 "h", TaskCreationOptions.AttachedToParent);
586
587                         Assert.AreEqual (TaskCreationOptions.None, task.CreationOptions, "#1");
588                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, (TaskCreationOptions) task.AsyncState, "#2");
589                         Assert.IsTrue (task.Wait (5000), "#3");
590                         Assert.IsTrue (called, "#4");
591                         Assert.IsTrue (called2, "#5");
592                 }
593
594                 [Test]
595                 public void StartNewCancelled ()
596                 {
597                         var cts = new CancellationTokenSource ();
598                         cts.Cancel ();
599
600                         var task = factory.StartNew (() => Assert.Fail ("Should never be called"), cts.Token);
601                         try {
602                                 task.Start ();
603                         } catch (InvalidOperationException) {
604                         }
605
606                         Assert.IsTrue (task.IsCanceled, "#2");
607                 }
608         }
609 }
610 #endif