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.Native;
20 namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
22 namespace MonoTests.Mono.Unix {
25 public class UnixSignalTest {
27 // helper method to create a thread waiting on a UnixSignal
28 static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
30 Thread t1 = new Thread(delegate() {
31 DateTime start = DateTime.Now;
32 bool r = signal.WaitOne (timeout, false);
33 DateTime end = DateTime.Now;
34 Assert.AreEqual (signal.Count, 1);
35 Assert.AreEqual (r, true);
36 if ((end - start) > new TimeSpan (0, 0, timeout/1000))
37 throw new InvalidOperationException ("Signal slept too long");
42 // helper method to create a two-thread test
43 static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
45 Thread t1 = CreateWaitSignalThread (signal, timeout);
46 Thread t2 = new Thread (tstart);
54 public void TestNestedInvocation()
56 UnixSignal s = new UnixSignal(Signum.SIGINT);
57 Thread a = new Thread(delegate() {
58 bool r = s.WaitOne (1000, false);
60 Thread b = new Thread(delegate() {
61 bool r = s.WaitOne (500, false);
70 public void TestWaitAnyFailsWithMore64Signals()
72 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
73 UnixSignal[] signals = new UnixSignal[65];
74 for (int i=0; i<65; ++i)
77 Assert.That(UnixSignal.WaitAny(signals, new TimeSpan(0,0,1)), Is.EqualTo(-1));
81 public void TestConcurrentWaitOne()
83 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
84 UnixSignal s2 = new UnixSignal(Signum.SIGINT);
85 Thread a = CreateWaitSignalThread(s1, 10000);
86 Thread b = CreateWaitSignalThread(s2, 5000);
87 Thread c = new Thread (delegate () {
89 Stdlib.raise (Signum.SIGINT);
97 Assert.That(s1.Count, Is.EqualTo(1), "Expected 1 signal raised");
98 Assert.That(s2.Count, Is.EqualTo(1), "Expected 1 signal raised");
102 public void TestConcurrentWaitOneSameInstance()
104 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
105 Thread a = CreateWaitSignalThread(s1, 10000);
106 Thread b = CreateWaitSignalThread(s1, 10000);
107 Thread c = new Thread (delegate () {
109 Stdlib.raise (Signum.SIGINT);
120 public void TestSignumProperty ()
122 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
123 Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
127 [Category ("NotOnMac")]
128 public void TestRealTimeCstor ()
130 RealTimeSignum rts = new RealTimeSignum (0);
131 using (UnixSignal s = new UnixSignal (rts))
133 Assert.That(s.IsRealTimeSignal);
134 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
140 [Category ("NotOnMac")]
141 public void TestSignumPropertyThrows ()
143 UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
144 Signum s = signal1.Signum;
148 [Category ("NotOnMac")]
149 public void TestRealTimeSignumProperty ()
151 RealTimeSignum rts = new RealTimeSignum (0);
152 UnixSignal signal1 = new UnixSignal (rts);
153 Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
158 [Category ("NotOnMac")]
159 public void TestRealTimePropertyThrows ()
161 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
162 RealTimeSignum s = signal1.RealTimeSignum;
166 [Category ("NotOnMac")]
167 public void TestRaiseRTMINSignal ()
169 RealTimeSignum rts = new RealTimeSignum (0);
170 using (UnixSignal signal = new UnixSignal (rts))
172 MultiThreadTest (signal, 5000, delegate() {
180 [Category ("NotOnMac")]
181 public void TestRaiseRTMINPlusOneSignal ()
183 /*this number is a guestimate, but it's ok*/
184 for (int i = 1; i < 10; ++i) {
185 RealTimeSignum rts = new RealTimeSignum (i);
188 signal = new UnixSignal (rts);
189 } catch (ArgumentException) { /*skip the ones that are unavailable*/
194 MultiThreadTest (signal, 5000, delegate() {
201 Assert.IsTrue (false, "#1 No available RT signal");
205 [Category ("NotOnMac")]
206 public void TestCanRegisterRTSignalMultipleTimes ()
208 /*this number is a guestimate, but it's ok*/
209 for (int i = 1; i < 10; ++i) {
210 RealTimeSignum rts = new RealTimeSignum (i);
213 signal = new UnixSignal (rts);
214 } catch (ArgumentException) { /*skip the ones that are unavailable*/
218 using (UnixSignal signal2 = new UnixSignal (rts))
223 } catch (ArgumentException) { /*skip the ones that are unavailable*/
224 Assert.IsTrue (false, "#1 Could not register second signal handler");
227 Assert.IsTrue (false, "#2 No available RT signal");
231 public void TestRaise ()
233 Thread t1 = new Thread (delegate () {
234 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
235 DateTime start = DateTime.Now;
236 bool r = a.WaitOne (5000, false);
237 DateTime end = DateTime.Now;
238 Assert.AreEqual (a.Count, 1);
239 Assert.AreEqual (r, true);
240 if ((end - start) > new TimeSpan (0, 0, 5))
241 throw new InvalidOperationException ("Signal slept too long");
244 Thread t2 = new Thread (delegate () {
246 Stdlib.raise (Signum.SIGINT);
255 public void TestRaiseAny ()
257 Thread t1 = new Thread (delegate () {
258 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
259 DateTime start = DateTime.Now;
260 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
261 DateTime end = DateTime.Now;
262 Assert.AreEqual (idx, 0);
263 Assert.AreEqual (a.Count, 1);
264 if ((end - start) > new TimeSpan (0, 0, 5))
265 throw new InvalidOperationException ("Signal slept too long");
268 Thread t2 = new Thread (delegate () {
270 Stdlib.raise (Signum.SIGINT);
279 public void TestSeparation ()
281 Thread t1 = new Thread (delegate () {
282 using (UnixSignal a = new UnixSignal (Signum.SIGINT))
283 using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
284 DateTime start = DateTime.Now;
285 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
286 DateTime end = DateTime.Now;
287 Assert.AreEqual (idx, 1);
288 Assert.AreEqual (a.Count, 0);
289 Assert.AreEqual (b.Count, 1);
290 if ((end - start) > new TimeSpan (0, 0, 5))
291 throw new InvalidOperationException ("Signal slept too long");
294 Thread t2 = new Thread (delegate () {
296 Stdlib.raise (Signum.SIGTERM);
305 public void TestNoEmit ()
307 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
308 DateTime start = DateTime.Now;
309 bool r = u.WaitOne (5100, false);
310 Assert.AreEqual (r, false);
311 DateTime end = DateTime.Now;
312 if ((end - start) < new TimeSpan (0, 0, 5))
313 throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
318 public void TestNoEmitAny ()
320 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
321 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
322 Assert.AreEqual (idx, 5100);
327 public void TestDispose1 ()
329 UnixSignal a = new UnixSignal (Signum.SIGINT);
330 UnixSignal b = new UnixSignal (Signum.SIGINT);
332 Stdlib.raise (Signum.SIGINT);
333 SleepUntilSignaled (a);
335 Assert.AreEqual (a.Count, 1);
336 Assert.AreEqual (b.Count, 1);
341 Stdlib.raise (Signum.SIGINT);
342 SleepUntilSignaled (b);
343 Assert.AreEqual (b.Count, 1);
348 static void SleepUntilSignaled (UnixSignal s)
350 for (int i = 0; i < 10; ++i) {
358 public void TestDispose2 ()
360 UnixSignal a = new UnixSignal (Signum.SIGINT);
361 UnixSignal b = new UnixSignal (Signum.SIGINT);
363 Stdlib.raise (Signum.SIGINT);
364 SleepUntilSignaled (a);
366 Assert.AreEqual (a.Count, 1);
367 Assert.AreEqual (b.Count, 1);
372 Stdlib.raise (Signum.SIGINT);
373 SleepUntilSignaled (a);
374 Assert.AreEqual (a.Count, 1);
380 [Category ("AndroidNotWorking")] // Android 4.4.4 doesn't have signal(2)
381 public void TestSignalActionInteraction ()
383 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
384 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
385 Stdlib.raise (Signum.SIGINT);
386 Assert.AreEqual (a.Count, 0); // never invoked
390 static readonly Signum[] signals = new Signum[] {
391 Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
394 const int StormCount = 100000;
397 [Category("NotOnMac")] // OSX signal storming will not deliver every one
398 public void TestRaiseStorm ()
400 UnixSignal[] usignals = CreateSignals (signals);
401 Thread[] threads = new Thread[]{
402 CreateRaiseStormThread (StormCount/4),
403 CreateRaiseStormThread (StormCount/4),
404 CreateRaiseStormThread (StormCount/4),
405 CreateRaiseStormThread (StormCount/4),
407 foreach (Thread t in threads)
409 foreach (Thread t in threads)
411 AssertCount (usignals);
412 CloseSignals (usignals);
415 static void AssertCount (UnixSignal[] usignals)
418 foreach (UnixSignal s in usignals)
420 Assert.AreEqual (sum, StormCount);
423 static UnixSignal[] CreateSignals (Signum[] signals)
425 UnixSignal[] s = new UnixSignal [signals.Length];
426 for (int i = 0; i < signals.Length; ++i)
427 s [i] = new UnixSignal (signals [i]);
431 static void CloseSignals (UnixSignal[] signals)
433 foreach (UnixSignal s in signals)
437 static Thread CreateRaiseStormThread (int max)
439 return new Thread (delegate () {
440 Random r = new Random (Environment.TickCount);
441 for (int i = 0; i < max; ++i) {
442 int n = r.Next (0, signals.Length);
443 Stdlib.raise (signals [n]);
449 [Category("NotOnMac")] // OSX signal storming will not deliver every one
450 public void TestAddRemove ()
452 UnixSignal[] usignals = CreateSignals (signals);
454 Thread[] threads = new Thread[]{
455 CreateRaiseStormThread (StormCount),
456 CreateSignalCreatorThread (),
459 foreach (Thread t in threads)
461 foreach (Thread t in threads)
464 AssertCount (usignals);
465 CloseSignals (usignals);
468 static Thread CreateSignalCreatorThread ()
470 return new Thread (delegate () {
471 Random r = new Random (Environment.TickCount << 4);
472 for (int i = 0; i < StormCount; ++i) {
473 int n = r.Next (0, signals.Length);
474 using (new UnixSignal (signals [n]))
475 using (new UnixSignal (signals [(n+1)%signals.Length]))
476 using (new UnixSignal (signals [(n+2)%signals.Length]))
477 using (new UnixSignal (signals [(n+3)%signals.Length])) {
484 [Category("NotOnMac")] // OSX signal storming will not deliver every one
485 public void TestWaitAny ()
487 UnixSignal[] usignals = CreateSignals (signals);
489 Thread[] threads = new Thread[]{
490 CreateRaiseStormThread (StormCount),
491 CreateSignalCreatorThread (),
492 CreateWaitAnyThread (usignals [0], usignals [2]),
493 CreateWaitAnyThread (usignals [1], usignals [3]),
494 CreateWaitAnyThread (usignals [1], usignals [2]),
497 foreach (Thread t in threads)
499 foreach (Thread t in threads)
502 AssertCount (usignals);
503 CloseSignals (usignals);
506 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
508 return new Thread (delegate () {
509 int idx = UnixSignal.WaitAny (usignals, 30000);
510 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);