Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / corlib / Test / System.Threading.Tasks / TaskTest.cs
index df382b17008f85d45b7f6bec89e8b133efb2a526..d3ce52f88e831094a37d9307ead9bbe2f0f56625 100644 (file)
@@ -104,14 +104,49 @@ namespace MonoTests.System.Threading.Tasks
                        }
                }
 
+               int workerThreads;
+               int completionPortThreads;
 
                Task[] tasks;
                const int max = 6;
+               object cleanup_mutex = new object ();
+               List<Task> cleanup_list;
                
                [SetUp]
                public void Setup()
                {
-                       tasks = new Task[max];                  
+                       ThreadPool.GetMinThreads (out workerThreads, out completionPortThreads);
+                       ThreadPool.SetMinThreads (1, 1);
+
+                       tasks = new Task[max];
+                       cleanup_list = new List<Task> ();
+               }
+               
+               [TearDown]
+               public void Teardown()
+               {
+                       ThreadPool.SetMinThreads (workerThreads, completionPortThreads);
+                       Task[] l = null;
+                       lock (cleanup_mutex) {
+                               l = cleanup_list.ToArray ();
+                       }
+                       try {
+                               Task.WaitAll (l);
+                       } catch (Exception) {
+                       }
+               }
+
+               void AddToCleanup (Task[] tasks) {
+                       lock (cleanup_mutex) {
+                               foreach (var t in tasks)
+                                       cleanup_list.Add (t);
+                       }
+               }
+
+               void AddToCleanup (Task task) {
+                       lock (cleanup_mutex) {
+                               cleanup_list.Add (task);
+                       }
                }
                
                void InitWithDelegate(Action action)
@@ -119,6 +154,7 @@ namespace MonoTests.System.Threading.Tasks
                        for (int i = 0; i < max; i++) {
                                tasks[i] = Task.Factory.StartNew(action);
                        }
+                       AddToCleanup (tasks);
                }
                
                [Test]
@@ -201,11 +237,11 @@ namespace MonoTests.System.Threading.Tasks
                {
                        var mre = new ManualResetEventSlim (false);
                        var tasks = new Task[] {
-                               Task.Factory.StartNew (delegate { mre.Wait (1000); }),
+                               Task.Factory.StartNew (delegate { mre.Wait (5000); }),
                                Task.Factory.StartNew (delegate { throw new ApplicationException (); })
                        };
 
-                       Assert.AreEqual (1, Task.WaitAny (tasks, 1000), "#1");
+                       Assert.AreEqual (1, Task.WaitAny (tasks, 3000), "#1");
                        Assert.IsFalse (tasks[0].IsCompleted, "#2");
                        Assert.IsTrue (tasks[1].IsFaulted, "#3");
 
@@ -275,6 +311,7 @@ namespace MonoTests.System.Threading.Tasks
                                for (int i = 0; i < tasks.Length; i++) {
                                        tasks[i] = Task.Factory.StartNew (delegate { Thread.Sleep (0); });
                                }
+                               AddToCleanup (tasks);
 
                                Assert.IsTrue (Task.WaitAll (tasks, 5000));
                        }
@@ -308,7 +345,7 @@ namespace MonoTests.System.Threading.Tasks
                        CountdownEvent cde = new CountdownEvent (2);
                        var mre = new ManualResetEvent (false);
                        var tasks = new[] {
-                               Task.Factory.StartNew (delegate { mre.WaitOne (); }),
+                               Task.Factory.StartNew (delegate { Assert.IsTrue (mre.WaitOne (1500), "#0"); }),
                                Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } }),
                                Task.Factory.StartNew (delegate { try { throw new ApplicationException (); } finally { cde.Signal (); } })
                        };
@@ -319,7 +356,7 @@ namespace MonoTests.System.Threading.Tasks
                        mre.Set ();
 
                        try {
-                               Assert.IsTrue (Task.WaitAll (tasks, 1000), "#3");
+                               Task.WaitAll (tasks, 1000);
                                Assert.Fail ("#4");
                        } catch (AggregateException e) {
                                Assert.AreEqual (2, e.InnerExceptions.Count, "#5");
@@ -481,13 +518,26 @@ namespace MonoTests.System.Threading.Tasks
                        Assert.AreEqual (true, previouslyQueued);
                }
 
