Merge pull request #963 from kebby/master
[mono.git] / mcs / class / corlib / Test / System.Threading / ManualResetEventSlimTests.cs
index d70b3d78907249e71415cd21e96c31228a69f51c..0694ef80b63ee7808bf39187837f2dcbd9c59f8f 100644 (file)
@@ -1,7 +1,11 @@
-#if NET_4_0
 // ManualResetEventSlimTests.cs
 //
+// Authors:
+//       Marek Safar (marek.safar@gmail.com)
+//       Jeremie Laval (jeremie.laval@gmail.com)
+//
 // Copyright (c) 2008 Jérémie "Garuma" Laval
+// Copyright (c) 2012 Xamarin, Inc (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +27,8 @@
 //
 //
 
+#if NET_4_0
+
 using System;
 using System.Threading;
 
@@ -43,6 +49,29 @@ namespace MonoTests.System.Threading
                {
                        mre = new ManualResetEventSlim();
                }
+
+               [Test]
+               public void Constructor_Defaults ()
+               {
+                       Assert.IsFalse (mre.IsSet, "#1");
+                       Assert.AreEqual (10, mre.SpinCount, "#2");
+               }
+
+               [Test]
+               public void Constructor_Invalid ()
+               {
+                       try {
+                               new ManualResetEventSlim (true, -1);
+                               Assert.Fail ("#1");
+                       } catch (ArgumentException) {
+                       }
+
+                       try {
+                               new ManualResetEventSlim (true, 2048);
+                               Assert.Fail ("#2");
+                       } catch (ArgumentException) {
+                       }
+               }
                
                [Test]
                public void IsSetTestCase()
@@ -73,11 +102,208 @@ namespace MonoTests.System.Threading
                                        m.Wait();
                                        s = true;
                                }
-                       });     
+                       }, 2);  
                        
                        Assert.IsTrue(s, "#1");
                        Assert.IsTrue(mre.IsSet, "#2");
                }
