Update mcs/class/Commons.Xml.Relaxng/Commons.Xml.Relaxng/RelaxngPattern.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 || MOBILE
32
33 using System;
34 using System.Threading;
35 using System.Threading.Tasks;
36 using System.Collections.Generic;
37
38 using NUnit.Framework;
39
40 namespace MonoTests.System.Threading.Tasks
41 {
42         [TestFixture]
43         public class TaskFactoryTests
44         {
45                 class CompletedAsyncResult : IAsyncResult
46                 {
47                         public object AsyncState
48                         {
49                                 get { throw new NotImplementedException (); }
50                         }
51
52                         public WaitHandle AsyncWaitHandle
53                         {
54                                 get { throw new NotImplementedException (); }
55                         }
56
57                         public bool CompletedSynchronously
58                         {
59                                 get { throw new NotImplementedException (); }
60                         }
61
62                         public bool IsCompleted
63                         {
64                                 get { return true; }
65                         }
66                 }
67
68                 class TestAsyncResult : IAsyncResult
69                 {
70                         WaitHandle wh = new ManualResetEvent (true);
71
72                         public object AsyncState
73                         {
74                                 get { throw new NotImplementedException (); }
75                         }
76
77                         public WaitHandle AsyncWaitHandle
78                         {
79                                 get
80                                 {
81                                         return wh;
82                                 }
83                         }
84
85                         public bool CompletedSynchronously
86                         {
87                                 get { throw new NotImplementedException (); }
88                         }
89
90                         public bool IsCompleted
91                         {
92                                 get { return false; }
93                         }
94                 }
95
96                 class TestScheduler : TaskScheduler
97                 {
98                         public bool ExecutedInline { get; set; }
99
100                         protected override void QueueTask (Task task)
101                         {
102                                 throw new NotImplementedException ();
103                         }
104
105                         protected override bool TryDequeue (Task task)
106                         {
107                                 throw new NotImplementedException ();
108                         }
109
110                         protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
111                         {
112                                 if (taskWasPreviouslyQueued)
113                                         throw new ArgumentException ("taskWasPreviouslyQueued");
114
115                                 if (task.Status != TaskStatus.WaitingToRun)
116                                         throw new ArgumentException ("task.Status");
117
118                                 ExecutedInline = true;
119                                 return TryExecuteTask (task);
120                         }
121
122                         protected override IEnumerable<Task> GetScheduledTasks ()
123                         {
124                                 throw new NotImplementedException ();
125                         }
126                 }
127
128
129                 TaskFactory factory;
130
131                 [SetUp]
132                 public void Setup ()
133                 {
134                         this.factory = Task.Factory;
135                 }
136
137                 [Test]
138                 public void StartNewTest ()
139                 {
140                         bool result = false;
141                         factory.StartNew (() => result = true).Wait ();
142                         Assert.IsTrue (result);
143                 }
144
145                 [Test]
146                 public void NoDefaultScheduler ()
147                 {
148                         Assert.IsNull (factory.Scheduler, "#1");
149                 }
150
151                 [Test]
152                 public void ContinueWhenAll_Simple ()
153                 {
154                         var mre = new ManualResetEventSlim (false);
155
156                         Task[] tasks = new Task[3];
157                         tasks[0] = new Task (() => { Thread.Sleep (0); Assert.IsTrue (mre.Wait (3000)); });
158                         tasks[1] = new Task (() => { Assert.IsTrue (mre.Wait (3000)); });
159                         tasks[2] = new Task (() => { Assert.IsTrue (mre.Wait (3000)); });
160
161                         bool ran = false;
162                         Task cont = factory.ContinueWhenAll (tasks, ts => {
163                                 Assert.AreEqual (tasks, ts, "#0");
164                                 ran = true;
165                         });
166
167                         foreach (Task t in tasks)
168                                 t.Start ();
169
170                         mre.Set ();
171
172                         Assert.IsTrue (cont.Wait (1000), "#1");
173                         Assert.IsTrue (ran, "#2");
174                 }
175
176                 [Test]
177                 public void ContinueWhenAll_WithMixedCompletionState ()
178                 {
179                         var mre = new ManualResetEventSlim ();
180                         var task = Task.Factory.StartNew (() => mre.Wait (200));
181                         var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
182                         var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
183                         var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
184                         bool ran = false;
185
186                         var cont = Task.Factory.ContinueWhenAll (new Task[] { contFailed, contCanceled, contSuccess }, _ => ran = true);
187
188                         mre.Set ();
189                         cont.Wait (200);
190
191                         Assert.IsTrue (ran);
192                         Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
193                 }
194
195                 [Test]
196                 public void ContinueWhenAll_InvalidArguments ()
197                 {
198                         try {
199                                 factory.ContinueWhenAll (null, delegate { });
200                                 Assert.Fail ("#1");
201                         } catch (ArgumentNullException) {
202                         }
203
204                         try {
205                                 factory.ContinueWhenAll (new Task[0], delegate { });
206                                 Assert.Fail ("#2");
207                         } catch (ArgumentException) {
208                         }
209
210                         try {
211                                 factory.ContinueWhenAll (new Task[] { null }, delegate { });
212                                 Assert.Fail ("#3");
213                         } catch (ArgumentException) {
214                         }
215
216                         var tasks = new Task [] {
217                                 factory.StartNew (delegate {})
218                         };
219
220                         try {
221                                 factory.ContinueWhenAll (tasks, null);
222                                 Assert.Fail ("#4");
223                         } catch (ArgumentException) {
224                         }
225
226                         try {
227                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
228                                 Assert.Fail ("#5");
229                         } catch (ArgumentException) {
230                         }
231
232                         try {
233                                 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
234                                 Assert.Fail ("#6");
235                         } catch (ArgumentException) {
236                         }
237                 }
238
239                 [Test]
240                 public void ContinueWhenAny_Simple ()
241                 {
242                         var t1 = new ManualResetEvent (false);
243                         var t2 = new ManualResetEvent (false);
244
245                         var tasks = new Task[2] {
246                                 Task.Factory.StartNew (() => { t1.WaitOne (3000); }),
247                                 Task.Factory.StartNew (() => { t2.WaitOne (3000); })
248                         };
249
250                         bool ran = false;
251                         var ct = new CancellationToken ();
252                         Task cont = factory.ContinueWhenAny (tasks, t => {
253                                 Assert.AreEqual (tasks[0], t, "#1");
254                                 ran = true;
255                         }, ct);
256
257                         Assert.AreEqual (TaskStatus.WaitingForActivation, cont.Status, "#2");
258
259                         t1.Set ();
260
261                         Assert.IsTrue (cont.Wait (2000), "#10");
262                         Assert.IsTrue (ran, "#11");
263
264                         t2.Set ();
265                 }
266
267                 [Test]
268                 public void ContinueWhenAny_InvalidArguments ()
269                 {
270                         try {
271                                 factory.ContinueWhenAny (null, delegate { });
272                                 Assert.Fail ("#1");
273                         } catch (ArgumentNullException) {
274                         }
275
276                         try {
277                                 factory.ContinueWhenAny (new Task[0], delegate { });
278                                 Assert.Fail ("#2");
279                         } catch (ArgumentException) {
280                         }
281
282                         try {
283                                 factory.ContinueWhenAny (new Task[] { null }, delegate { });
284                                 Assert.Fail ("#3");
285                         } catch (ArgumentException) {
286                         }
287
288                         var tasks = new Task [] {
289                                 factory.StartNew (delegate {})
290                         };
291
292                         try {
293                                 factory.ContinueWhenAny (tasks, null);
294                                 Assert.Fail ("#4");
295                         } catch (ArgumentException) {
296                         }
297
298                         try {
299                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
300                                 Assert.Fail ("#5");
301                         } catch (ArgumentException) {
302                         }
303
304                         try {
305                                 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
306                                 Assert.Fail ("#6");
307                         } catch (ArgumentException) {
308                         }
309                 }
310
311                 [Test]
312                 public void FromAsyncBeginInvoke_WithResult ()
313                 {
314                         bool result = false;
315
316                         Func<int, int> func = (i) => {
317                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread);
318                                 result = true; return i + 3;
319                         };
320
321                         var task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, "state", TaskCreationOptions.AttachedToParent);
322                         Assert.IsTrue (task.Wait (5000), "#1");
323                         Assert.IsTrue (result, "#2");
324                         Assert.AreEqual (4, task.Result, "#3");
325                         Assert.AreEqual ("state", (string) task.AsyncState, "#4");
326                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#5");
327                 }
328
329                 [Test]
330                 public void FromAsyncBeginMethod_DirectResult ()
331                 {
332                         bool result = false;
333                         bool continuationTest = false;
334
335                         Func<int, int> func = (i) => { result = true; return i + 3; };
336                         Task<int> task = factory.FromAsync<int> (func.BeginInvoke (1, delegate { }, null), func.EndInvoke);
337                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
338                         task.Wait ();
339                         cont.Wait ();
340
341                         Assert.IsTrue (result);
342                         Assert.IsTrue (continuationTest);
343                         Assert.AreEqual (4, task.Result);
344                 }
345
346                 [Test]
347                 public void FromAsyncBeginMethod_Exception ()
348                 {
349                         bool result = false;
350                         bool continuationTest = false;
351
352                         Func<int, int> func = (i) => { result = true; throw new ApplicationException ("bleh"); };
353                         Task<int> task = factory.FromAsync<int, int> (func.BeginInvoke, func.EndInvoke, 1, null);
354                         var cont = task.ContinueWith (_ => continuationTest = true, TaskContinuationOptions.ExecuteSynchronously);
355                         try {
356                                 task.Wait ();
357                         } catch { }
358                         cont.Wait ();
359
360                         Assert.IsTrue (result);
361                         Assert.IsTrue (continuationTest);
362                         Assert.IsNotNull (task.Exception);
363                         var agg = task.Exception;
364                         Assert.AreEqual (1, agg.InnerExceptions.Count);
365                         Assert.IsInstanceOfType (typeof (ApplicationException), agg.InnerExceptions[0]);
366                         Assert.AreEqual (TaskStatus.Faulted, task.Status);
367
368                         try {
369                                 var a = task.Result;
370                                 Assert.Fail ();
371                         } catch (AggregateException) {
372                         }
373                 }
374
375                 [Test]
376                 public void FromAsync_ArgumentsCheck ()
377                 {
378                         var result = new CompletedAsyncResult ();
379                         try {
380                                 factory.FromAsync (null, l => { });
381                                 Assert.Fail ("#1");
382                         } catch (ArgumentNullException) {
383                         }
384
385                         try {
386                                 factory.FromAsync (result, null);
387                                 Assert.Fail ("#2");
388                         } catch (ArgumentNullException) {
389                         }
390
391                         try {
392                                 factory.FromAsync (result, l => { }, TaskCreationOptions.LongRunning);
393                                 Assert.Fail ("#3");
394                         } catch (ArgumentOutOfRangeException) {
395                         }
396
397                         try {
398                                 factory.FromAsync (result, l => { }, TaskCreationOptions.PreferFairness);
399                                 Assert.Fail ("#4");
400                         } catch (ArgumentOutOfRangeException) {
401                         }
402
403                         try {
404                                 factory.FromAsync (result, l => { }, TaskCreationOptions.None, null);
405                                 Assert.Fail ("#5");
406                         } catch (ArgumentNullException) {
407                         }
408
409                         try {
410                                 factory.FromAsync (null, l => { }, null, TaskCreationOptions.None);
411                                 Assert.Fail ("#6");
412                         } catch (ArgumentNullException) {
413                         }
414
415                         try {
416                                 factory.FromAsync ((a, b) => null, l => { }, null, TaskCreationOptions.LongRunning);
417                                 Assert.Fail ("#7");
418                         } catch (ArgumentOutOfRangeException) {
419                         }
420                 }
421
422                 [Test]
423                 public void FromAsync_Completed ()
424                 {
425                         var completed = new CompletedAsyncResult ();
426                         bool? valid = null;
427
428                         Action<IAsyncResult> end = l => {
429                                 Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#2");
430                                 valid = l == completed;
431                         };
432                         Task task = factory.FromAsync (completed, end);
433                         Assert.IsTrue (valid == true, "#1");
434                 }
435
436                 [Test]
437                 public void FromAsync_CompletedWithException ()
438                 {
439                         var completed = new CompletedAsyncResult ();
440
441                         Action<IAsyncResult> end = l => {
442                                 throw new ApplicationException ();
443                         };
444                         Task task = factory.FromAsync (completed, end);
445                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#1");
446                 }
447
448                 [Test]
449                 public void FromAsync_CompletedCanceled ()
450                 {
451                         var completed = new CompletedAsyncResult ();
452
453                         Action<IAsyncResult> end = l => {
454                                 throw new OperationCanceledException ();
455                         };
456                         Task task = factory.FromAsync (completed, end);
457                         Assert.AreEqual (TaskStatus.Canceled, task.Status, "#1");
458                         Assert.IsNull (task.Exception, "#2");
459                 }
460
461                 [Test]
462                 public void FromAsync_SimpleAsyncResult ()
463                 {
464                         var result = new TestAsyncResult ();
465                         bool called = false;
466
467                         var task = factory.FromAsync (result, l => {
468                                 called = true;
469                         });
470
471                         Assert.IsTrue (task.Wait (1000), "#1");
472                         Assert.IsTrue (called, "#2");
473                 }
474
475                 [Test]
476                 public void FromAsync_ResultException ()
477                 {
478                         var result = new TestAsyncResult ();
479
480                         var task = factory.FromAsync (result, l => {
481                                 throw new ApplicationException ();
482                         });
483
484                         try {
485                                 Assert.IsFalse (task.Wait (1000), "#1");
486                         } catch (AggregateException) {
487                         }
488
489                         Assert.AreEqual (TaskStatus.Faulted, task.Status, "#2");
490                 }
491
492                 [Test]
493                 public void FromAsync_ReturnInt ()
494                 {
495                         var result = new TestAsyncResult ();
496                         bool called = false;
497
498                         var task = factory.FromAsync<int> (result, l => {
499                                 called = true;
500                                 return 4;
501                         });
502
503                         Assert.IsTrue (task.Wait (1000), "#1");
504                         Assert.IsTrue (called, "#2");
505                         Assert.AreEqual (4, task.Result, "#3");
506                 }
507
508                 [Test]
509                 public void FromAsync_Scheduler_Explicit ()
510                 {
511                         var result = new TestAsyncResult ();
512                         bool called = false;
513                         var scheduler = new TestScheduler ();
514
515                         var task = factory.FromAsync (result, l => {
516                                 called = true;
517                         }, TaskCreationOptions.None, scheduler);
518
519                         Assert.IsTrue (task.Wait (5000), "#1");
520                         Assert.IsTrue (called, "#2");
521                         Assert.IsTrue (scheduler.ExecutedInline, "#3");
522                 }
523
524                 [Test]
525                 public void FromAsync_Scheduler_Implicit ()
526                 {
527                         var result = new TestAsyncResult ();
528                         bool called = false;
529                         var scheduler = new TestScheduler ();
530
531                         factory = new TaskFactory (scheduler);
532
533                         Task task = factory.FromAsync (result, l => {
534                                 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread, "#6");
535                                 called = true;
536                         }, TaskCreationOptions.AttachedToParent);
537
538                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#1");
539                         Assert.IsNull (task.AsyncState, "#2");
540                         Assert.IsTrue (task.Wait (5000), "#3");
541                         Assert.IsTrue (called, "#4");
542                         Assert.IsTrue (scheduler.ExecutedInline, "#5");
543                 }
544
545                 [Test]
546                 public void FromAsync_BeginCallback ()
547                 {
548                         bool called = false;
549                         bool called2 = false;
550
551                         var task = factory.FromAsync (
552                                 (a, b, c) => {
553                                         if (a != "h")
554                                                 Assert.Fail ("#10");
555
556                                         if ((TaskCreationOptions) c != TaskCreationOptions.AttachedToParent)
557                                                 Assert.Fail ("#11");
558
559                                         Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#12");
560
561                                         called2 = true;
562                                         b.Invoke (null);
563                                         return null;
564                                 },
565                                 l => {
566                                         called = true;
567                                 },
568                                 "h", TaskCreationOptions.AttachedToParent);
569
570                         Assert.AreEqual (TaskCreationOptions.None, task.CreationOptions, "#1");
571                         Assert.AreEqual (TaskCreationOptions.AttachedToParent, (TaskCreationOptions) task.AsyncState, "#2");
572                         Assert.IsTrue (task.Wait (5000), "#3");
573                         Assert.IsTrue (called, "#4");
574                         Assert.IsTrue (called2, "#5");
575                 }
576
577                 [Test]
578                 public void StartNewCancelled ()
579                 {
580                         var cts = new CancellationTokenSource ();
581                         cts.Cancel ();
582
583                         var task = factory.StartNew (() => Assert.Fail ("Should never be called"), cts.Token);
584                         try {
585                                 task.Start ();
586                         } catch (InvalidOperationException) {
587                         }
588
589                         Assert.IsTrue (task.IsCanceled, "#2");
590                 }
591         }
592 }
593 #endif