-               [Test, ExpectedException (typeof (InvalidOperationException))]
+               [Test]
                public void CreationWhileInitiallyCanceled ()
                {
                        var token = new CancellationToken (true);
                        var task = new Task (() => { }, token);
-                       Assert.AreEqual (TaskStatus.Canceled, task.Status);
-                       task.Start ();
+
+                       try {
+                               task.Start ();
+                               Assert.Fail ("#1");
+                       } catch (InvalidOperationException) {
+                       }
+
+                       try {
+                               task.Wait ();
+                               Assert.Fail ("#2");
+                       } catch (AggregateException e) {
+                               Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
+                       }
+
+                       Assert.IsTrue (task.IsCanceled, "#4");
                }
 
                [Test]
@@ -497,25 +547,25 @@ namespace MonoTests.System.Threading.Tasks
                        try {
                                task.ContinueWith (null);
                                Assert.Fail ("#1");
-                       } catch (ArgumentException) {
+                       } catch (ArgumentNullException e) {
                        }
 
                        try {
                                task.ContinueWith (delegate { }, null);
                                Assert.Fail ("#2");
-                       } catch (ArgumentException) {
+                       } catch (ArgumentNullException e) {
                        }
 
                        try {
                                task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.NotOnCanceled);
                                Assert.Fail ("#3");
-                       } catch (ArgumentException) {
+                       } catch (ArgumentOutOfRangeException) {
                        }
 
                        try {
                                task.ContinueWith (delegate { }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion);
                                Assert.Fail ("#4");
-                       } catch (ArgumentException) {
+                       } catch (ArgumentOutOfRangeException) {
                        }
                }
 
@@ -616,18 +666,18 @@ namespace MonoTests.System.Threading.Tasks
                public void ContinueWithChildren ()
                {
                        ParallelTestHelper.Repeat (delegate {
-                           bool result = false;
+                               bool result = false;
 
-                           var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
+                               var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => {}, TaskCreationOptions.AttachedToParent));
 
                                var mre = new ManualResetEvent (false);
-                           t.ContinueWith (l => {
+                               t.ContinueWith (l => {
                                        result = true;
                                        mre.Set ();
                                });
 
                                Assert.IsTrue (mre.WaitOne (1000), "#1");
-                           Assert.IsTrue (result, "#2");
+                               Assert.IsTrue (result, "#2");
                        }, 2);
                }
 
@@ -788,19 +838,64 @@ namespace MonoTests.System.Threading.Tasks
                {
                        ParallelTestHelper.Repeat (delegate {
                                var evt = new ManualResetEventSlim ();
-                               var t = Task.Factory.StartNew (() => evt.Wait (5000));
+                               var monitor = new object ();
+                               int finished = 0;
+                               var t = Task.Factory.StartNew (delegate {
+                                               var r = evt.Wait (5000);
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                               return r ? 1 : 10; //1 -> ok, 10 -> evt wait failed
+                                       });
                                var cntd = new CountdownEvent (2);
                                var cntd2 = new CountdownEvent (2);
 
-                               bool r1 = false, r2 = false;
-                               ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-                               ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000) && t.Result; cntd2.Signal (); });
-
+                               int r1 = 0, r2 = 0;
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                               cntd.Signal ();
+                                               if (!t.Wait (1000))
+                                                       r1 = 20; // 20 -> task wait failed
+                                               else if (t.Result != 1)
+                                                       r1 = 30 + t.Result; // 30 -> task result is bad
+                                               else
+                                                       r1 = 2; //2 -> ok
+                                               cntd2.Signal ();
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                       });
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                               cntd.Signal ();
+                                               if (!t.Wait (1000))
+                                                       r2 = 40; // 40 -> task wait failed
+                                               else if (t.Result != 1)
+                                                       r2 = 50 + t.Result; // 50 -> task result is bad
+                                               else
+                                                       r2 = 3; //3 -> ok
+
+                                               cntd2.Signal ();
+                                               lock (monitor) {
+                                                       finished ++;
+                                                       Monitor.Pulse (monitor);
+                                               }
+                                       });
                                Assert.IsTrue (cntd.Wait (2000), "#1");
                                evt.Set ();
                                Assert.IsTrue (cntd2.Wait (2000), "#2");
-                               Assert.IsTrue (r1, "r1");
-                               Assert.IsTrue (r2, "r2");
+                               Assert.AreEqual (2, r1, "r1");
+                               Assert.AreEqual (3, r2, "r2");
+
+                               // Wait for everything to finish to avoid overloading the tpool
+                               lock (monitor) {
+                                       while (true) {
+                                               if (finished == 3)
+                                                       break;
+                                               else
+                                                       Monitor.Wait (monitor);
+                                       }
+                               }
                        }, 10);
                }
 
