[System] UriKind.RelativeOrAbsolute workaround.
[mono.git] / mcs / class / Mono.Posix / Test / Mono.Unix / UnixSignalTest.cs
index 19deea2fb0f253526cdf68c56fed11520799b44d..3098596b4b0becd52c8deda139b7408c1fa4efb7 100644 (file)
 //
 
 using NUnit.Framework;
+using NUnit.Framework.SyntaxHelpers;
 using System;
 using System.Text;
 using System.Threading;
 using Mono.Unix;
 using Mono.Unix.Native;
 
+namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
+
 namespace MonoTests.Mono.Unix {
 
        [TestFixture]
        public class UnixSignalTest {
+
+               // helper method to create a thread waiting on a UnixSignal
+               static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
+               {
+                       Thread t1 = new Thread(delegate() {
+                                               DateTime start = DateTime.Now;
+                                               bool r = signal.WaitOne (timeout, false);
+                                               DateTime end = DateTime.Now;
+                                               Assert.AreEqual (signal.Count, 1);
+                                               Assert.AreEqual (r, true);
+                                               if ((end - start) > new TimeSpan (0, 0, timeout/1000))
+                                                       throw new InvalidOperationException ("Signal slept too long");
+                                       });
+                       return t1;
+               }
+
+               // helper method to create a two-thread test
+               static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
+               {
+                       Thread t1 = CreateWaitSignalThread (signal, timeout);
+                       Thread t2 = new Thread (tstart);
+                       t1.Start ();
+                       t2.Start ();
+                       t1.Join ();
+                       t2.Join ();
+               }
+
+               [Test]
+               public void TestNestedInvocation()
+               {
+                       UnixSignal s = new UnixSignal(Signum.SIGINT);
+                       Thread a = new Thread(delegate() {
+                                       bool r = s.WaitOne (1000, false);
+      });
+                       Thread b = new Thread(delegate() {
+                                       bool r = s.WaitOne (500, false);
+      });
+                       a.Start();
+                       b.Start();
+                       a.Join();
+                       b.Join();
+               }
+
+               [Test]
+               public void TestWaitAnyFailsWithMore64Signals()
+               {
+                       UnixSignal s1 = new UnixSignal(Signum.SIGINT);
+                       UnixSignal[] signals = new UnixSignal[65];
+                       for (int i=0; i<65; ++i)
+                               signals[i] = s1;
+                       
+                       Assert.That(UnixSignal.WaitAny(signals, new TimeSpan(0,0,1)), Is.EqualTo(-1));
+               }
+
+               [Test]
+               public void TestConcurrentWaitOne()
+               {
+                       UnixSignal s1 = new UnixSignal(Signum.SIGINT);
+                       UnixSignal s2 = new UnixSignal(Signum.SIGINT);
+                       Thread a = CreateWaitSignalThread(s1, 10000);
+                       Thread b = CreateWaitSignalThread(s2, 5000);
+                       Thread c = new Thread (delegate () {
+                                       Thread.Sleep (1000);
+                                       Stdlib.raise (Signum.SIGINT);
+                       });
+                       a.Start();
+                       b.Start();
+                       c.Start();
+                       a.Join();
+                       b.Join();
+                       c.Join();
+                       Assert.That(s1.Count, Is.EqualTo(1), "Expected 1 signal raised");
+                       Assert.That(s2.Count, Is.EqualTo(1), "Expected 1 signal raised");
+               }
+
+               [Test]
+               public void TestConcurrentWaitOneSameInstance()
+               {
+                       UnixSignal s1 = new UnixSignal(Signum.SIGINT);
+                       Thread a = CreateWaitSignalThread(s1, 10000);
+                       Thread b = CreateWaitSignalThread(s1, 10000);
+                       Thread c = new Thread (delegate () {
+                                       Thread.Sleep (500);
+                                       Stdlib.raise (Signum.SIGINT);
+                       });
+                       a.Start();
+                       b.Start();
+                       c.Start();
+                       a.Join();
+                       b.Join();
+                       c.Join();
+               }
+
+               [Test]
+               public void TestSignumProperty ()
+               {
+                       UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
+                       Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
+               }
+       
+               [Test]
+               [Category ("NotOnMac")]
+               public void TestRealTimeCstor ()
+               {
+                       RealTimeSignum rts = new RealTimeSignum (0);
+                       using (UnixSignal s = new UnixSignal (rts))
+                       {
+                               Assert.That(s.IsRealTimeSignal);
+                               Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
+                       }
+               }
+
+               [Test]
+               [ExpectedException]
+               [Category ("NotOnMac")]
+               public void TestSignumPropertyThrows ()
+               {
+                       UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
+                       Signum s = signal1.Signum;
+               }
+
+               [Test]
+               [Category ("NotOnMac")]
+               public void TestRealTimeSignumProperty ()
+               {
+                       RealTimeSignum rts = new RealTimeSignum (0);
+                       UnixSignal signal1 = new UnixSignal (rts);
+                       Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
+               }
+       
+               [Test]
+               [ExpectedException]
+               [Category ("NotOnMac")]
+               public void TestRealTimePropertyThrows ()
+               {
+                       UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
+                       RealTimeSignum s = signal1.RealTimeSignum;
+               }
+
+               [Test]
+               [Category ("NotOnMac")]
+               public void TestRaiseRTMINSignal ()
+               {
+                       RealTimeSignum rts = new RealTimeSignum (0);
+                       using (UnixSignal signal = new UnixSignal (rts))
+                       {
+                               MultiThreadTest (signal, 5000, delegate() {
+                                       Thread.Sleep (1000);
+                                       Stdlib.raise (rts);
+                                       });
+                       }
+               }
+
+               [Test]
+               [Category ("NotOnMac")]
+               public void TestRaiseRTMINPlusOneSignal ()
+               {
+                       /*this number is a guestimate, but it's ok*/
+                       for (int i = 1; i < 10; ++i) {
+                               RealTimeSignum rts = new RealTimeSignum (i);
+                               UnixSignal signal;
+                               try {
+                                       signal  = new UnixSignal (rts);
+                               } catch (ArgumentException) { /*skip the ones that are unavailable*/
+                                       continue;
+                               }
+                               using (signal)
+                               {
+                                       MultiThreadTest (signal, 5000, delegate() {
+                                               Thread.Sleep(1000);
+                                               Stdlib.raise(rts);
+                                               });
+                               }
+                               return;
+                       }
+                       Assert.IsTrue (false, "#1 No available RT signal");
+               }
+
+               [Test]
+               [Category ("NotOnMac")]
+               public void TestCanRegisterRTSignalMultipleTimes ()
+               {
+                       /*this number is a guestimate, but it's ok*/
+                       for (int i = 1; i < 10; ++i) {
+                               RealTimeSignum rts = new RealTimeSignum (i);
+                               UnixSignal signal;
+                               try {
+                                       signal  = new UnixSignal (rts);
+                               } catch (ArgumentException) { /*skip the ones that are unavailable*/
+                                       continue;
+                               }
+                               try {
+                                       using (UnixSignal signal2 =  new UnixSignal (rts))
+                                       {
+                                               //ok
+                                               return;
+                                       }
+                               } catch (ArgumentException) { /*skip the ones that are unavailable*/
+                                               Assert.IsTrue (false, "#1 Could not register second signal handler");
+                               }
+                       }
+                       Assert.IsTrue (false, "#2 No available RT signal");
+               }
+
                [Test]
                public void TestRaise ()
                {
@@ -121,6 +328,7 @@ namespace MonoTests.Mono.Unix {
                        UnixSignal b = new UnixSignal (Signum.SIGINT);
 
                        Stdlib.raise (Signum.SIGINT);
+                       SleepUntilSignaled (a);
 
                        Assert.AreEqual (a.Count, 1);
                        Assert.AreEqual (b.Count, 1);
@@ -129,11 +337,21 @@ namespace MonoTests.Mono.Unix {
                        b.Reset ();
 
                        Stdlib.raise (Signum.SIGINT);
+                       SleepUntilSignaled (b);
                        Assert.AreEqual (b.Count, 1);
 
                        b.Close ();
                }
 
+               static void SleepUntilSignaled (UnixSignal s)
+               {
+                       for (int i = 0; i < 10; ++i) {
+                               if (s.Count > 0)
+                                       break;
+                               Thread.Sleep (100);
+                       }
+               }
+
                [Test]
                public void TestDispose2 ()
                {
@@ -141,6 +359,7 @@ namespace MonoTests.Mono.Unix {
                        UnixSignal b = new UnixSignal (Signum.SIGINT);
 
                        Stdlib.raise (Signum.SIGINT);
+                       SleepUntilSignaled (a);
 
                        Assert.AreEqual (a.Count, 1);
                        Assert.AreEqual (b.Count, 1);
@@ -149,6 +368,7 @@ namespace MonoTests.Mono.Unix {
                        a.Reset ();
 
                        Stdlib.raise (Signum.SIGINT);
+                       SleepUntilSignaled (a);
                        Assert.AreEqual (a.Count, 1);
 
                        a.Close ();
@@ -171,6 +391,7 @@ namespace MonoTests.Mono.Unix {
                const int StormCount = 100000;
 
                [Test]
+               [Category("NotOnMac")] // OSX signal storming will not deliver every one
                public void TestRaiseStorm ()
                {
                        UnixSignal[] usignals = CreateSignals (signals);
@@ -222,6 +443,7 @@ namespace MonoTests.Mono.Unix {
                }
 
                [Test]
+               [Category("NotOnMac")] // OSX signal storming will not deliver every one
                public void TestAddRemove ()
                {
                        UnixSignal[] usignals = CreateSignals (signals);
@@ -256,6 +478,7 @@ namespace MonoTests.Mono.Unix {
                }
 
                [Test]
+               [Category("NotOnMac")] // OSX signal storming will not deliver every one
                public void TestWaitAny ()
                {
                        UnixSignal[] usignals = CreateSignals (signals);