X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FTest%2FSystem.Runtime.CompilerServices%2FTaskAwaiterTest.cs;h=57b1d2c27642c1dafc45d854a7ccf92f086f1cee;hb=69f207ee9e4f440e66e98bf5f685807f6527c39d;hp=74d5c548852556979c82a339d9ada3173ab4f9d9;hpb=d1da2873830f5fcebf7000c1fd3e260ddd3336bb;p=mono.git diff --git a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs index 74d5c548852..57b1d2c2764 100644 --- a/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs +++ b/mcs/class/corlib/Test/System.Runtime.CompilerServices/TaskAwaiterTest.cs @@ -35,6 +35,7 @@ using NUnit.Framework; using System.Runtime.CompilerServices; using System.Collections.Generic; using System.Collections; +using System.Collections.Concurrent; namespace MonoTests.System.Runtime.CompilerServices { @@ -72,6 +73,11 @@ namespace MonoTests.System.Runtime.CompilerServices Interlocked.Increment (ref ic); return false; } + + public override string ToString () + { + return "Scheduler-" + name; + } } class SingleThreadSynchronizationContext : SynchronizationContext @@ -101,6 +107,43 @@ namespace MonoTests.System.Runtime.CompilerServices } } + class NestedSynchronizationContext : SynchronizationContext + { + Thread thread; + readonly ConcurrentQueue> workQueue = new ConcurrentQueue> (); + readonly AutoResetEvent workReady = new AutoResetEvent (false); + + public NestedSynchronizationContext () + { + thread = new Thread (WorkerThreadProc) { IsBackground = true }; + thread.Start (); + } + + public override void Post (SendOrPostCallback d, object state) + { + var context = ExecutionContext.Capture (); + workQueue.Enqueue (Tuple.Create (d, state, context)); + workReady.Set (); + } + + void WorkerThreadProc () + { + if (!workReady.WaitOne (10000)) + return; + + Tuple work; + + while (workQueue.TryDequeue (out work)) { + ExecutionContext.Run (work.Item3, _ => { + var oldSyncContext = SynchronizationContext.Current; + SynchronizationContext.SetSynchronizationContext (this); + work.Item1 (_); + SynchronizationContext.SetSynchronizationContext (oldSyncContext); + }, work.Item2); + } + } + } + string progress; SynchronizationContext sc; ManualResetEvent mre; @@ -178,7 +221,7 @@ namespace MonoTests.System.Runtime.CompilerServices Assert.IsTrue (t.Wait (3000), "#0"); Assert.AreEqual (0, t.Result, "#1"); Assert.AreEqual (0, b.InlineCalls, "#2b"); - Assert.AreEqual (2, a.QueueCalls, "#3a"); + Assert.IsTrue (a.QueueCalls == 1 || a.QueueCalls == 2, "#3a"); Assert.AreEqual (1, b.QueueCalls, "#3b"); } @@ -205,6 +248,7 @@ namespace MonoTests.System.Runtime.CompilerServices return res.Result; } +#if !MOBILE_STATIC [Test] public void FinishedTaskOnCompleted () { @@ -229,6 +273,8 @@ namespace MonoTests.System.Runtime.CompilerServices Assert.AreEqual (Thread.CurrentThread.IsBackground, mres2.WaitOne (2000), "#2");; } +#endif + [Test] public void CompletionOnSameCustomSynchronizationContext () { @@ -278,7 +324,9 @@ namespace MonoTests.System.Runtime.CompilerServices SynchronizationContext.SetSynchronizationContext (syncContext); syncContext.Post (delegate { - Go2 (syncContext); + Task t = new Task (delegate() { }); + Go2 (syncContext, t); + t.Start (); }, null); // Custom message loop @@ -289,30 +337,62 @@ namespace MonoTests.System.Runtime.CompilerServices Thread.Sleep (0); } - Assert.AreEqual ("132", progress); + Assert.AreEqual ("13xa2", progress); } - async void Go2 (SynchronizationContext ctx) + async void Go2 (SynchronizationContext ctx, Task t) { - await Wait2 (ctx); + await Wait2 (ctx, t); + + progress += "a"; if (mre.WaitOne (5000)) progress += "2"; + else + progress += "b"; } - async Task Wait2 (SynchronizationContext ctx) + async Task Wait2 (SynchronizationContext ctx, Task t) { - await Task.Delay (10); // Force block suspend/return + await t; // Force block suspend/return ctx.Post (l => { progress += "3"; mre.Set (); + progress += "x"; }, null); progress += "1"; SynchronizationContext.SetSynchronizationContext (null); } + + [Test] + public void NestedLeakingSynchronizationContext () + { + var sc = SynchronizationContext.Current; + if (sc == null) + Assert.IsTrue (NestedLeakingSynchronizationContext_MainAsync (sc).Wait (5000), "#1"); + else + Assert.Ignore ("NestedSynchronizationContext may never complete on custom context"); + } + + static async Task NestedLeakingSynchronizationContext_MainAsync (SynchronizationContext sc) + { + Assert.AreSame (sc, SynchronizationContext.Current, "#1"); + await NestedLeakingSynchronizationContext_DoWorkAsync (); + Assert.AreSame (sc, SynchronizationContext.Current, "#2"); + } + + static async Task NestedLeakingSynchronizationContext_DoWorkAsync () + { + var sc = new NestedSynchronizationContext (); + SynchronizationContext.SetSynchronizationContext (sc); + + Assert.AreSame (sc, SynchronizationContext.Current); + await Task.Yield (); + Assert.AreSame (sc, SynchronizationContext.Current); + } } }