TARGET_J2EE:
[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 System;
12 using System.Text;
13 using System.Threading;
14 using Mono.Unix;
15 using Mono.Unix.Native;
16
17 namespace MonoTests.Mono.Unix {
18
19         [TestFixture]
20         public class UnixSignalTest {
21                 [Test]
22                 public void TestRaise ()
23                 {
24                         Thread t1 = new Thread (delegate () {
25                                         using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
26                                                 DateTime start = DateTime.Now;
27                                                 bool r = a.WaitOne (5000, false);
28                                                 DateTime end = DateTime.Now;
29                                                 Assert.AreEqual (a.Count, 1);
30                                                 Assert.AreEqual (r, true);
31                                                 if ((end - start) > new TimeSpan (0, 0, 5))
32                                                         throw new InvalidOperationException ("Signal slept too long");
33                                         }
34                         });
35                         Thread t2 = new Thread (delegate () {
36                                         Thread.Sleep (1000);
37                                         Stdlib.raise (Signum.SIGINT);
38                         });
39                         t1.Start ();
40                         t2.Start ();
41                         t1.Join ();
42                         t2.Join ();
43                 }
44
45                 [Test]
46                 public void TestRaiseAny ()
47                 {
48                         Thread t1 = new Thread (delegate () {
49                                         using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
50                                                 DateTime start = DateTime.Now;
51                                                 int idx = UnixSignal.WaitAny (new UnixSignal[]{a}, 5000);
52                                                 DateTime end = DateTime.Now;
53                                                 Assert.AreEqual (idx, 0);
54                                                 Assert.AreEqual (a.Count, 1);
55                                                 if ((end - start) > new TimeSpan (0, 0, 5))
56                                                         throw new InvalidOperationException ("Signal slept too long");
57                                         }
58                         });
59                         Thread t2 = new Thread (delegate () {
60                                         Thread.Sleep (1000);
61                                         Stdlib.raise (Signum.SIGINT);
62                         });
63                         t1.Start ();
64                         t2.Start ();
65                         t1.Join ();
66                         t2.Join ();
67                 }
68
69                 [Test]
70                 public void TestSeparation ()
71                 {
72                         Thread t1 = new Thread (delegate () {
73                                         using (UnixSignal a = new UnixSignal (Signum.SIGINT))
74                                         using (UnixSignal b = new UnixSignal (Signum.SIGTERM)) {
75                                                 DateTime start = DateTime.Now;
76                                                 int idx = UnixSignal.WaitAny (new UnixSignal[]{a, b}, 5000);
77                                                 DateTime end = DateTime.Now;
78                                                 Assert.AreEqual (idx, 1);
79                                                 Assert.AreEqual (a.Count, 0);
80                                                 Assert.AreEqual (b.Count, 1);
81                                                 if ((end - start) > new TimeSpan (0, 0, 5))
82                                                         throw new InvalidOperationException ("Signal slept too long");
83                                         }
84                         });
85                         Thread t2 = new Thread (delegate () {
86                                         Thread.Sleep (1000);
87                                         Stdlib.raise (Signum.SIGTERM);
88                         });
89                         t1.Start ();
90                         t2.Start ();
91                         t1.Join ();
92                         t2.Join ();
93                 }
94
95                 [Test]
96                 public void TestNoEmit ()
97                 {
98                         using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
99                                 DateTime start = DateTime.Now;
100                                 bool r = u.WaitOne (5100, false);
101                                 Assert.AreEqual (r, false);
102                                 DateTime end = DateTime.Now;
103                                 if ((end - start) < new TimeSpan (0, 0, 5))
104                                         throw new InvalidOperationException ("Signal didn't block for 5s; blocked for " + (end-start).ToString());
105                         }
106                 }
107
108                 [Test]
109                 public void TestNoEmitAny ()
110                 {
111                         using (UnixSignal u = new UnixSignal (Signum.SIGINT)) {
112                                 int idx = UnixSignal.WaitAny (new UnixSignal[]{u}, 5100);
113                                 Assert.AreEqual (idx, 5100);
114                         }
115                 }
116
117                 [Test]
118                 public void TestDispose1 ()
119                 {
120                         UnixSignal a = new UnixSignal (Signum.SIGINT);
121                         UnixSignal b = new UnixSignal (Signum.SIGINT);
122
123                         Stdlib.raise (Signum.SIGINT);
124
125                         Assert.AreEqual (a.Count, 1);
126                         Assert.AreEqual (b.Count, 1);
127
128                         a.Close ();
129                         b.Reset ();
130
131                         Stdlib.raise (Signum.SIGINT);
132                         Assert.AreEqual (b.Count, 1);
133
134                         b.Close ();
135                 }
136
137                 [Test]
138                 public void TestDispose2 ()
139                 {
140                         UnixSignal a = new UnixSignal (Signum.SIGINT);
141                         UnixSignal b = new UnixSignal (Signum.SIGINT);
142
143                         Stdlib.raise (Signum.SIGINT);
144
145                         Assert.AreEqual (a.Count, 1);
146                         Assert.AreEqual (b.Count, 1);
147
148                         b.Close ();
149                         a.Reset ();
150
151                         Stdlib.raise (Signum.SIGINT);
152                         Assert.AreEqual (a.Count, 1);
153
154                         a.Close ();
155                 }
156
157                 [Test]
158                 public void TestSignalActionInteraction ()
159                 {
160                         using (UnixSignal a = new UnixSignal (Signum.SIGINT)) {
161                                 Stdlib.SetSignalAction (Signum.SIGINT, SignalAction.Ignore);
162                                 Stdlib.raise (Signum.SIGINT);
163                                 Assert.AreEqual (a.Count, 0); // never invoked
164                         }
165                 }
166
167                 static readonly Signum[] signals = new Signum[] {
168                         Signum.SIGHUP, Signum.SIGINT, Signum.SIGTERM, Signum.SIGCONT,
169                 };
170
171                 const int StormCount = 100000;
172
173                 [Test]
174                 public void TestRaiseStorm ()
175                 {
176                         UnixSignal[] usignals = CreateSignals (signals);
177                         Thread[] threads = new Thread[]{
178                                 CreateRaiseStormThread (StormCount/4),
179                                 CreateRaiseStormThread (StormCount/4),
180                                 CreateRaiseStormThread (StormCount/4),
181                                 CreateRaiseStormThread (StormCount/4),
182                         };
183                         foreach (Thread t in threads)
184                                 t.Start ();
185                         foreach (Thread t in threads)
186                                 t.Join ();
187                         AssertCount (usignals);
188                         CloseSignals (usignals);
189                 }
190
191                 static void AssertCount (UnixSignal[] usignals)
192                 {
193                         int sum = 0;
194                         foreach (UnixSignal s in usignals)
195                                 sum += s.Count;
196                         Assert.AreEqual (sum, StormCount);
197                 }
198
199                 static UnixSignal[] CreateSignals (Signum[] signals)
200                 {
201                         UnixSignal[] s = new UnixSignal [signals.Length];
202                         for (int i = 0; i < signals.Length; ++i)
203                                 s [i] = new UnixSignal (signals [i]);
204                         return s;
205                 }
206
207                 static void CloseSignals (UnixSignal[] signals)
208                 {
209                         foreach (UnixSignal s in signals)
210                                 s.Close ();
211                 }
212
213                 static Thread CreateRaiseStormThread (int max)
214                 {
215                         return new Thread (delegate () {
216                                 Random r = new Random (Environment.TickCount);
217                                 for (int i = 0; i < max; ++i) {
218                                         int n = r.Next (0, signals.Length);
219                                         Stdlib.raise (signals [n]);
220                                 }
221                         });
222                 }
223
224                 [Test]
225                 public void TestAddRemove ()
226                 {
227                         UnixSignal[] usignals = CreateSignals (signals);
228
229                         Thread[] threads = new Thread[]{
230                                 CreateRaiseStormThread (StormCount),
231                                 CreateSignalCreatorThread (),
232                         };
233
234                         foreach (Thread t in threads)
235                                 t.Start ();
236                         foreach (Thread t in threads)
237                                 t.Join ();
238
239                         AssertCount (usignals);
240                         CloseSignals (usignals);
241                 }
242
243                 static Thread CreateSignalCreatorThread ()
244                 {
245                         return new Thread (delegate () {
246                                 Random r = new Random (Environment.TickCount << 4);
247                                 for (int i = 0; i < StormCount; ++i) {
248                                         int n = r.Next (0, signals.Length);
249                                         using (new UnixSignal (signals [n]))
250                                         using (new UnixSignal (signals [(n+1)%signals.Length]))
251                                         using (new UnixSignal (signals [(n+2)%signals.Length]))
252                                         using (new UnixSignal (signals [(n+3)%signals.Length])) {
253                                         }
254                                 }
255                         });
256                 }
257
258                 [Test]
259                 public void TestWaitAny ()
260                 {
261                         UnixSignal[] usignals = CreateSignals (signals);
262
263                         Thread[] threads = new Thread[]{
264                                 CreateRaiseStormThread (StormCount),
265                                 CreateSignalCreatorThread (),
266                                 CreateWaitAnyThread (usignals [0], usignals [2]),
267                                 CreateWaitAnyThread (usignals [1], usignals [3]),
268                                 CreateWaitAnyThread (usignals [1], usignals [2]),
269                         };
270
271                         foreach (Thread t in threads)
272                                 t.Start ();
273                         foreach (Thread t in threads)
274                                 t.Join ();
275
276                         AssertCount (usignals);
277                         CloseSignals (usignals);
278                 }
279
280                 static Thread CreateWaitAnyThread (params UnixSignal[] usignals)
281                 {
282                         return new Thread (delegate () {
283                                 int idx = UnixSignal.WaitAny (usignals);
284                                 Assert.AreEqual (idx >= 0 && idx < usignals.Length, true);
285                         });
286                 }
287         }
288 }