using System;
using System.Threading;
using System.Threading.Tasks;
-
+using System.Collections.Generic;
using NUnit.Framework;
+#if !MOBILE
+using NUnit.Framework.SyntaxHelpers;
+#endif
+
namespace MonoTests.System.Threading.Tasks
{
[TestFixture]
public class TaskTests
{
+ class MockScheduler : TaskScheduler
+ {
+ public event Action<Task, bool> TryExecuteTaskInlineHandler;
+
+ protected override IEnumerable<Task> GetScheduledTasks ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override void QueueTask (Task task)
+ {
+ return;
+ }
+
+ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+ {
+ if (TryExecuteTaskInlineHandler != null)
+ TryExecuteTaskInlineHandler (task, taskWasPreviouslyQueued);
+
+ return base.TryExecuteTask (task);
+ }
+ }
+
+ class NonInlineableScheduler : TaskScheduler
+ {
+ protected override IEnumerable<Task> GetScheduledTasks ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override void QueueTask (Task task)
+ {
+ if (!base.TryExecuteTask (task))
+ throw new ApplicationException ();
+ }
+
+ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+ {
+ return false;
+ }
+ }
+
+
Task[] tasks;
const int max = 6;
Assert.IsTrue (tasks[0].IsCompleted, "#3");
Assert.IsTrue (tasks[1].IsCanceled, "#4");
}
-
+
+#if NET_4_5
[Test]
public void WaitAll_CancelledAndTimeout ()
{
var t2 = Task.Delay (3000);
Assert.IsFalse (Task.WaitAll (new[] { t1, t2 }, 10));
}
+#endif
[Test]
public void WaitAllExceptionThenCancelled ()
Task.WaitAll (tasks);
Assert.Fail ("#1");
} catch (AggregateException e) {
- Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#2");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#2");
var inner = (TaskCanceledException) e.InnerExceptions[1];
Assert.AreEqual (tasks[1], inner.Task, "#3");
}
}
}
+ [Test]
+ public void Wait_Inlined ()
+ {
+ bool? previouslyQueued = null;
+
+ var scheduler = new MockScheduler ();
+ scheduler.TryExecuteTaskInlineHandler += (task, b) => {
+ previouslyQueued = b;
+ };
+
+ var tf = new TaskFactory (scheduler);
+ var t = tf.StartNew (() => { });
+ t.Wait ();
+
+ Assert.AreEqual (true, previouslyQueued);
+ }
+
[Test, ExpectedException (typeof (InvalidOperationException))]
public void CreationWhileInitiallyCanceled ()
{
}, 10);
}
+ Task parent_wfc;
+
+ [Test]
+ public void WaitingForChildrenToComplete ()
+ {
+ Task nested = null;
+ var mre = new ManualResetEvent (false);
+
+ parent_wfc = Task.Factory.StartNew (() => {
+ nested = Task.Factory.StartNew (() => {
+ Assert.IsTrue (mre.WaitOne (4000), "parent_wfc needs to be set first");
+ Assert.IsFalse (parent_wfc.Wait (10), "#1a");
+ Assert.AreEqual (TaskStatus.WaitingForChildrenToComplete, parent_wfc.Status, "#1b");
+ }, TaskCreationOptions.AttachedToParent).ContinueWith (l => {
+ Assert.IsTrue (parent_wfc.Wait (2000), "#2a");
+ Assert.AreEqual (TaskStatus.RanToCompletion, parent_wfc.Status, "#2b");
+ }, TaskContinuationOptions.ExecuteSynchronously);
+ });
+
+ mre.Set ();
+ Assert.IsTrue (parent_wfc.Wait (2000), "#3");
+ Assert.IsTrue (nested.Wait (2000), "#4");
+ }
+
[Test]
public void WaitChildWithContinuationAttachedTest ()
{
public void DoubleWaitTest ()
{
ParallelTestHelper.Repeat (delegate {
- Console.WriteLine ("run");
var evt = new ManualResetEventSlim ();
- var t = Task.Factory.StartNew (() => evt.Wait (2000));
+ var t = Task.Factory.StartNew (() => evt.Wait (5000));
var cntd = new CountdownEvent (2);
+ var cntd2 = new CountdownEvent (2);
bool r1 = false, r2 = false;
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r1 = t.Wait (1000); Console.WriteLine ("out 1 {0}", r1); cntd.Signal (); });
- ThreadPool.QueueUserWorkItem (delegate { cntd.Signal (); r2 = t.Wait (1000); Console.WriteLine ("out 2 {0}", r2); cntd.Signal (); });
+ 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 (); });
- cntd.Wait (2000);
- cntd.Reset ();
+ Assert.IsTrue (cntd.Wait (2000), "#1");
evt.Set ();
- cntd.Wait (2000);
- Assert.IsTrue (r1);
- Assert.IsTrue (r2);
- }, 5);
+ Assert.IsTrue (cntd2.Wait (2000), "#2");
+ Assert.IsTrue (r1, "r1");
+ Assert.IsTrue (r2, "r2");
+ }, 10);
}
[Test]
}
[Test]
- public void ExecuteSynchronouslyTest ()
+ public void RunSynchronously ()
{
var val = 0;
Task t = new Task (() => { Thread.Sleep (100); val = 1; });
t.RunSynchronously ();
- Assert.AreEqual (1, val);
+ Assert.AreEqual (1, val, "#1");
+
+ t = new Task (() => { Thread.Sleep (0); val = 2; });
+
+ bool? previouslyQueued = null;
+
+ var scheduler = new MockScheduler ();
+ scheduler.TryExecuteTaskInlineHandler += (task, b) => {
+ previouslyQueued = b;
+ };
+
+ t.RunSynchronously (scheduler);
+
+ Assert.AreEqual (2, val, "#2");
+ Assert.AreEqual (false, previouslyQueued, "#2a");
}
[Test]
Assert.IsTrue (result);
}
+ [Test]
+ public void RunSynchronouslyOnContinuation ()
+ {
+ Task t = new Task<int> (() => 1);
+ t = t.ContinueWith (l => { });
+ try {
+ t.RunSynchronously ();
+ Assert.Fail ("#1");
+ } catch (InvalidOperationException) {
+ }
+ }
+
[Test]
public void UnobservedExceptionOnFinalizerThreadTest ()
{
Assert.IsTrue (r2);
}
+ [Test]
+ public void AsyncWaitHandleSet ()
+ {
+ var task = new TaskFactory ().StartNew (() => { });
+ var ar = (IAsyncResult)task;
+ ar.AsyncWaitHandle.WaitOne ();
+ }
+
#if NET_4_5
[Test]
public void Delay_Invalid ()
}
}
+ [Test]
+ public void Delay_TimeManagement ()
+ {
+ var delay1 = Task.Delay(50);
+ var delay2 = Task.Delay(25);
+ Assert.IsTrue (Task.WhenAny(new[] { delay1, delay2 }).Wait (1000));
+ Assert.AreEqual (TaskStatus.RanToCompletion, delay2.Status);
+ }
+
[Test]
public void WaitAny_WithNull ()
{
}
}
+ [Test]
+ public void WhenAll_Empty ()
+ {
+ var tasks = new Task[0];
+
+ Task t = Task.WhenAll(tasks);
+
+ Assert.IsTrue(t.Wait(1000), "#1");
+ }
+
[Test]
public void WhenAll_WithNull ()
{
Assert.IsTrue (t.Wait (1000), "#2");
Assert.Fail ("#2a");
} catch (AggregateException e) {
- Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
}
}
Assert.IsTrue (t.Wait (1000), "#2");
Assert.Fail ("#2a");
} catch (AggregateException e) {
- Assert.IsInstanceOfType (typeof (ApplicationException), e.InnerException, "#3");
- Assert.IsInstanceOfType (typeof (InvalidTimeZoneException), e.InnerExceptions[1], "#4");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (ApplicationException)), "#3");
+ Assert.That (e.InnerExceptions[1], Is.TypeOf (typeof (InvalidTimeZoneException)), "#4");
}
}
Assert.IsTrue (t.Wait (1000), "#2");
}
+ [Test]
+ public void WhenAllResult_Empty ()
+ {
+ var tasks = new Task<int>[0];
+
+ Task<int[]> t = Task.WhenAll(tasks);
+
+ Assert.IsTrue(t.Wait(1000), "#1");
+ Assert.IsNotNull(t.Result, "#2");
+ Assert.AreEqual(t.Result.Length, 0, "#3");
+ }
+
[Test]
public void WhenAllResult_WithNull ()
{
Assert.IsTrue (t.Wait (1000), "#2");
Assert.Fail ("#2a");
} catch (AggregateException e) {
- Assert.IsInstanceOfType (typeof (TaskCanceledException), e.InnerException, "#3");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
}
try {
Assert.IsTrue (t.Wait (1000), "#2");
Assert.IsNull (t.Exception, "#3");
- Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
+ Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
}
[Test]
Assert.IsTrue (t.Wait (1000), "#2");
Assert.IsNull (t.Exception, "#3");
- Assert.IsInstanceOfType (typeof (ApplicationException), t.Result.Exception.InnerException, "#4");
+ Assert.That (t.Result.Exception.InnerException, Is.TypeOf (typeof (ApplicationException)), "#4");
}
[Test]
Assert.AreEqual ('d', d.Result, "#3r");
}
+ [Test]
+ public void ContinueWith_CustomScheduleRejected ()
+ {
+ var scheduler = new NonInlineableScheduler ();
+ var t = Task.Factory.StartNew (delegate { }).
+ ContinueWith (r => {}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, scheduler);
+
+ Assert.IsTrue (t.Wait (5000));
+ }
+
[Test]
public void FromResult ()
{
[Test]
public void Run ()
{
- var t = Task.Run (delegate { });
+ bool ranOnDefaultScheduler = false;
+ var t = Task.Run (delegate { ranOnDefaultScheduler = Thread.CurrentThread.IsThreadPoolThread; });
Assert.AreEqual (TaskCreationOptions.DenyChildAttach, t.CreationOptions, "#1");
t.Wait ();
+ Assert.IsTrue (ranOnDefaultScheduler, "#2");
}
[Test]
}
[Test]
- public void Run_ExistingTask ()
+ public void Run_ExistingTaskT ()
{
var t = new Task<int> (() => 5);
var t2 = Task.Run (() => { t.Start (); return t; });
Assert.IsTrue (t2.Wait (1000), "#1");
Assert.AreEqual (5, t2.Result, "#2");
}
+
+ [Test]
+ public void Run_ExistingTask ()
+ {
+ var t = new Task (delegate { throw new Exception ("Foo"); });
+ var t2 = Task.Run (() => { t.Start (); return t; });
+
+ try {
+ t2.Wait (1000);
+ Assert.Fail ();
+ } catch (Exception) {}
+
+ Assert.AreEqual (TaskStatus.Faulted, t.Status, "#2");
+ }
+
+ [Test]
+ public void DenyChildAttachTest ()
+ {
+ var mre = new ManualResetEventSlim ();
+ Task nested = null;
+ Task parent = Task.Factory.StartNew (() => {
+ nested = Task.Factory.StartNew (() => mre.Wait (2000), TaskCreationOptions.AttachedToParent);
+ }, TaskCreationOptions.DenyChildAttach);
+ Assert.IsTrue (parent.Wait (1000), "#1");
+ mre.Set ();
+ Assert.IsTrue (nested.Wait (2000), "#2");
+ }
+
+ class SynchronousScheduler : TaskScheduler
+ {
+ protected override IEnumerable<Task> GetScheduledTasks ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override void QueueTask (Task task)
+ {
+ TryExecuteTaskInline (task, false);
+ }
+
+ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+ {
+ return base.TryExecuteTask (task);
+ }
+ }
+
+ [Test]
+ public void HideSchedulerTest ()
+ {
+ var mre = new ManualResetEventSlim ();
+ var ranOnDefault = false;
+ var scheduler = new SynchronousScheduler ();
+
+ Task parent = Task.Factory.StartNew (() => {
+ Task.Factory.StartNew (() => {
+ ranOnDefault = Thread.CurrentThread.IsThreadPoolThread;
+ mre.Set ();
+ });
+ }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler);
+
+ Assert.IsTrue (mre.Wait (1000), "#1");
+ Assert.IsTrue (ranOnDefault, "#2");
+ }
+
+ [Test]
+ public void LazyCancelationTest ()
+ {
+ var source = new CancellationTokenSource ();
+ source.Cancel ();
+ var parent = new Task (delegate {});
+ var cont = parent.ContinueWith (delegate {}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
+
+ Assert.AreNotEqual (TaskStatus.Canceled, cont.Status, "#1");
+ parent.Start ();
+ try {
+ Assert.IsTrue (cont.Wait (1000), "#2");
+ Assert.Fail ();
+ } catch (AggregateException ex) {
+ Assert.That (ex.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#3");
+ }
+ }
#endif
}
}