@@ -905,7 +1000,7 @@ namespace MonoTests.System.Threading.Tasks
                        };
                        var inner = new ApplicationException ();
                        Thread t = new Thread (delegate () {
-                                       Task.Factory.StartNew (() => { Console.WriteLine ("HIT!"); throw inner; });
+                                       Task.Factory.StartNew (() => { throw inner; });
                                });
                        t.Start ();
                        t.Join ();
@@ -929,7 +1024,7 @@ namespace MonoTests.System.Threading.Tasks
                [Test]
                public void Start_NullArgument ()
                {
-                       var t = Task.Factory.StartNew (delegate () { });
+                       var t = new Task (() => { });
                        try {
                                t.Start (null);
                                Assert.Fail ();
@@ -1064,7 +1159,7 @@ namespace MonoTests.System.Threading.Tasks
                        });
                        var onErrorTask = testTask.ContinueWith (x => continuationRan = true, TaskContinuationOptions.OnlyOnFaulted);
                        testTask.RunSynchronously ();
-                       onErrorTask.Wait (100);
+                       onErrorTask.Wait (1000);
                        Assert.IsNotNull (e);
                        Assert.IsTrue (continuationRan);
                }
@@ -1094,7 +1189,7 @@ namespace MonoTests.System.Threading.Tasks
                        var t = new Task (() => {
                                new Task (() => { r1 = true; }, TaskCreationOptions.AttachedToParent).RunSynchronously ();
                                Task.Factory.StartNew (() => { Thread.Sleep (100); r2 = true; }, TaskCreationOptions.AttachedToParent);
-                   });
+                       });
                        t.RunSynchronously ();
 
                        Assert.IsTrue (r1);
@@ -1106,7 +1201,8 @@ namespace MonoTests.System.Threading.Tasks
                {
                        var task = new TaskFactory ().StartNew (() => { });
                        var ar = (IAsyncResult)task;
-                       ar.AsyncWaitHandle.WaitOne ();
+                       Assert.IsFalse (ar.CompletedSynchronously, "#1");
+                       Assert.IsTrue (ar.AsyncWaitHandle.WaitOne (5000), "#2");
                }
 
                [Test]
@@ -1793,7 +1889,7 @@ namespace MonoTests.System.Threading.Tasks
                        bool? is_bg = null;
                        var t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; });
                        t.Start ();
-                       Assert.IsTrue (t.Wait (100));
+                       Assert.IsTrue (t.Wait (5000), "#0");
                        Assert.IsTrue ((bool)is_tp, "#1");
                        Assert.IsTrue ((bool)is_bg, "#2");
 
@@ -1801,8 +1897,7 @@ namespace MonoTests.System.Threading.Tasks
                        is_bg = null;
                        t = new Task (() => { is_tp = Thread.CurrentThread.IsThreadPoolThread; is_bg = Thread.CurrentThread.IsBackground; }, TaskCreationOptions.LongRunning);
                        t.Start ();
-
-                       Assert.IsTrue (t.Wait (100));
+                       Assert.IsTrue (t.Wait (5000), "#10");
                        Assert.IsFalse ((bool) is_tp, "#11");
                        Assert.IsTrue ((bool) is_bg, "#12");
                }
@@ -1931,6 +2026,24 @@ namespace MonoTests.System.Threading.Tasks
                        }
                }
 
+               [Test]
+               public void ChildTaskWithUnscheduledContinuationAttachedToParent ()
+               {
+                       Task inner = null;
+                       var child = Task.Factory.StartNew (() => {
+                               inner  = Task.Run (() => {
+                                       throw new ApplicationException ();
+                               }).ContinueWith (task => { }, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
+                       });
+
+                       int counter = 0;
+                       var t = child.ContinueWith (t2 => ++counter, TaskContinuationOptions.ExecuteSynchronously);
+                       Assert.IsTrue (t.Wait (5000), "#1");
+                       Assert.AreEqual (1, counter, "#2");
+                       Assert.AreEqual (TaskStatus.RanToCompletion, child.Status, "#3");
+                       Assert.AreEqual (TaskStatus.Canceled, inner.Status, "#4");
+               }
+
                [Test]
                [Category("NotWorking")]
                public void TaskContinuationChainLeak()