[corlib] CoreRT System.Threading.Tasks (#6672)
[mono-project.git] / mcs / class / corlib / Test / System.Threading.Tasks / TaskFactoryTest.cs
blob973ec1ff4668c06c83660156f0d8deb87999738a
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)
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:
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
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.
32 using System;
33 using System.Threading;
34 using System.Threading.Tasks;
35 using System.Collections.Generic;
37 using NUnit.Framework;
39 namespace MonoTests.System.Threading.Tasks
41 [TestFixture]
42 public class TaskFactoryTests
44 class CompletedAsyncResult : IAsyncResult
46 public object AsyncState
48 get { throw new NotImplementedException (); }
51 public WaitHandle AsyncWaitHandle
53 get { throw new NotImplementedException (); }
56 public bool CompletedSynchronously
58 get { throw new NotImplementedException (); }
61 public bool IsCompleted
63 get { return true; }
67 class TestAsyncResult : IAsyncResult
69 WaitHandle wh = new ManualResetEvent (true);
71 public object AsyncState
73 get { throw new NotImplementedException (); }
76 public WaitHandle AsyncWaitHandle
78 get
80 return wh;
84 public bool CompletedSynchronously
86 get { throw new NotImplementedException (); }
89 public bool IsCompleted
91 get { return false; }
95 class TestScheduler : TaskScheduler
97 public bool ExecutedInline { get; set; }
99 protected override void QueueTask (Task task)
101 throw new NotImplementedException ();
104 protected override bool TryDequeue (Task task)
106 throw new NotImplementedException ();
109 protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
111 if (taskWasPreviouslyQueued)
112 throw new ArgumentException ("taskWasPreviouslyQueued");
114 if (task.Status != TaskStatus.WaitingToRun)
115 throw new ArgumentException ("task.Status");
117 ExecutedInline = true;
118 return TryExecuteTask (task);
121 protected override IEnumerable<Task> GetScheduledTasks ()
123 throw new NotImplementedException ();
128 TaskFactory factory;
130 [SetUp]
131 public void Setup ()
133 this.factory = Task.Factory;
136 [Test]
137 public void StartNewTest ()
139 bool result = false;
140 factory.StartNew (() => result = true).Wait ();
141 Assert.IsTrue (result);
144 [Test]
145 public void NoDefaultScheduler ()
147 Assert.IsNull (factory.Scheduler, "#1");
150 [Test]
151 public void ContinueWhenAll_Simple ()
153 var mre = new ManualResetEventSlim (false);
155 Task[] tasks = new Task[3];
156 tasks[0] = new Task (() => { Thread.Sleep (0); Assert.IsTrue (mre.Wait (5000)); });
157 tasks[1] = new Task (() => { Assert.IsTrue (mre.Wait (5000)); });
158 tasks[2] = new Task (() => { Assert.IsTrue (mre.Wait (5000)); });
160 bool ran = false;
161 Task cont = factory.ContinueWhenAll (tasks, ts => {
162 Assert.AreEqual (tasks, ts, "#0");
163 ran = true;
166 foreach (Task t in tasks)
167 t.Start ();
169 mre.Set ();
171 Assert.IsTrue (cont.Wait (3000), "#1");
172 Assert.IsTrue (ran, "#2");
175 [Test]
176 public void ContinueWhenAll_WithMixedCompletionState ()
178 var mre = new ManualResetEventSlim ();
179 var task = Task.Factory.StartNew (() => mre.Wait (1000));
180 var contFailed = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnFaulted);
181 var contCanceled = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnCanceled);
182 var contSuccess = task.ContinueWith (t => {}, TaskContinuationOptions.OnlyOnRanToCompletion);
183 bool ran = false;
185 var cont = Task.Factory.ContinueWhenAll (new Task[] { contFailed, contCanceled, contSuccess }, _ => ran = true);
187 mre.Set ();
188 cont.Wait (3000);
190 Assert.IsTrue (ran);
191 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
194 [Test]
195 public void ContinueWhenAll_InvalidArguments ()
197 try {
198 factory.ContinueWhenAll (null, delegate { });
199 Assert.Fail ("#1");
200 } catch (ArgumentNullException) {
203 try {
204 factory.ContinueWhenAll (new Task[0], delegate { });
205 Assert.Fail ("#2");
206 } catch (ArgumentException) {
209 try {
210 factory.ContinueWhenAll (new Task[] { null }, delegate { });
211 Assert.Fail ("#3");
212 } catch (ArgumentException) {
215 var tasks = new Task [] {
216 factory.StartNew (delegate {})
219 try {
220 factory.ContinueWhenAll (tasks, null);
221 Assert.Fail ("#4");
222 } catch (ArgumentNullException) {
225 try {
226 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
227 Assert.Fail ("#5");
228 } catch (ArgumentNullException) {
231 try {
232 factory.ContinueWhenAll (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
233 Assert.Fail ("#6");
234 } catch (ArgumentNullException) {
235 } catch (ArgumentOutOfRangeException) {
239 [Test]
240 public void ContinueWhenAll_WithExceptions ()
242 var t1 = Task.Factory.StartNew (() => { throw new ApplicationException ("Foo"); });
243 var t2 = Task.Factory.StartNew (() => { throw new ApplicationException ("Bar"); });
245 var cont = Task.Factory.ContinueWhenAll (new[] { t1, t2 }, delegate {});
246 cont.Wait (200);
248 Assert.IsTrue (t1.IsFaulted);
249 Assert.IsTrue (t2.IsFaulted);
250 Assert.AreEqual (TaskStatus.RanToCompletion, cont.Status);
253 [Test]
254 public void ContinueWhenAny_Simple ()
256 var t1 = new ManualResetEvent (false);
257 var t2 = new ManualResetEvent (false);
259 var tasks = new Task[2] {
260 Task.Factory.StartNew (() => { t1.WaitOne (5000); }),
261 Task.Factory.StartNew (() => { t2.WaitOne (5000); })
264 bool ran = false;
265 var ct = new CancellationToken ();
266 Task cont = factory.ContinueWhenAny (tasks, t => {
267 Assert.AreEqual (tasks[0], t, "#1");
268 ran = true;
269 }, ct);
271 Assert.AreEqual (TaskStatus.WaitingForActivation, cont.Status, "#2");
273 t1.Set ();
275 Assert.IsTrue (cont.Wait (3000), "#10");
276 Assert.IsTrue (ran, "#11");
278 t2.Set ();
281 [Test]
282 public void ContinueWhenAny_WithResult ()
284 var tcs = new TaskCompletionSource<int>();
285 tcs.SetResult(1);
286 Task[] tasks = new[] { tcs.Task };
287 var res = Task.Factory.ContinueWhenAny (tasks, l => 4);
288 Assert.AreEqual (4, res.Result);
291 [Test]
292 public void ContinueWhenAny_InvalidArguments ()
294 try {
295 factory.ContinueWhenAny (null, delegate { });
296 Assert.Fail ("#1");
297 } catch (ArgumentNullException) {
300 try {
301 factory.ContinueWhenAny (new Task[0], delegate { });
302 Assert.Fail ("#2");
303 } catch (ArgumentException) {
306 try {
307 factory.ContinueWhenAny (new Task[] { null }, delegate { });
308 Assert.Fail ("#3");
309 } catch (ArgumentException) {
312 var tasks = new Task [] {
313 factory.StartNew (delegate {})
316 try {
317 factory.ContinueWhenAny (tasks, null);
318 Assert.Fail ("#4");
319 } catch (ArgumentNullException) {
322 try {
323 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.None, null);
324 Assert.Fail ("#5");
325 } catch (ArgumentNullException) {
328 try {
329 factory.ContinueWhenAny (tasks, delegate { }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, null);
330 Assert.Fail ("#6");
331 } catch (ArgumentNullException) {
332 } catch (ArgumentOutOfRangeException) {
336 [Test]
337 public void FromAsyncBeginInvoke_WithResult ()
339 bool result = false;
341 Func<int, int> func = (i) => {
342 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread);
343 result = true; return i + 3;
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");
354 [Test]
355 public void FromAsyncBeginMethod_DirectResult ()
357 bool result = false;
358 bool continuationTest = false;
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 ();
366 Assert.IsTrue (result);
367 Assert.IsTrue (continuationTest);
368 Assert.AreEqual (4, task.Result);
371 [Test]
372 public void FromAsyncBeginMethod_Exception ()
374 bool result = false;
375 bool continuationTest = false;
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");
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);
393 try {
394 var a = task.Result;
395 Assert.Fail ();
396 } catch (AggregateException) {
400 [Test]
401 public void FromAsync_ArgumentsCheck ()
403 var result = new CompletedAsyncResult ();
404 try {
405 factory.FromAsync (null, l => { });
406 Assert.Fail ("#1");
407 } catch (ArgumentNullException) {
410 try {
411 factory.FromAsync (result, null);
412 Assert.Fail ("#2");
413 } catch (ArgumentNullException) {
416 try {
417 factory.FromAsync (result, l => { }, TaskCreationOptions.LongRunning);
418 Assert.Fail ("#3");
419 } catch (ArgumentOutOfRangeException) {
422 try {
423 factory.FromAsync (result, l => { }, TaskCreationOptions.PreferFairness);
424 Assert.Fail ("#4");
425 } catch (ArgumentOutOfRangeException) {
428 try {
429 factory.FromAsync (result, l => { }, TaskCreationOptions.None, null);
430 Assert.Fail ("#5");
431 } catch (ArgumentNullException) {
434 try {
435 factory.FromAsync (null, l => { }, null, TaskCreationOptions.None);
436 Assert.Fail ("#6");
437 } catch (ArgumentNullException) {
440 try {
441 factory.FromAsync ((a, b) => null, l => { }, null, TaskCreationOptions.LongRunning);
442 Assert.Fail ("#7");
443 } catch (ArgumentOutOfRangeException) {
447 [Test]
448 [Category ("MacNotWorking")] // Randomly fails - https://bugzilla.xamarin.com/show_bug.cgi?id=51255
449 public void FromAsync_Completed ()
451 var completed = new CompletedAsyncResult ();
452 bool? valid = null;
454 Action<IAsyncResult> end = l => {
455 Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#2");
456 valid = l == completed;
458 Task task = factory.FromAsync (completed, end);
459 Assert.IsTrue (valid == true, "#1");
462 [Test]
463 public void FromAsync_CompletedWithException ()
465 var completed = new CompletedAsyncResult ();
467 Action<IAsyncResult> end = l => {
468 throw new ApplicationException ();
470 Task task = factory.FromAsync (completed, end);
471 Assert.AreEqual (TaskStatus.Faulted, task.Status, "#1");
474 [Test]
475 public void FromAsync_CompletedCanceled ()
477 var completed = new CompletedAsyncResult ();
479 Action<IAsyncResult> end = l => {
480 throw new OperationCanceledException ();
482 Task task = factory.FromAsync (completed, end);
483 Assert.AreEqual (TaskStatus.Canceled, task.Status, "#1");
484 Assert.IsNull (task.Exception, "#2");
487 [Test]
488 public void FromAsync_SimpleAsyncResult ()
490 var result = new TestAsyncResult ();
491 bool called = false;
493 var task = factory.FromAsync (result, l => {
494 called = true;
497 Assert.IsTrue (task.Wait (1000), "#1");
498 Assert.IsTrue (called, "#2");
501 [Test]
502 public void FromAsync_ResultException ()
504 var result = new TestAsyncResult ();
506 var task = factory.FromAsync (result, l => {
507 throw new ApplicationException ();
510 try {
511 Assert.IsFalse (task.Wait (1000), "#1");
512 } catch (AggregateException) {
515 Assert.AreEqual (TaskStatus.Faulted, task.Status, "#2");
518 [Test]
519 public void FromAsync_ReturnInt ()
521 var result = new TestAsyncResult ();
522 bool called = false;
524 var task = factory.FromAsync<int> (result, l => {
525 called = true;
526 return 4;
529 Assert.IsTrue (task.Wait (1000), "#1");
530 Assert.IsTrue (called, "#2");
531 Assert.AreEqual (4, task.Result, "#3");
534 [Test]
535 public void FromAsync_Scheduler_Explicit ()
537 var result = new TestAsyncResult ();
538 bool called = false;
539 var scheduler = new TestScheduler ();
541 var task = factory.FromAsync (result, l => {
542 called = true;
543 }, TaskCreationOptions.None, scheduler);
545 Assert.IsTrue (task.Wait (5000), "#1");
546 Assert.IsTrue (called, "#2");
547 Assert.IsTrue (scheduler.ExecutedInline, "#3");
550 [Test]
551 public void FromAsync_Scheduler_Implicit ()
553 var result = new TestAsyncResult ();
554 bool called = false;
555 var scheduler = new TestScheduler ();
557 factory = new TaskFactory (scheduler);
559 Task task = factory.FromAsync (result, l => {
560 Assert.IsTrue (Thread.CurrentThread.IsThreadPoolThread, "#6");
561 called = true;
562 }, TaskCreationOptions.AttachedToParent);
564 Assert.AreEqual (TaskCreationOptions.AttachedToParent, task.CreationOptions, "#1");
565 Assert.IsNull (task.AsyncState, "#2");
566 Assert.IsTrue (task.Wait (5000), "#3");
567 Assert.IsTrue (called, "#4");
568 Assert.IsTrue (scheduler.ExecutedInline, "#5");
571 [Test]
572 public void FromAsync_BeginCallback ()
574 bool called = false;
575 bool called2 = false;
577 var task = factory.FromAsync (
578 (a, b, c) => {
579 if (a != "h")
580 Assert.Fail ("#10");
582 if ((TaskCreationOptions) c != TaskCreationOptions.AttachedToParent)
583 Assert.Fail ("#11");
585 Assert.IsFalse (Thread.CurrentThread.IsThreadPoolThread, "#12");
587 called2 = true;
588 var ar = Task.CompletedTask;
589 b.Invoke (ar);
590 return ar;
592 l => {
593 called = true;
595 "h", TaskCreationOptions.AttachedToParent);
597 Assert.AreEqual (TaskCreationOptions.None, task.CreationOptions, "#1");
598 Assert.AreEqual (TaskCreationOptions.AttachedToParent, (TaskCreationOptions) task.AsyncState, "#2");
599 Assert.IsTrue (task.Wait (5000), "#3");
600 Assert.IsTrue (called, "#4");
601 Assert.IsTrue (called2, "#5");
604 [Test]
605 public void StartNewCancelled ()
607 var ct = new CancellationToken (true);
609 var task = factory.StartNew (() => Assert.Fail ("Should never be called"), ct);
610 try {
611 task.Start ();
612 Assert.Fail ("#1");
613 } catch (InvalidOperationException) {
616 try {
617 task.Wait ();
618 Assert.Fail ("#2");
619 } catch (AggregateException e) {
620 Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
623 Assert.IsTrue (task.IsCanceled, "#4");