2 // UnixSignalTest.cs - NUnit Test Cases for Mono.Unix.UnixSignal
5 // Jonathan Pryor <jonpryor@vt.edu>
7 // (C) 2008 Jonathan Pryor
10 using NUnit.Framework;
11 using NUnit.Framework.SyntaxHelpers;
14 using System.Threading;
16 using Mono.Unix.Native;
18 namespace MonoTests.Mono.Unix {
21 public class UnixSignalTest {
23 // helper method to create a thread waiting on a UnixSignal
24 static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
26 Thread t1 = new Thread(delegate() {
27 DateTime start = DateTime.Now;
28 bool r = signal.WaitOne (timeout, false);
29 DateTime end = DateTime.Now;
30 Assert.AreEqual (signal.Count, 1);
31 Assert.AreEqual (r, true);
32 if ((end - start) > new TimeSpan (0, 0, timeout/1000))
33 throw new InvalidOperationException ("Signal slept too long");
38 // helper method to create a two-thread test
39 static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
41 Thread t1 = CreateWaitSignalThread (signal, timeout);
42 Thread t2 = new Thread (tstart);
50 public void TestNestedInvocation()
52 UnixSignal s = new UnixSignal(Signum.SIGINT);
53 Thread a = new Thread(delegate() {
54 bool r = s.WaitOne (1000, false);
56 Thread b = new Thread(delegate() {
57 bool r = s.WaitOne (500, false);
66 public void TestWaitAnyFailsWithMore64Signals()
68 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
69 UnixSignal[] signals = new UnixSignal[65];
70 for (int i=0; i<65; ++i)
73 Assert.That(UnixSignal.WaitAny(signals, new TimeSpan(0,0,1)), Is.EqualTo(-1));
77 public void TestConcurrentWaitOne()
79 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
80 UnixSignal s2 = new UnixSignal(Signum.SIGINT);
81 Thread a = CreateWaitSignalThread(s1, 10000);
82 Thread b = CreateWaitSignalThread(s2, 5000);
83 Thread c = new Thread (delegate () {
85 Stdlib.raise (Signum.SIGINT);
93 Assert.That(s1.Count, Is.EqualTo(1), "Expected 1 signal raised");
94 Assert.That(s2.Count, Is.EqualTo(1), "Expected 1 signal raised");
98 public void TestConcurrentWaitOneSameInstance()
100 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
101 Thread a = CreateWaitSignalThread(s1, 10000);
102 Thread b = CreateWaitSignalThread(s1, 10000);
103 Thread c = new Thread (delegate () {
105 Stdlib.raise (Signum.SIGINT);
116 public void TestSignumProperty ()
118 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
119 Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
123 [Category ("NotOnMac")]
124 public void TestRealTimeCstor ()
126 RealTimeSignum rts = new RealTimeSignum (0);
127 using (UnixSignal s = new UnixSignal (rts))
129 Assert.That(s.IsRealTimeSignal);
130 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
136 [Category ("NotOnMac")]
137 public void TestSignumPropertyThrows ()
139 UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
140 Signum s = signal1.Signum;
144 [Category ("NotOnMac")]
145 public void TestRealTimeSignumProperty ()
147 RealTimeSignum rts = new RealTimeSignum (0);
148 UnixSignal signal1 = new UnixSignal (rts);
149 Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
154 [Category ("NotOnMac")]
155 public void TestRealTimePropertyThrows ()
157 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
158 RealTimeSignum s = signal1.RealTimeSignum;
162 [Category ("NotOnMac")]
163 public void TestRaiseRTMINSignal ()
165 RealTimeSignum rts = new RealTimeSignum (0);
166 using (UnixSignal signal = new UnixSignal (rts))
168 MultiThreadTest (signal, 5000, delegate() {
176 [Category ("NotOnMac")]
177 public void TestRaiseRTMINPlusOneSignal ()
179 /*this number is a guestimate, but it's ok*/
180 for (int i = 1; i < 10; ++i) {
181 RealTimeSignum rts = new RealTimeSignum (i);
184 signal = new UnixSignal (rts);
185 } catch (ArgumentException) { /*skip the ones that are unavailable*/
190 MultiThreadTest (signal, 5000, delegate() {
197 Assert.IsTrue (false, "#1 No available RT signal");
201 [Category ("NotOnMac")]
202 public void TestCanRegisterRTSignalMultipleTimes ()
204 /*this number is a guestimate, but it's ok*/
205 for (int i = 1; i < 10; ++i) {
206 RealTimeSignum rts = new RealTimeSignum (i);
209 signal = new UnixSignal (rts);
210 } catch (ArgumentException) { /*skip the ones that are unavailable*/
214 using (UnixSignal signal2 = new UnixSignal (rts))
219 } catch (ArgumentException) { /*skip the ones that are unavailable*/
220 Assert.IsTrue (false, "#1 Could not register second signal handler");
223 Assert.IsTrue (false, "#2 No available RT signal");
227 public void TestRaise ()
229 Thread t1 = new Thread (delegate () {
230 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
231 DateTime start = DateTime.Now;
232 bool r = a.WaitOne (5000, false);
233 DateTime end = DateTime.Now;
234 Assert.AreEqual (a.Count, 1);
235 Assert.AreEqual (r, true);
236 if ((end - start) > new TimeSpan (0, 0, 5))
237 throw new InvalidOperationException ("Signal slept too long");
240 Thread t2 = new Thread (delegate () {
242 Stdlib.raise (Signum.SIGINT);
251 public void TestRaiseAny ()
253 Thread t1 = new Thread (delegate () {
254 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
255 DateTime start = DateTime.Now;
256 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
257 DateTime end = DateTime.Now;
258 Assert.AreEqual (idx, 0);
259 Assert.AreEqual (a.Count, 1);
260 if ((end - start) > new TimeSpan (0, 0, 5))
261 throw new InvalidOperationException ("Signal slept too long");
264 Thread t2 = new Thread (delegate () {
266 Stdlib.raise (Signum.SIGINT);
275 public void TestSeparation ()
277 Thread t1 = new Thread (delegate () {
278 using (UnixSignal a = new UnixSignal (Signum.SIGINT))
279 using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
280 DateTime start = DateTime.Now;
281 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
282 DateTime end = DateTime.Now;
283 Assert.AreEqual (idx, 1);
284 Assert.AreEqual (a.Count, 0);
285 Assert.AreEqual (b.Count, 1);
286 if ((end - start) > new TimeSpan (0, 0, 5))
287 throw new InvalidOperationException ("Signal slept too long");
290 Thread t2 = new Thread (delegate () {
292 Stdlib.raise (Signum.SIGTERM);
301 public void TestNoEmit ()
303 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
304 DateTime start = DateTime.Now;
305 bool r = u.WaitOne (5100, false);
306 Assert.AreEqual (r, false);
307 DateTime end = DateTime.Now;
308 if ((end - start) < new TimeSpan (0, 0, 5))
309 throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
314 public void TestNoEmitAny ()
316 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
317 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
318 Assert.AreEqual (idx, 5100);
323 public void TestDispose1 ()
325 UnixSignal a = new UnixSignal (Signum.SIGINT);
326 UnixSignal b = new UnixSignal (Signum.SIGINT);
328 Stdlib.raise (Signum.SIGINT);
330 Assert.AreEqual (a.Count, 1);
331 Assert.AreEqual (b.Count, 1);
336 Stdlib.raise (Signum.SIGINT);
337 Assert.AreEqual (b.Count, 1);
343 public void TestDispose2 ()
345 UnixSignal a = new UnixSignal (Signum.SIGINT);
346 UnixSignal b = new UnixSignal (Signum.SIGINT);
348 Stdlib.raise (Signum.SIGINT);
350 Assert.AreEqual (a.Count, 1);
351 Assert.AreEqual (b.Count, 1);
356 Stdlib.raise (Signum.SIGINT);
357 Assert.AreEqual (a.Count, 1);
363 public void TestSignalActionInteraction ()
365 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
366 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
367 Stdlib.raise (Signum.SIGINT);
368 Assert.AreEqual (a.Count, 0); // never invoked
372 static readonly Signum[] signals = new Signum[] {
373 Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
376 const int StormCount = 100000;
379 [Category("NotOnMac")] // OSX signal storming will not deliver every one
380 public void TestRaiseStorm ()
382 UnixSignal[] usignals = CreateSignals (signals);
383 Thread[] threads = new Thread[]{
384 CreateRaiseStormThread (StormCount/4),
385 CreateRaiseStormThread (StormCount/4),
386 CreateRaiseStormThread (StormCount/4),
387 CreateRaiseStormThread (StormCount/4),
389 foreach (Thread t in threads)
391 foreach (Thread t in threads)
393 AssertCount (usignals);
394 CloseSignals (usignals);
397 static void AssertCount (UnixSignal[] usignals)
400 foreach (UnixSignal s in usignals)
402 Assert.AreEqual (sum, StormCount);
405 static UnixSignal[] CreateSignals (Signum[] signals)
407 UnixSignal[] s = new UnixSignal [signals.Length];
408 for (int i = 0; i < signals.Length; ++i)
409 s [i] = new UnixSignal (signals [i]);
413 static void CloseSignals (UnixSignal[] signals)
415 foreach (UnixSignal s in signals)
419 static Thread CreateRaiseStormThread (int max)
421 return new Thread (delegate () {
422 Random r = new Random (Environment.TickCount);
423 for (int i = 0; i < max; ++i) {
424 int n = r.Next (0, signals.Length);
425 Stdlib.raise (signals [n]);
431 [Category("NotOnMac")] // OSX signal storming will not deliver every one
432 public void TestAddRemove ()
434 UnixSignal[] usignals = CreateSignals (signals);
436 Thread[] threads = new Thread[]{
437 CreateRaiseStormThread (StormCount),
438 CreateSignalCreatorThread (),
441 foreach (Thread t in threads)
443 foreach (Thread t in threads)
446 AssertCount (usignals);
447 CloseSignals (usignals);
450 static Thread CreateSignalCreatorThread ()
452 return new Thread (delegate () {
453 Random r = new Random (Environment.TickCount << 4);
454 for (int i = 0; i < StormCount; ++i) {
455 int n = r.Next (0, signals.Length);
456 using (new UnixSignal (signals [n]))
457 using (new UnixSignal (signals [(n+1)%signals.Length]))
458 using (new UnixSignal (signals [(n+2)%signals.Length]))
459 using (new UnixSignal (signals [(n+3)%signals.Length])) {
466 [Category("NotOnMac")] // OSX signal storming will not deliver every one
467 public void TestWaitAny ()
469 UnixSignal[] usignals = CreateSignals (signals);
471 Thread[] threads = new Thread[]{
472 CreateRaiseStormThread (StormCount),
473 CreateSignalCreatorThread (),
474 CreateWaitAnyThread (usignals [0], usignals [2]),
475 CreateWaitAnyThread (usignals [1], usignals [3]),
476 CreateWaitAnyThread (usignals [1], usignals [2]),
479 foreach (Thread t in threads)
481 foreach (Thread t in threads)
484 AssertCount (usignals);
485 CloseSignals (usignals);
488 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
490 return new Thread (delegate () {
491 int idx = UnixSignal.WaitAny (usignals, 30000);
492 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);