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