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;
12 using NUnit.Framework.SyntaxHelpers;
16 using System.Threading;
18 using Mono.Unix.Android;
19 using Mono.Unix.Native;
21 namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
23 namespace MonoTests.Mono.Unix {
26 public class UnixSignalTest {
28 // helper method to create a thread waiting on a UnixSignal
29 static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
31 Thread t1 = new Thread(delegate() {
32 DateTime start = DateTime.Now;
33 bool r = signal.WaitOne (timeout, false);
34 DateTime end = DateTime.Now;
35 Assert.AreEqual (signal.Count, 1);
36 Assert.AreEqual (r, true);
37 if ((end - start) > new TimeSpan (0, 0, timeout/1000))
38 throw new InvalidOperationException ("Signal slept too long");
43 // helper method to create a two-thread test
44 static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
46 Thread t1 = CreateWaitSignalThread (signal, timeout);
47 Thread t2 = new Thread (tstart);
55 public void TestNestedInvocation()
57 UnixSignal s = new UnixSignal(Signum.SIGINT);
58 Thread a = new Thread(delegate() {
59 bool r = s.WaitOne (1000, false);
61 Thread b = new Thread(delegate() {
62 bool r = s.WaitOne (500, false);
71 public void TestWaitAnyFailsWithMore64Signals()
73 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
74 UnixSignal[] signals = new UnixSignal[65];
75 for (int i=0; i<65; ++i)
78 Assert.That(UnixSignal.WaitAny(signals, new TimeSpan(0,0,1)), Is.EqualTo(-1));
82 public void TestConcurrentWaitOne()
84 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
85 UnixSignal s2 = new UnixSignal(Signum.SIGINT);
86 Thread a = CreateWaitSignalThread(s1, 10000);
87 Thread b = CreateWaitSignalThread(s2, 5000);
88 Thread c = new Thread (delegate () {
90 Stdlib.raise (Signum.SIGINT);
98 Assert.That(s1.Count, Is.EqualTo(1), "Expected 1 signal raised");
99 Assert.That(s2.Count, Is.EqualTo(1), "Expected 1 signal raised");
103 public void TestConcurrentWaitOneSameInstance()
105 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
106 Thread a = CreateWaitSignalThread(s1, 10000);
107 Thread b = CreateWaitSignalThread(s1, 10000);
108 Thread c = new Thread (delegate () {
110 Stdlib.raise (Signum.SIGINT);
121 public void TestSignumProperty ()
123 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
124 Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
128 [Category ("NotOnMac")]
129 public void TestRealTimeCstor ()
131 if (!TestHelper.CanUseRealTimeSignals ())
133 RealTimeSignum rts = new RealTimeSignum (0);
134 using (UnixSignal s = new UnixSignal (rts))
136 Assert.That(s.IsRealTimeSignal);
137 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
143 [Category ("NotOnMac")]
144 public void TestSignumPropertyThrows ()
146 if (!TestHelper.CanUseRealTimeSignals ())
148 UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
149 Signum s = signal1.Signum;
153 [Category ("NotOnMac")]
154 public void TestRealTimeSignumProperty ()
156 if (!TestHelper.CanUseRealTimeSignals ())
158 RealTimeSignum rts = new RealTimeSignum (0);
159 UnixSignal signal1 = new UnixSignal (rts);
160 Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
165 [Category ("NotOnMac")]
166 public void TestRealTimePropertyThrows ()
168 if (!TestHelper.CanUseRealTimeSignals ())
170 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
171 RealTimeSignum s = signal1.RealTimeSignum;
175 [Category ("NotOnMac")]
176 public void TestRaiseRTMINSignal ()
178 if (!TestHelper.CanUseRealTimeSignals ())
180 RealTimeSignum rts = new RealTimeSignum (0);
181 using (UnixSignal signal = new UnixSignal (rts))
183 MultiThreadTest (signal, 5000, delegate() {
191 [Category ("NotOnMac")]
192 public void TestRaiseRTMINPlusOneSignal ()
194 if (!TestHelper.CanUseRealTimeSignals ())
196 /*this number is a guestimate, but it's ok*/
197 for (int i = 1; i < 10; ++i) {
198 RealTimeSignum rts = new RealTimeSignum (i);
201 signal = new UnixSignal (rts);
202 } catch (ArgumentException) { /*skip the ones that are unavailable*/
207 MultiThreadTest (signal, 5000, delegate() {
214 Assert.IsTrue (false, "#1 No available RT signal");
218 [Category ("NotOnMac")]
219 public void TestCanRegisterRTSignalMultipleTimes ()
221 if (!TestHelper.CanUseRealTimeSignals ())
223 /*this number is a guestimate, but it's ok*/
224 for (int i = 1; i < 10; ++i) {
225 RealTimeSignum rts = new RealTimeSignum (i);
228 signal = new UnixSignal (rts);
229 } catch (ArgumentException) { /*skip the ones that are unavailable*/
233 using (UnixSignal signal2 = new UnixSignal (rts))
238 } catch (ArgumentException) { /*skip the ones that are unavailable*/
239 Assert.IsTrue (false, "#1 Could not register second signal handler");
242 Assert.IsTrue (false, "#2 No available RT signal");
246 public void TestRaise ()
248 Thread t1 = new Thread (delegate () {
249 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
250 DateTime start = DateTime.Now;
251 bool r = a.WaitOne (5000, false);
252 DateTime end = DateTime.Now;
253 Assert.AreEqual (a.Count, 1);
254 Assert.AreEqual (r, true);
255 if ((end - start) > new TimeSpan (0, 0, 5))
256 throw new InvalidOperationException ("Signal slept too long");
259 Thread t2 = new Thread (delegate () {
261 Stdlib.raise (Signum.SIGINT);
270 public void TestRaiseAny ()
272 Thread t1 = new Thread (delegate () {
273 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
274 DateTime start = DateTime.Now;
275 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
276 DateTime end = DateTime.Now;
277 Assert.AreEqual (idx, 0);
278 Assert.AreEqual (a.Count, 1);
279 if ((end - start) > new TimeSpan (0, 0, 5))
280 throw new InvalidOperationException ("Signal slept too long");
283 Thread t2 = new Thread (delegate () {
285 Stdlib.raise (Signum.SIGINT);
294 public void TestSeparation ()
296 Thread t1 = new Thread (delegate () {
297 using (UnixSignal a = new UnixSignal (Signum.SIGINT))
298 using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
299 DateTime start = DateTime.Now;
300 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
301 DateTime end = DateTime.Now;
302 Assert.AreEqual (idx, 1);
303 Assert.AreEqual (a.Count, 0);
304 Assert.AreEqual (b.Count, 1);
305 if ((end - start) > new TimeSpan (0, 0, 5))
306 throw new InvalidOperationException ("Signal slept too long");
309 Thread t2 = new Thread (delegate () {
311 Stdlib.raise (Signum.SIGTERM);
320 public void TestNoEmit ()
322 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
323 DateTime start = DateTime.Now;
324 bool r = u.WaitOne (5100, false);
325 Assert.AreEqual (r, false);
326 DateTime end = DateTime.Now;
327 if ((end - start) < new TimeSpan (0, 0, 5))
328 throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
333 public void TestNoEmitAny ()
335 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
336 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
337 Assert.AreEqual (idx, 5100);
342 public void TestDispose1 ()
344 UnixSignal a = new UnixSignal (Signum.SIGINT);
345 UnixSignal b = new UnixSignal (Signum.SIGINT);
347 Stdlib.raise (Signum.SIGINT);
348 SleepUntilSignaled (a);
350 Assert.AreEqual (a.Count, 1);
351 Assert.AreEqual (b.Count, 1);
356 Stdlib.raise (Signum.SIGINT);
357 SleepUntilSignaled (b);
358 Assert.AreEqual (b.Count, 1);
363 static void SleepUntilSignaled (UnixSignal s)
365 for (int i = 0; i < 10; ++i) {
373 public void TestDispose2 ()
375 UnixSignal a = new UnixSignal (Signum.SIGINT);
376 UnixSignal b = new UnixSignal (Signum.SIGINT);
378 Stdlib.raise (Signum.SIGINT);
379 SleepUntilSignaled (a);
381 Assert.AreEqual (a.Count, 1);
382 Assert.AreEqual (b.Count, 1);
387 Stdlib.raise (Signum.SIGINT);
388 SleepUntilSignaled (a);
389 Assert.AreEqual (a.Count, 1);
395 [Category ("AndroidNotWorking")] // Android 4.4.4 doesn't have signal(2)
396 public void TestSignalActionInteraction ()
398 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
399 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
400 Stdlib.raise (Signum.SIGINT);
401 Assert.AreEqual (a.Count, 0); // never invoked
405 static readonly Signum[] signals = new Signum[] {
406 Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
409 const int StormCount = 100000;
412 [Category("NotOnMac")] // OSX signal storming will not deliver every one
413 public void TestRaiseStorm ()
415 UnixSignal[] usignals = CreateSignals (signals);
416 Thread[] threads = new Thread[]{
417 CreateRaiseStormThread (StormCount/4),
418 CreateRaiseStormThread (StormCount/4),
419 CreateRaiseStormThread (StormCount/4),
420 CreateRaiseStormThread (StormCount/4),
422 foreach (Thread t in threads)
424 foreach (Thread t in threads)
426 AssertCount (usignals);
427 CloseSignals (usignals);
430 static void AssertCount (UnixSignal[] usignals)
433 foreach (UnixSignal s in usignals)
435 Assert.AreEqual (sum, StormCount);
438 static UnixSignal[] CreateSignals (Signum[] signals)
440 UnixSignal[] s = new UnixSignal [signals.Length];
441 for (int i = 0; i < signals.Length; ++i)
442 s [i] = new UnixSignal (signals [i]);
446 static void CloseSignals (UnixSignal[] signals)
448 foreach (UnixSignal s in signals)
452 static Thread CreateRaiseStormThread (int max)
454 return new Thread (delegate () {
455 Random r = new Random (Environment.TickCount);
456 for (int i = 0; i < max; ++i) {
457 int n = r.Next (0, signals.Length);
458 Stdlib.raise (signals [n]);
464 [Category("NotOnMac")] // OSX signal storming will not deliver every one
465 public void TestAddRemove ()
467 UnixSignal[] usignals = CreateSignals (signals);
469 Thread[] threads = new Thread[]{
470 CreateRaiseStormThread (StormCount),
471 CreateSignalCreatorThread (),
474 foreach (Thread t in threads)
476 foreach (Thread t in threads)
479 AssertCount (usignals);
480 CloseSignals (usignals);
483 static Thread CreateSignalCreatorThread ()
485 return new Thread (delegate () {
486 Random r = new Random (Environment.TickCount << 4);
487 for (int i = 0; i < StormCount; ++i) {
488 int n = r.Next (0, signals.Length);
489 using (new UnixSignal (signals [n]))
490 using (new UnixSignal (signals [(n+1)%signals.Length]))
491 using (new UnixSignal (signals [(n+2)%signals.Length]))
492 using (new UnixSignal (signals [(n+3)%signals.Length])) {
499 [Category("NotOnMac")] // OSX signal storming will not deliver every one
500 public void TestWaitAny ()
502 UnixSignal[] usignals = CreateSignals (signals);
504 Thread[] threads = new Thread[]{
505 CreateRaiseStormThread (StormCount),
506 CreateSignalCreatorThread (),
507 CreateWaitAnyThread (usignals [0], usignals [2]),
508 CreateWaitAnyThread (usignals [1], usignals [3]),
509 CreateWaitAnyThread (usignals [1], usignals [2]),
512 foreach (Thread t in threads)
514 foreach (Thread t in threads)
517 AssertCount (usignals);
518 CloseSignals (usignals);
521 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
523 return new Thread (delegate () {
524 int idx = UnixSignal.WaitAny (usignals, 30000);
525 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);