+
+               [Test]
+               public void Wait_SetConcurrent ()
+               {
+                       for (int i = 0; i < 10000; ++i) {
+                               var mre = new ManualResetEventSlim ();
+                               bool b = true;
+
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                       mre.Set ();
+                               });
+
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                       b &= mre.Wait (1000);
+                               });
+
+                               Assert.IsTrue (mre.Wait (1000), i.ToString ());
+                               Assert.IsTrue (b, i.ToString ());
+                       }
+               }
+
+               [Test]
+               public void Wait_DisposeWithCancel ()
+               {
+                       var token = new CancellationTokenSource ();
+                       ThreadPool.QueueUserWorkItem (delegate {
+                               Thread.Sleep (10);
+                               mre.Dispose ();
+                               token.Cancel ();
+                       });
+
+                       try {
+                               mre.Wait (10000, token.Token);
+                               Assert.Fail ("#0");
+                       } catch (OperationCanceledException e) {
+                       }
+               }
+
+               [Test]
+               public void Wait_Expired ()
+               {
+                       Assert.IsFalse (mre.Wait (10));
+               }
+
+               [Test, ExpectedException (typeof (ObjectDisposedException))]
+               public void WaitAfterDisposeTest ()
+               {
+                       mre.Dispose ();
+                       mre.Wait ();
+               }
+
+               [Test]
+               public void SetAfterDisposeTest ()
+               {
+                       ParallelTestHelper.Repeat (delegate {
+                               Exception disp = null, setting = null;
+
+                               CountdownEvent evt = new CountdownEvent (2);
+                               CountdownEvent evtFinish = new CountdownEvent (2);
+
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                       try {
+                                               evt.Signal ();
+                                               evt.Wait (1000);
+                                               mre.Dispose ();
+                                       } catch (Exception e) {
+                                               disp = e;
+                                       }
+                                       evtFinish.Signal ();
+                               });
+                               ThreadPool.QueueUserWorkItem (delegate {
+                                       try {
+                                               evt.Signal ();
+                                               evt.Wait (1000);
+                                               mre.Set ();
+                                       } catch (Exception e) {
+                                               setting = e;
+                                       }
+                                       evtFinish.Signal ();
+                               });
+
+                               bool bb = evtFinish.Wait (1000);
+                               if (!bb)
+                                       Assert.AreEqual (true, evtFinish.IsSet);
+
+                               Assert.IsTrue (bb, "#0");
+                               Assert.IsNull (disp, "#1");
+                               Assert.IsNull (setting, "#2");
+
+                               evt.Dispose ();
+                               evtFinish.Dispose ();
+                       });
+               }
+
+               [Test]
+               public void WaitHandle_Initialized ()
+               {
+                       var mre = new ManualResetEventSlim (true);
+                       Assert.IsTrue (mre.WaitHandle.WaitOne (0), "#1");
+                       mre.Reset ();
+                       Assert.IsFalse (mre.WaitHandle.WaitOne (0), "#2");
+                       Assert.AreEqual (mre.WaitHandle, mre.WaitHandle, "#3");
+               }
+
+               [Test]
+               public void WaitHandle_NotInitialized ()
+               {
+                       var mre = new ManualResetEventSlim (false);
+                       Assert.IsFalse (mre.WaitHandle.WaitOne (0), "#1");
+                       mre.Set ();
+                       Assert.IsTrue (mre.WaitHandle.WaitOne (0), "#2");
+               }
+
+               [Test]
+               public void WaitHandleConsistencyTest ()
+               {
+                       var mre = new ManualResetEventSlim ();
+                       mre.WaitHandle.WaitOne (0);
+
+                       for (int i = 0; i < 10000; i++) {
+                               int count = 2;
+                               SpinWait wait = new SpinWait ();
+
+                               ThreadPool.QueueUserWorkItem (_ => { mre.Set (); Interlocked.Decrement (ref count); });
+                               ThreadPool.QueueUserWorkItem (_ => { mre.Reset (); Interlocked.Decrement (ref count); });
+
+                               while (count > 0)
+                                       wait.SpinOnce ();
+                               Assert.AreEqual (mre.IsSet, mre.WaitHandle.WaitOne (0));
+                       }
+               }
+
+               [Test]
+               public void WaitWithCancellationTokenAndNotImmediateSetTest ()
+               {
+                       var mres = new ManualResetEventSlim ();
+                       var cts = new CancellationTokenSource ();
+                       ThreadPool.QueueUserWorkItem(x => { Thread.Sleep (1000); mres.Set (); });
+                       Assert.IsTrue (mres.Wait (TimeSpan.FromSeconds (10), cts.Token), "Wait returned false despite event was set.");
+               }
+
+               [Test]
+               public void WaitWithCancellationTokenAndCancel ()
+               {
+                       var mres = new ManualResetEventSlim ();
+                       var cts = new CancellationTokenSource ();
+                       ThreadPool.QueueUserWorkItem(x => { Thread.Sleep (1000); cts.Cancel (); });
+                       try {
+                               mres.Wait (TimeSpan.FromSeconds (10), cts.Token);
+                               Assert.Fail ("Wait did not throw an exception despite cancellation token was cancelled.");
+                       } catch (OperationCanceledException) {
+                       }
+               }
+
+               [Test]
+               public void WaitWithCancellationTokenAndTimeout ()
+               {
+                       var mres = new ManualResetEventSlim ();
+                       var cts = new CancellationTokenSource ();
+                       Assert.IsFalse (mres.Wait (TimeSpan.FromSeconds (1), cts.Token), "Wait returned true despite timeout.");
+               }
+
+               [Test]
+               public void Dispose ()
+               {
+                       var mre = new ManualResetEventSlim (false);
+                       mre.Dispose ();
+                       Assert.IsFalse (mre.IsSet, "#0a");
+
+                       try {
+                           mre.Reset ();
+                           Assert.Fail ("#1");
+                       } catch (ObjectDisposedException) {
+                       }
+
+                       mre.Set ();
+
+                       try {
+                               mre.Wait (0);
+                               Assert.Fail ("#3");
+                       } catch (ObjectDisposedException) {
+                       }
+
+                       try {
+                               var v = mre.WaitHandle;
+                               Assert.Fail ("#4");
+                       } catch (ObjectDisposedException) {
+                       }
+               }
+
+               [Test]
+               public void Dispose_Double ()
+               {
+                       var mre = new ManualResetEventSlim ();
+                       mre.Dispose ();
+                       mre.Dispose ();
+               }
        }
 }
 #endif