* Test/Mono.Unix/UnixSignalTest.cs: Disable the tests that use
[mono.git] / mcs / class / Mono.Posix / Test / Mono.Unix / UnixSignalTest.cs
1 //
2 // UnixSignalTest.cs - NUnit Test Cases for Mono.Unix.UnixSignal
3 //
4 // Authors:
5 //      Jonathan Pryor  <jonpryor@vt.edu>
6 //
7 // (C) 2008 Jonathan Pryor
8 //
9
10 using NUnit.Framework;
11 using NUnit.Framework.SyntaxHelpers;
12 using System;
13 using System.Text;
14 using System.Threading;
15 using Mono.Unix;
16 using Mono.Unix.Native;
17
18 namespace MonoTests.Mono.Unix {
19
20         [TestFixture]
21         public class UnixSignalTest {
22
23                 // helper method to create a thread waiting on a UnixSignal
24                 static Thread CreateWaitSignalThread (UnixSignal signal, int timeout)
25                 {
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");
34                                         });
35                         return t1;
36                 }
37
38                 // helper method to create a two-thread test
39                 static void MultiThreadTest (UnixSignal signal, int timeout, ThreadStart tstart)
40                 {
41                         Thread t1 = CreateWaitSignalThread (signal, timeout);
42                         Thread t2 = new Thread (tstart);
43                         t1.Start ();
44                         t2.Start ();
45                         t1.Join ();
46                         t2.Join ();
47                 }
48
49                 [Test]
50                 public void TestSignumProperty ()
51                 {
52                         UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
53                         Assert.That (signal1.Signum, Is.EqualTo (Signum.SIGSEGV));
54                 }
55         
56                 [Test]
57                 [Category ("NotOnMac")]
58                 public void TestRealTimeCstor ()
59                 {
60                         RealTimeSignum rts = new RealTimeSignum (0);
61                         using (UnixSignal s = new UnixSignal (rts))
62                         {
63                                 Assert.That(s.IsRealTimeSignal);
64                                 Assert.That(s.RealTimeSignum, Is.EqualTo (rts));
65                         }
66                 }
67
68                 [Test]
69                 [ExpectedException]
70                 [Category ("NotOnMac")]
71                 public void TestSignumPropertyThrows ()
72                 {
73                         UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
74                         Signum s = signal1.Signum;
75                 }
76
77                 [Test]
78                 [Category ("NotOnMac")]
79                 public void TestRealTimeSignumProperty ()
80                 {
81                         RealTimeSignum rts = new RealTimeSignum (0);
82                         UnixSignal signal1 = new UnixSignal (rts);
83                         Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
84                 }
85         
86                 [Test]
87                 [ExpectedException]
88                 [Category ("NotOnMac")]
89                 public void TestRealTimePropertyThrows ()
90                 {
91                         UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
92                         RealTimeSignum s = signal1.RealTimeSignum;
93                 }
94
95                 [Test]
96                 [Category ("NotOnMac")]
97                 public void TestRaiseRTMINSignal ()
98                 {
99                         RealTimeSignum rts = new RealTimeSignum (0);
100                         using (UnixSignal signal = new UnixSignal (rts))
101                         {
102                                 MultiThreadTest (signal, 5000, delegate() {
103                                         Thread.Sleep (1000);
104                                         Stdlib.raise (rts);
105                                         });
106                         }
107                 }
108
109                 [Test]
110                 [Category ("NotOnMac")]
111                 public void TestRaiseRTMINPlusOneSignal ()
112                 {
113                         /*this number is a guestimate, but it's ok*/
114                         for (int i = 1; i < 10; ++i) {
115                                 RealTimeSignum rts = new RealTimeSignum (i);
116                                 UnixSignal signal;
117                                 try {
118                                         signal  = new UnixSignal (rts);
119                                 } catch (ArgumentException) { /*skip the ones that are unavailable*/
120                                         continue;
121                                 }
122                                 using (signal)
123                                 {
124                                         MultiThreadTest (signal, 5000, delegate() {
125                                                 Thread.Sleep(1000);
126                                                 Stdlib.raise(rts);
127                                                 });
128                                 }
129                                 return;
130                         }
131                         Assert.IsTrue (false, "#1 No available RT signal");
132                 }
133
134                 [Test]
135                 [Category ("NotOnMac")]
136                 public void TestCanRegisterRTSignalMultipleTimes ()
137                 {
138                         /*this number is a guestimate, but it's ok*/
139                         for (int i = 1; i < 10; ++i) {
140                                 RealTimeSignum rts = new RealTimeSignum (i);
141                                 UnixSignal signal;
142                                 try {
143                                         signal  = new UnixSignal (rts);
144                                 } catch (ArgumentException) { /*skip the ones that are unavailable*/
145                                         continue;
146                                 }
147                                 try {
148                                         using (UnixSignal signal2 =  new UnixSignal (rts))
149                                         {
150                                                 //ok
151                                                 return;
152                                         }
153                                 } catch (ArgumentException) { /*skip the ones that are unavailable*/
154                                                 Assert.IsTrue (false, "#1 Could not register second signal handler");
155                                 }
156                         }
157                         Assert.IsTrue (false, "#2 No available RT signal");
158                 }
159
160                 [Test]
161                 public void TestRaise ()
162                 {
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");
172                                         }
173                         });
174                         Thread t2 = new Thread (delegate () {
175                                         Thread.Sleep (1000);
176                                         Stdlib.raise (Signum.SIGINT);
177                         });
178                         t1.Start ();
179                         t2.Start ();
180                         t1.Join ();
181                         t2.Join ();
182                 }
183
184                 [Test]
185                 public void TestRaiseAny ()
186                 {
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");
196                                         }
197                         });
198                         Thread t2 = new Thread (delegate () {
199                                         Thread.Sleep (1000);
200                                         Stdlib.raise (Signum.SIGINT);
201                         });
202                         t1.Start ();
203                         t2.Start ();
204                         t1.Join ();
205                         t2.Join ();
206                 }
207
208                 [Test]
209                 public void TestSeparation ()
210                 {
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");
222                                         }
223                         });
224                         Thread t2 = new Thread (delegate () {
225                                         Thread.Sleep (1000);
226                                         Stdlib.raise (Signum.SIGTERM);
227                         });
228                         t1.Start ();
229                         t2.Start ();
230                         t1.Join ();
231                         t2.Join ();
232                 }
233
234                 [Test]
235                 public void TestNoEmit ()
236                 {
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());
244                         }
245                 }
246
247                 [Test]
248                 public void TestNoEmitAny ()
249                 {
250                         using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
251                                 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
252                                 Assert.AreEqual (idx, 5100);
253                         }
254                 }
255
256                 [Test]
257                 public void TestDispose1 ()
258                 {
259                         UnixSignal a = new UnixSignal (Signum.SIGINT);
260                         UnixSignal b = new UnixSignal (Signum.SIGINT);
261
262                         Stdlib.raise (Signum.SIGINT);
263
264                         Assert.AreEqual (a.Count, 1);
265                         Assert.AreEqual (b.Count, 1);
266
267                         a.Close ();
268                         b.Reset ();
269
270                         Stdlib.raise (Signum.SIGINT);
271                         Assert.AreEqual (b.Count, 1);
272
273                         b.Close ();
274                 }
275
276                 [Test]
277                 public void TestDispose2 ()
278                 {
279                         UnixSignal a = new UnixSignal (Signum.SIGINT);
280                         UnixSignal b = new UnixSignal (Signum.SIGINT);
281
282                         Stdlib.raise (Signum.SIGINT);
283
284                         Assert.AreEqual (a.Count, 1);
285                         Assert.AreEqual (b.Count, 1);
286
287                         b.Close ();
288                         a.Reset ();
289
290                         Stdlib.raise (Signum.SIGINT);
291                         Assert.AreEqual (a.Count, 1);
292
293                         a.Close ();
294                 }
295
296                 [Test]
297                 public void TestSignalActionInteraction ()
298                 {
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
303                         }
304                 }
305
306                 static readonly Signum[] signals = new Signum[] {
307                         Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
308                 };
309
310                 const int StormCount = 100000;
311
312                 [Test]
313                 [Category("NotOnMac")] // OSX signal storming will not deliver every one
314                 public void TestRaiseStorm ()
315                 {
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),
322                         };
323                         foreach (Thread t in threads)
324                                 t.Start ();
325                         foreach (Thread t in threads)
326                                 t.Join ();
327                         AssertCount (usignals);
328                         CloseSignals (usignals);
329                 }
330
331                 static void AssertCount (UnixSignal[] usignals)
332                 {
333                         int sum = 0;
334                         foreach (UnixSignal s in usignals)
335                                 sum += s.Count;
336                         Assert.AreEqual (sum, StormCount);
337                 }
338
339                 static UnixSignal[] CreateSignals (Signum[] signals)
340                 {
341                         UnixSignal[] s = new UnixSignal [signals.Length];
342                         for (int i = 0; i < signals.Length; ++i)
343                                 s [i] = new UnixSignal (signals [i]);
344                         return s;
345                 }
346
347                 static void CloseSignals (UnixSignal[] signals)
348                 {
349                         foreach (UnixSignal s in signals)
350                                 s.Close ();
351                 }
352
353                 static Thread CreateRaiseStormThread (int max)
354                 {
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]);
360                                 }
361                         });
362                 }
363
364                 [Test]
365                 [Category("NotOnMac")] // OSX signal storming will not deliver every one
366                 public void TestAddRemove ()
367                 {
368                         UnixSignal[] usignals = CreateSignals (signals);
369
370                         Thread[] threads = new Thread[]{
371                                 CreateRaiseStormThread (StormCount),
372                                 CreateSignalCreatorThread (),
373                         };
374
375                         foreach (Thread t in threads)
376                                 t.Start ();
377                         foreach (Thread t in threads)
378                                 t.Join ();
379
380                         AssertCount (usignals);
381                         CloseSignals (usignals);
382                 }
383
384                 static Thread CreateSignalCreatorThread ()
385                 {
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])) {
394                                         }
395                                 }
396                         });
397                 }
398
399                 [Test]
400                 [Category("NotOnMac")] // OSX signal storming will not deliver every one
401                 public void TestWaitAny ()
402                 {
403                         UnixSignal[] usignals = CreateSignals (signals);
404
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]),
411                         };
412
413                         foreach (Thread t in threads)
414                                 t.Start ();
415                         foreach (Thread t in threads)
416                                 t.Join ();
417
418                         AssertCount (usignals);
419                         CloseSignals (usignals);
420                 }
421
422                 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
423                 {
424                         return new Thread (delegate () {
425                                 int idx = UnixSignal.WaitAny (usignals, 30000);
426                                 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);
427                         });
428                 }
429         }
430 }