Merge pull request #901 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mcs / class / corlib / Test / System.Runtime.CompilerServices / TaskAwaiterTest.cs
index 9c07e125095e86bfac97535a02c1336a5d826af2..18b2099b8dd5fa9e00ff893ee5c6688648192ae8 100644 (file)
@@ -33,20 +33,51 @@ using System.Threading;
 using System.Threading.Tasks;
 using NUnit.Framework;
 using System.Runtime.CompilerServices;
+using System.Collections.Generic;
 
 namespace MonoTests.System.Runtime.CompilerServices
 {
        [TestFixture]
        public class TaskAwaiterTest
        {
-               Task task;
+               class Scheduler : TaskScheduler
+               {
+                       string name;
+
+                       public Scheduler (string name)
+                       {
+                               this.name = name;
+                       }
+
+                       public int InlineCalls { get; set; }
+                       public int QueueCalls { get; set; }
+
+                       protected override IEnumerable<Task> GetScheduledTasks ()
+                       {
+                               throw new NotImplementedException ();
+                       }
+
+                       protected override void QueueTask (Task task)
+                       {
+                               ++QueueCalls;
+                               ThreadPool.QueueUserWorkItem (o => {
+                                       TryExecuteTask (task);
+                               });
+                       }
+
+                       protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+                       {
+                               ++InlineCalls;
+                               return false;
+                       }
+               }
 
                [Test]
                public void GetResultFaulted ()
                {
                        TaskAwaiter awaiter;
 
-                       task = new Task (() => { throw new ApplicationException (); });
+                       var task = new Task (() => { throw new ApplicationException (); });
                        awaiter = task.GetAwaiter ();
                        task.RunSynchronously (TaskScheduler.Current);
 
@@ -61,34 +92,97 @@ namespace MonoTests.System.Runtime.CompilerServices
                }
 
                [Test]
-               public void GetResultNotCompleted ()
+               public void GetResultCanceled ()
                {
                        TaskAwaiter awaiter;
 
-                       task = new Task (() => { });
+                       var token = new CancellationToken (true);
+                       var task = new Task (() => { }, token);
                        awaiter = task.GetAwaiter ();
 
                        try {
                                awaiter.GetResult ();
                                Assert.Fail ();
-                       } catch (InvalidOperationException) {
+                       } catch (TaskCanceledException) {
                        }
                }
 
                [Test]
-               public void GetResultCanceled ()
+               public void GetResultWaitOnCompletion ()
                {
                        TaskAwaiter awaiter;
-
-                       var token = new CancellationToken (true);
-                       task = new Task (() => { }, token);
+                               
+                       var task = Task.Delay (30);
                        awaiter = task.GetAwaiter ();
+                               
+                       awaiter.GetResult ();
+                       Assert.AreEqual (TaskStatus.RanToCompletion, task.Status);
+               }
 
-                       try {
-                               awaiter.GetResult ();
-                               Assert.Fail ();
-                       } catch (TaskCanceledException) {
-                       }
+               [Test]
+               public void CustomScheduler ()
+               {
+                       // some test runners (e.g. Touch.Unit) will execute this on the main thread and that would lock them
+                       if (!Thread.CurrentThread.IsBackground)
+                               return;
+
+                       var a = new Scheduler ("a");
+                       var b = new Scheduler ("b");
+
+                       var t = TestCS (a, b);
+                       Assert.IsTrue (t.Wait (3000), "#0");
+                       Assert.AreEqual (0, t.Result, "#1");
+                       Assert.AreEqual (1, a.InlineCalls, "#2a");
+                       Assert.AreEqual (0, b.InlineCalls, "#2b");
+                       Assert.AreEqual (2, a.QueueCalls, "#3a");
+                       Assert.AreEqual (1, b.QueueCalls, "#3b");
+               }
+
+               static async Task<int> TestCS (TaskScheduler schedulerA, TaskScheduler schedulerB)
+               {
+                       var res = await Task.Factory.StartNew (async () => {
+                               if (TaskScheduler.Current != schedulerA)
+                                       return 1;
+
+                               await Task.Factory.StartNew (
+                                       () => {
+                                               if (TaskScheduler.Current != schedulerB)
+                                                       return 2;
+
+                                               return 0;
+                                       }, CancellationToken.None, TaskCreationOptions.None, schedulerB);
+
+                               if (TaskScheduler.Current != schedulerA)
+                                       return 3;
+
+                               return 0;
+                       }, CancellationToken.None, TaskCreationOptions.None, schedulerA);
+
+                       return res.Result;
+               }
+
+               [Test]
+               public void FinishedTaskOnCompleted ()
+               {
+                       var mres = new ManualResetEvent (false);
+                       var mres2 = new ManualResetEvent (false);
+
+                       var tcs = new TaskCompletionSource<object> ();
+                       tcs.SetResult (null);
+                       var task = tcs.Task;
+
+                       var awaiter = task.GetAwaiter ();
+                       Assert.IsTrue (awaiter.IsCompleted, "#1");
+
+                       awaiter.OnCompleted(() => { 
+                               if (mres.WaitOne (1000))
+                                       mres2.Set ();
+                       });
+
+                       mres.Set ();
+                       // this will only terminate correctly if the test was not executed from the main thread
+                       // e.g. Touch.Unit defaults to run tests on the main thread and this will return false
+                       Assert.AreEqual (Thread.CurrentThread.IsBackground, mres2.WaitOne (2000), "#2");;
                }
        }
 }