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 NUnit.Framework.SyntaxHelpers { class Dummy {} }
20 namespace MonoTests.Mono.Unix {
23 public class UnixSignalTest {
25 // helper method to create a thread waiting on a UnixSignal
26 static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
28 Thread t1 = new Thread(delegate() {
29 DateTime start = DateTime.Now;
30 bool r = signal.WaitOne (timeout, false);
31 DateTime end = DateTime.Now;
32 Assert.AreEqual (signal.Count, 1);
33 Assert.AreEqual (r, true);
34 if ((end - start) > new TimeSpan (0, 0, timeout/1000))
35 throw new InvalidOperationException ("Signal slept too long");
40 // helper method to create a two-thread test
41 static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
43 Thread t1 = CreateWaitSignalThread (signal, timeout);
44 Thread t2 = new Thread (tstart);
52 public void TestNestedInvocation()
54 UnixSignal s = new UnixSignal(Signum.SIGINT);
55 Thread a = new Thread(delegate() {
56 bool r = s.WaitOne (1000, false);
58 Thread b = new Thread(delegate() {
59 bool r = s.WaitOne (500, false);
68 public void TestWaitAnyFailsWithMore64Signals()
70 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
71 UnixSignal[] signals = new UnixSignal[65];
72 for (int i=0; i<65; ++i)
75 Assert.That(UnixSignal.WaitAny(signals, new TimeSpan(0,0,1)), Is.EqualTo(-1));
79 public void TestConcurrentWaitOne()
81 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
82 UnixSignal s2 = new UnixSignal(Signum.SIGINT);
83 Thread a = CreateWaitSignalThread(s1, 10000);
84 Thread b = CreateWaitSignalThread(s2, 5000);
85 Thread c = new Thread (delegate () {
87 Stdlib.raise (Signum.SIGINT);
95 Assert.That(s1.Count, Is.EqualTo(1), "Expected 1 signal raised");
96 Assert.That(s2.Count, Is.EqualTo(1), "Expected 1 signal raised");
100 public void TestConcurrentWaitOneSameInstance()
102 UnixSignal s1 = new UnixSignal(Signum.SIGINT);
103 Thread a = CreateWaitSignalThread(s1, 10000);
104 Thread b = CreateWaitSignalThread(s1, 10000);
105 Thread c = new Thread (delegate () {
107 Stdlib.raise (Signum.SIGINT);
118 public void TestSignumProperty ()
120 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
121 Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
125 [Category ("NotOnMac")]
126 public void TestRealTimeCstor ()
128 RealTimeSignum rts = new RealTimeSignum (0);
129 using (UnixSignal s = new UnixSignal (rts))
131 Assert.That(s.IsRealTimeSignal);
132 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
138 [Category ("NotOnMac")]
139 public void TestSignumPropertyThrows ()
141 UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
142 Signum s = signal1.Signum;
146 [Category ("NotOnMac")]
147 public void TestRealTimeSignumProperty ()
149 RealTimeSignum rts = new RealTimeSignum (0);
150 UnixSignal signal1 = new UnixSignal (rts);
151 Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
156 [Category ("NotOnMac")]
157 public void TestRealTimePropertyThrows ()
159 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
160 RealTimeSignum s = signal1.RealTimeSignum;
164 [Category ("NotOnMac")]
165 public void TestRaiseRTMINSignal ()
167 RealTimeSignum rts = new RealTimeSignum (0);
168 using (UnixSignal signal = new UnixSignal (rts))
170 MultiThreadTest (signal, 5000, delegate() {
178 [Category ("NotOnMac")]
179 public void TestRaiseRTMINPlusOneSignal ()
181 /*this number is a guestimate, but it's ok*/
182 for (int i = 1; i < 10; ++i) {
183 RealTimeSignum rts = new RealTimeSignum (i);
186 signal = new UnixSignal (rts);
187 } catch (ArgumentException) { /*skip the ones that are unavailable*/
192 MultiThreadTest (signal, 5000, delegate() {
199 Assert.IsTrue (false, "#1 No available RT signal");
203 [Category ("NotOnMac")]
204 public void TestCanRegisterRTSignalMultipleTimes ()
206 /*this number is a guestimate, but it's ok*/
207 for (int i = 1; i < 10; ++i) {
208 RealTimeSignum rts = new RealTimeSignum (i);
211 signal = new UnixSignal (rts);
212 } catch (ArgumentException) { /*skip the ones that are unavailable*/
216 using (UnixSignal signal2 = new UnixSignal (rts))
221 } catch (ArgumentException) { /*skip the ones that are unavailable*/
222 Assert.IsTrue (false, "#1 Could not register second signal handler");
225 Assert.IsTrue (false, "#2 No available RT signal");
229 public void TestRaise ()
231 Thread t1 = new Thread (delegate () {
232 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
233 DateTime start = DateTime.Now;
234 bool r = a.WaitOne (5000, false);
235 DateTime end = DateTime.Now;
236 Assert.AreEqual (a.Count, 1);
237 Assert.AreEqual (r, true);
238 if ((end - start) > new TimeSpan (0, 0, 5))
239 throw new InvalidOperationException ("Signal slept too long");
242 Thread t2 = new Thread (delegate () {
244 Stdlib.raise (Signum.SIGINT);
253 public void TestRaiseAny ()
255 Thread t1 = new Thread (delegate () {
256 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
257 DateTime start = DateTime.Now;
258 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
259 DateTime end = DateTime.Now;
260 Assert.AreEqual (idx, 0);
261 Assert.AreEqual (a.Count, 1);
262 if ((end - start) > new TimeSpan (0, 0, 5))
263 throw new InvalidOperationException ("Signal slept too long");
266 Thread t2 = new Thread (delegate () {
268 Stdlib.raise (Signum.SIGINT);
277 public void TestSeparation ()
279 Thread t1 = new Thread (delegate () {
280 using (UnixSignal a = new UnixSignal (Signum.SIGINT))
281 using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
282 DateTime start = DateTime.Now;
283 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
284 DateTime end = DateTime.Now;
285 Assert.AreEqual (idx, 1);
286 Assert.AreEqual (a.Count, 0);
287 Assert.AreEqual (b.Count, 1);
288 if ((end - start) > new TimeSpan (0, 0, 5))
289 throw new InvalidOperationException ("Signal slept too long");
292 Thread t2 = new Thread (delegate () {
294 Stdlib.raise (Signum.SIGTERM);
303 public void TestNoEmit ()
305 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
306 DateTime start = DateTime.Now;
307 bool r = u.WaitOne (5100, false);
308 Assert.AreEqual (r, false);
309 DateTime end = DateTime.Now;
310 if ((end - start) < new TimeSpan (0, 0, 5))
311 throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
316 public void TestNoEmitAny ()
318 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
319 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
320 Assert.AreEqual (idx, 5100);
325 public void TestDispose1 ()
327 UnixSignal a = new UnixSignal (Signum.SIGINT);
328 UnixSignal b = new UnixSignal (Signum.SIGINT);
330 Stdlib.raise (Signum.SIGINT);
332 Assert.AreEqual (a.Count, 1);
333 Assert.AreEqual (b.Count, 1);
338 Stdlib.raise (Signum.SIGINT);
339 Assert.AreEqual (b.Count, 1);
345 public void TestDispose2 ()
347 UnixSignal a = new UnixSignal (Signum.SIGINT);
348 UnixSignal b = new UnixSignal (Signum.SIGINT);
350 Stdlib.raise (Signum.SIGINT);
352 Assert.AreEqual (a.Count, 1);
353 Assert.AreEqual (b.Count, 1);
358 Stdlib.raise (Signum.SIGINT);
359 Assert.AreEqual (a.Count, 1);
365 public void TestSignalActionInteraction ()
367 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
368 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
369 Stdlib.raise (Signum.SIGINT);
370 Assert.AreEqual (a.Count, 0); // never invoked
374 static readonly Signum[] signals = new Signum[] {
375 Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
378 const int StormCount = 100000;
381 [Category("NotOnMac")] // OSX signal storming will not deliver every one
382 public void TestRaiseStorm ()
384 UnixSignal[] usignals = CreateSignals (signals);
385 Thread[] threads = new Thread[]{
386 CreateRaiseStormThread (StormCount/4),
387 CreateRaiseStormThread (StormCount/4),
388 CreateRaiseStormThread (StormCount/4),
389 CreateRaiseStormThread (StormCount/4),
391 foreach (Thread t in threads)
393 foreach (Thread t in threads)
395 AssertCount (usignals);
396 CloseSignals (usignals);
399 static void AssertCount (UnixSignal[] usignals)
402 foreach (UnixSignal s in usignals)
404 Assert.AreEqual (sum, StormCount);
407 static UnixSignal[] CreateSignals (Signum[] signals)
409 UnixSignal[] s = new UnixSignal [signals.Length];
410 for (int i = 0; i < signals.Length; ++i)
411 s [i] = new UnixSignal (signals [i]);
415 static void CloseSignals (UnixSignal[] signals)
417 foreach (UnixSignal s in signals)
421 static Thread CreateRaiseStormThread (int max)
423 return new Thread (delegate () {
424 Random r = new Random (Environment.TickCount);
425 for (int i = 0; i < max; ++i) {
426 int n = r.Next (0, signals.Length);
427 Stdlib.raise (signals [n]);
433 [Category("NotOnMac")] // OSX signal storming will not deliver every one
434 public void TestAddRemove ()
436 UnixSignal[] usignals = CreateSignals (signals);
438 Thread[] threads = new Thread[]{
439 CreateRaiseStormThread (StormCount),
440 CreateSignalCreatorThread (),
443 foreach (Thread t in threads)
445 foreach (Thread t in threads)
448 AssertCount (usignals);
449 CloseSignals (usignals);
452 static Thread CreateSignalCreatorThread ()
454 return new Thread (delegate () {
455 Random r = new Random (Environment.TickCount << 4);
456 for (int i = 0; i < StormCount; ++i) {
457 int n = r.Next (0, signals.Length);
458 using (new UnixSignal (signals [n]))
459 using (new UnixSignal (signals [(n+1)%signals.Length]))
460 using (new UnixSignal (signals [(n+2)%signals.Length]))
461 using (new UnixSignal (signals [(n+3)%signals.Length])) {
468 [Category("NotOnMac")] // OSX signal storming will not deliver every one
469 public void TestWaitAny ()
471 UnixSignal[] usignals = CreateSignals (signals);
473 Thread[] threads = new Thread[]{
474 CreateRaiseStormThread (StormCount),
475 CreateSignalCreatorThread (),
476 CreateWaitAnyThread (usignals [0], usignals [2]),
477 CreateWaitAnyThread (usignals [1], usignals [3]),
478 CreateWaitAnyThread (usignals [1], usignals [2]),
481 foreach (Thread t in threads)
483 foreach (Thread t in threads)
486 AssertCount (usignals);
487 CloseSignals (usignals);
490 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
492 return new Thread (delegate () {
493 int idx = UnixSignal.WaitAny (usignals, 30000);
494 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);