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 TestSignumProperty ()
52 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
53 Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
57 [Category ("NotOnMac")]
58 public void TestRealTimeCstor ()
60 RealTimeSignum rts = new RealTimeSignum (0);
61 using (UnixSignal s = new UnixSignal (rts))
63 Assert.That(s.IsRealTimeSignal);
64 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
70 [Category ("NotOnMac")]
71 public void TestSignumPropertyThrows ()
73 UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
74 Signum s = signal1.Signum;
78 [Category ("NotOnMac")]
79 public void TestRealTimeSignumProperty ()
81 RealTimeSignum rts = new RealTimeSignum (0);
82 UnixSignal signal1 = new UnixSignal (rts);
83 Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
88 [Category ("NotOnMac")]
89 public void TestRealTimePropertyThrows ()
91 UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
92 RealTimeSignum s = signal1.RealTimeSignum;
96 [Category ("NotOnMac")]
97 public void TestRaiseRTMINSignal ()
99 RealTimeSignum rts = new RealTimeSignum (0);
100 using (UnixSignal signal = new UnixSignal (rts))
102 MultiThreadTest (signal, 5000, delegate() {
110 [Category ("NotOnMac")]
111 public void TestRaiseRTMINPlusOneSignal ()
113 /*this number is a guestimate, but it's ok*/
114 for (int i = 1; i < 10; ++i) {
115 RealTimeSignum rts = new RealTimeSignum (i);
118 signal = new UnixSignal (rts);
119 } catch (ArgumentException) { /*skip the ones that are unavailable*/
124 MultiThreadTest (signal, 5000, delegate() {
131 Assert.IsTrue (false, "#1 No available RT signal");
135 [Category ("NotOnMac")]
136 public void TestCanRegisterRTSignalMultipleTimes ()
138 /*this number is a guestimate, but it's ok*/
139 for (int i = 1; i < 10; ++i) {
140 RealTimeSignum rts = new RealTimeSignum (i);
143 signal = new UnixSignal (rts);
144 } catch (ArgumentException) { /*skip the ones that are unavailable*/
148 using (UnixSignal signal2 = new UnixSignal (rts))
153 } catch (ArgumentException) { /*skip the ones that are unavailable*/
154 Assert.IsTrue (false, "#1 Could not register second signal handler");
157 Assert.IsTrue (false, "#2 No available RT signal");
161 public void TestRaise ()
163 Thread t1 = new Thread (delegate () {
164 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
165 DateTime start = DateTime.Now;
166 bool r = a.WaitOne (5000, false);
167 DateTime end = DateTime.Now;
168 Assert.AreEqual (a.Count, 1);
169 Assert.AreEqual (r, true);
170 if ((end - start) > new TimeSpan (0, 0, 5))
171 throw new InvalidOperationException ("Signal slept too long");
174 Thread t2 = new Thread (delegate () {
176 Stdlib.raise (Signum.SIGINT);
185 public void TestRaiseAny ()
187 Thread t1 = new Thread (delegate () {
188 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
189 DateTime start = DateTime.Now;
190 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
191 DateTime end = DateTime.Now;
192 Assert.AreEqual (idx, 0);
193 Assert.AreEqual (a.Count, 1);
194 if ((end - start) > new TimeSpan (0, 0, 5))
195 throw new InvalidOperationException ("Signal slept too long");
198 Thread t2 = new Thread (delegate () {
200 Stdlib.raise (Signum.SIGINT);
209 public void TestSeparation ()
211 Thread t1 = new Thread (delegate () {
212 using (UnixSignal a = new UnixSignal (Signum.SIGINT))
213 using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
214 DateTime start = DateTime.Now;
215 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
216 DateTime end = DateTime.Now;
217 Assert.AreEqual (idx, 1);
218 Assert.AreEqual (a.Count, 0);
219 Assert.AreEqual (b.Count, 1);
220 if ((end - start) > new TimeSpan (0, 0, 5))
221 throw new InvalidOperationException ("Signal slept too long");
224 Thread t2 = new Thread (delegate () {
226 Stdlib.raise (Signum.SIGTERM);
235 public void TestNoEmit ()
237 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
238 DateTime start = DateTime.Now;
239 bool r = u.WaitOne (5100, false);
240 Assert.AreEqual (r, false);
241 DateTime end = DateTime.Now;
242 if ((end - start) < new TimeSpan (0, 0, 5))
243 throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
248 public void TestNoEmitAny ()
250 using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
251 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
252 Assert.AreEqual (idx, 5100);
257 public void TestDispose1 ()
259 UnixSignal a = new UnixSignal (Signum.SIGINT);
260 UnixSignal b = new UnixSignal (Signum.SIGINT);
262 Stdlib.raise (Signum.SIGINT);
264 Assert.AreEqual (a.Count, 1);
265 Assert.AreEqual (b.Count, 1);
270 Stdlib.raise (Signum.SIGINT);
271 Assert.AreEqual (b.Count, 1);
277 public void TestDispose2 ()
279 UnixSignal a = new UnixSignal (Signum.SIGINT);
280 UnixSignal b = new UnixSignal (Signum.SIGINT);
282 Stdlib.raise (Signum.SIGINT);
284 Assert.AreEqual (a.Count, 1);
285 Assert.AreEqual (b.Count, 1);
290 Stdlib.raise (Signum.SIGINT);
291 Assert.AreEqual (a.Count, 1);
297 public void TestSignalActionInteraction ()
299 using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
300 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
301 Stdlib.raise (Signum.SIGINT);
302 Assert.AreEqual (a.Count, 0); // never invoked
306 static readonly Signum[] signals = new Signum[] {
307 Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
310 const int StormCount = 100000;
313 [Category("NotOnMac")] // OSX signal storming will not deliver every one
314 public void TestRaiseStorm ()
316 UnixSignal[] usignals = CreateSignals (signals);
317 Thread[] threads = new Thread[]{
318 CreateRaiseStormThread (StormCount/4),
319 CreateRaiseStormThread (StormCount/4),
320 CreateRaiseStormThread (StormCount/4),
321 CreateRaiseStormThread (StormCount/4),
323 foreach (Thread t in threads)
325 foreach (Thread t in threads)
327 AssertCount (usignals);
328 CloseSignals (usignals);
331 static void AssertCount (UnixSignal[] usignals)
334 foreach (UnixSignal s in usignals)
336 Assert.AreEqual (sum, StormCount);
339 static UnixSignal[] CreateSignals (Signum[] signals)
341 UnixSignal[] s = new UnixSignal [signals.Length];
342 for (int i = 0; i < signals.Length; ++i)
343 s [i] = new UnixSignal (signals [i]);
347 static void CloseSignals (UnixSignal[] signals)
349 foreach (UnixSignal s in signals)
353 static Thread CreateRaiseStormThread (int max)
355 return new Thread (delegate () {
356 Random r = new Random (Environment.TickCount);
357 for (int i = 0; i < max; ++i) {
358 int n = r.Next (0, signals.Length);
359 Stdlib.raise (signals [n]);
365 [Category("NotOnMac")] // OSX signal storming will not deliver every one
366 public void TestAddRemove ()
368 UnixSignal[] usignals = CreateSignals (signals);
370 Thread[] threads = new Thread[]{
371 CreateRaiseStormThread (StormCount),
372 CreateSignalCreatorThread (),
375 foreach (Thread t in threads)
377 foreach (Thread t in threads)
380 AssertCount (usignals);
381 CloseSignals (usignals);
384 static Thread CreateSignalCreatorThread ()
386 return new Thread (delegate () {
387 Random r = new Random (Environment.TickCount << 4);
388 for (int i = 0; i < StormCount; ++i) {
389 int n = r.Next (0, signals.Length);
390 using (new UnixSignal (signals [n]))
391 using (new UnixSignal (signals [(n+1)%signals.Length]))
392 using (new UnixSignal (signals [(n+2)%signals.Length]))
393 using (new UnixSignal (signals [(n+3)%signals.Length])) {
400 [Category("NotOnMac")] // OSX signal storming will not deliver every one
401 public void TestWaitAny ()
403 UnixSignal[] usignals = CreateSignals (signals);
405 Thread[] threads = new Thread[]{
406 CreateRaiseStormThread (StormCount),
407 CreateSignalCreatorThread (),
408 CreateWaitAnyThread (usignals [0], usignals [2]),
409 CreateWaitAnyThread (usignals [1], usignals [3]),
410 CreateWaitAnyThread (usignals [1], usignals [2]),
413 foreach (Thread t in threads)
415 foreach (Thread t in threads)
418 AssertCount (usignals);
419 CloseSignals (usignals);
422 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
424 return new Thread (delegate () {
425 int idx = UnixSignal.WaitAny (usignals, 30000);
426 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);