Merge pull request #820 from brendanzagaeski/master
[mono.git] / mcs / class / corlib / Test / System.Threading / CancellationTokenSourceTest.cs
index 55626334633010216d13a448cd53f84119d65197..8aef81c7b1e3e7533833536c520ff85ae90aa691 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_4_0 || MOBILE
+#if NET_4_0
 
 using System;
 using System.Threading;
 using NUnit.Framework;
 using System.Threading.Tasks;
+using MonoTests.System.Threading.Tasks;
 
 namespace MonoTests.System.Threading
 {
@@ -130,6 +131,20 @@ namespace MonoTests.System.Threading
                }
 
 
+               [Test]
+               public void Cancel_Order ()
+               {
+                       var cts = new CancellationTokenSource ();
+                       var current = 0;
+                       Action<object> a = x => { Assert.AreEqual(current, x); current++; };
+
+                       cts.Token.Register (a, 2);
+                       cts.Token.Register (a, 1);
+                       cts.Token.Register (a, 0);
+                       cts.Cancel ();
+               }
+
+
                [Test]
                public void CancelWithDispose ()
                {
@@ -191,6 +206,25 @@ namespace MonoTests.System.Threading
                        cts.Cancel ();
                }
 
+               [Test]
+               public void Cancel_ExceptionOrder ()
+               {
+                       var cts = new CancellationTokenSource ();
+
+                       cts.Token.Register (() => { throw new ApplicationException ("1"); });
+                       cts.Token.Register (() => { throw new ApplicationException ("2"); });
+                       cts.Token.Register (() => { throw new ApplicationException ("3"); });
+
+                       try {
+                               cts.Cancel ();
+                       } catch (AggregateException e) {
+                               Assert.AreEqual (3, e.InnerExceptions.Count, "#2");
+                               Assert.AreEqual ("3", e.InnerExceptions[0].Message, "#3");
+                               Assert.AreEqual ("2", e.InnerExceptions[1].Message, "#4");
+                               Assert.AreEqual ("1", e.InnerExceptions[2].Message, "#5");
+                       }
+               }
+
                [Test]
                public void Cancel_MultipleException_Recursive ()
                {
@@ -374,10 +408,9 @@ namespace MonoTests.System.Threading
                        var source = new CancellationTokenSource ();
                        var token = source.Token;
 
-                       var reg = new CancellationTokenRegistration ();
                        Console.WriteLine ("Test1");
+                       var reg = token.Register (() => unregister = true);
                        token.Register (() => reg.Dispose ());
-                       reg = token.Register (() => unregister = true);
                        token.Register (() => { Console.WriteLine ("Gnyah"); token.Register (() => register = true); });
                        source.Cancel ();
 
@@ -395,6 +428,63 @@ namespace MonoTests.System.Threading
                        req.Dispose ();
                        Assert.IsFalse (ran);
                }
+
+               [Test]
+               public void CancelLinkedTokenSource ()
+               {
+                       var cts = new CancellationTokenSource ();
+                       bool canceled = false;
+                       cts.Token.Register (() => canceled = true);
+
+                       using (var linked = CancellationTokenSource.CreateLinkedTokenSource (cts.Token))
+                               ;
+
+                       Assert.IsFalse (canceled, "#1");
+                       Assert.IsFalse (cts.IsCancellationRequested, "#2");
+
+                       cts.Cancel ();
+
+                       Assert.IsTrue (canceled, "#3");
+               }
+
+               [Test]
+               public void ConcurrentCancelLinkedTokenSourceWhileDisposing ()
+               {
+                       ParallelTestHelper.Repeat (delegate {
+                               var src = new CancellationTokenSource ();
+                               var linked = CancellationTokenSource.CreateLinkedTokenSource (src.Token);
+                               var cntd = new CountdownEvent (2);
+
+                               var t1 = new Thread (() => {
+                                       if (!cntd.Signal ())
+                                               cntd.Wait (200);
+                                       src.Cancel ();
+                               });
+                               var t2 = new Thread (() => {
+                                       if (!cntd.Signal ())
+                                               cntd.Wait (200);
+                                       linked.Dispose ();
+                               });
+
+                               t1.Start ();
+                               t2.Start ();
+                               t1.Join (500);
+                               t2.Join (500);
+                       }, 500);
+               }
+
+               [Test]
+               public void DisposeRace ()
+               {
+                       for (int i = 0; i < 1000; ++i) {
+                               var c1 = new CancellationTokenSource ();
+                               using (c1) {
+                                       var wh = c1.Token.WaitHandle;
+                                       c1.CancelAfter (1);
+                                       Thread.Sleep (1);
+                               }
+                       }
+               }
        }
 }