Merge pull request #2832 from razzfazz/handle_eintr
[mono.git] / mcs / class / corlib / Test / System.Threading / WaitHandleTest.cs
1 //
2 // WaitHandleTest.cs
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29
30 using System;
31 using System.Threading;
32
33 using NUnit.Framework;
34
35 namespace MonoTests.System.Threading {
36
37         [TestFixture]
38         public class WaitHandleTest {
39
40                 TimeSpan Infinite = new TimeSpan (-10000);      // -10000 ticks == -1 ms
41                 TimeSpan SmallNegative = new TimeSpan (-2);     // between 0 and -1.0 (infinite) ms
42                 TimeSpan Negative = new TimeSpan (-20000);      // really negative
43
44                 WaitHandle [] TooLarge = new Mutex [65];
45                 WaitHandle [] Empty = new Mutex [1];
46                 WaitHandle [] Single = new Mutex [1] { new Mutex (true) };
47
48
49                 [Test]
50                 [ExpectedException (typeof (ArgumentNullException))]
51                 public void WaitAny_WaitHandle_Null ()
52                 {
53                         WaitHandle.WaitAny (null);
54                 }
55
56                 [Test]
57                 [ExpectedException (typeof (NotSupportedException))]
58                 public void WaitAny_WaitHandle_TooLarge ()
59                 {
60                         WaitHandle.WaitAny (TooLarge);
61                 }
62
63                 [Test]
64                 [ExpectedException (typeof (ArgumentNullException))]
65                 public void WaitAny_WaitHandle_Empty ()
66                 {
67                         WaitHandle.WaitAny (Empty);
68                 }
69
70                 [Test]
71                 public void WaitAny_WaitHandle ()
72                 {
73                         Assert.AreEqual (0, WaitHandle.WaitAny (Single), "WaitAny");
74                 }
75
76                 [Test]
77                 [ExpectedException (typeof (ArgumentNullException))]
78                 public void WaitAny_WaitHandleNull_Int ()
79                 {
80                         WaitHandle.WaitAny (null, -1);
81                 }
82
83                 [Test]
84                 [ExpectedException (typeof (NotSupportedException))]
85                 public void WaitAny_WaitHandle_TooLarge_Int ()
86                 {
87                         WaitHandle.WaitAny (TooLarge, -1);
88                 }
89
90                 [Test]
91                 [ExpectedException (typeof (ArgumentNullException))]
92                 public void WaitAny_WaitHandle_Empty_Int ()
93                 {
94                         WaitHandle.WaitAny (Empty, -1);
95                 }
96
97                 [Test]
98                 public void WaitAny_WaitHandle_Int ()
99                 {
100                         // -1 is infinite
101                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, -1), "WaitAny");
102                 }
103
104                 [Test]
105                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
106                 public void WaitAny_WaitHandle_Int_Negative ()
107                 {
108                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, -2), "WaitAny");
109                 }
110
111                 [Test]
112                 [ExpectedException (typeof (ArgumentNullException))]
113                 public void WaitAny_WaitHandleNull_TimeSpan ()
114                 {
115                         WaitHandle.WaitAny (null, Infinite);
116                 }
117
118                 [Test]
119                 [ExpectedException (typeof (NotSupportedException))]
120                 public void WaitAny_WaitHandle_TooLarge_TimeSpan ()
121                 {
122                         WaitHandle.WaitAny (TooLarge, Infinite);
123                 }
124
125                 [Test]
126                 [ExpectedException (typeof (ArgumentNullException))]
127                 public void WaitAny_WaitHandle_Empty_TimeSpan ()
128                 {
129                         WaitHandle.WaitAny (Empty, Infinite);
130                 }
131
132                 [Test]
133                 public void WaitAny_WaitHandle_TimeSpan ()
134                 {
135                         Assert.AreEqual (Timeout.Infinite, (int) Infinite.TotalMilliseconds, "Infinite");
136                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, Infinite), "WaitAny-Infinite");
137                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, SmallNegative), "WaitAny-SmallNegative");
138                 }
139
140                 [Test]
141                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
142                 public void WaitAny_WaitHandle_TimeSpan_Negative ()
143                 {
144                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, Negative), "WaitAny");
145                 }
146
147                 [Test]
148                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
149                 public void WaitAny_WaitHandle_TimeSpan_MaxValue ()
150                 {
151                         Assert.AreEqual (0, WaitHandle.WaitAny (Single, TimeSpan.MaxValue), "WaitAny");
152                 }
153
154
155                 [Test]
156                 [ExpectedException (typeof (ArgumentNullException))]
157                 public void WaitAll_WaitHandle_Null ()
158                 {
159                         WaitHandle.WaitAll (null);
160                 }
161
162                 [Test]
163                 [ExpectedException (typeof (NotSupportedException))]
164                 public void WaitAll_WaitHandle_TooLarge ()
165                 {
166                         WaitHandle.WaitAll (TooLarge);
167                 }
168
169                 [Test]
170                 [ExpectedException (typeof (ArgumentNullException))]
171                 public void WaitAll_WaitHandle_Empty ()
172                 {
173                         WaitHandle.WaitAll (Empty);
174                 }
175
176                 [Test]
177                 public void WaitAll_WaitHandle ()
178                 {
179                         Assert.IsTrue (WaitHandle.WaitAll (Single), "WaitAll");
180                 }
181
182                 [Test]
183                 [ExpectedException (typeof (ArgumentNullException))]
184                 public void WaitAll_WaitHandleNull_Int ()
185                 {
186                         WaitHandle.WaitAll (null, -1);
187                 }
188
189                 [Test]
190                 [ExpectedException (typeof (NotSupportedException))]
191                 public void WaitAll_WaitHandle_TooLarge_Int ()
192                 {
193                         WaitHandle.WaitAll (TooLarge, -1);
194                 }
195
196                 [Test]
197                 [ExpectedException (typeof (ArgumentNullException))]
198                 public void WaitAll_WaitHandle_Empty_Int ()
199                 {
200                         WaitHandle.WaitAll (Empty, -1);
201                 }
202
203                 [Test]
204                 public void WaitAll_WaitHandle_Int ()
205                 {
206                         // -1 is infinite
207                         Assert.IsTrue (WaitHandle.WaitAll (Single, -1), "WaitAll");
208                 }
209
210                 [Test]
211                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
212                 public void WaitAll_WaitHandle_Int_Negative ()
213                 {
214                         Assert.IsTrue (WaitHandle.WaitAll (Single, -2), "WaitAll");
215                 }
216
217                 [Test]
218                 [ExpectedException (typeof (ArgumentNullException))]
219                 public void WaitAll_WaitHandleNull_TimeSpan ()
220                 {
221                         WaitHandle.WaitAll (null, Infinite);
222                 }
223
224                 [Test]
225                 [ExpectedException (typeof (NotSupportedException))]
226                 public void WaitAll_WaitHandle_TooLarge_TimeSpan ()
227                 {
228                         WaitHandle.WaitAll (TooLarge, Infinite);
229                 }
230
231                 [Test]
232                 [ExpectedException (typeof (ArgumentNullException))]
233                 public void WaitAll_WaitHandle_Empty_TimeSpan ()
234                 {
235                         WaitHandle.WaitAll (Empty, Infinite);
236                 }
237
238                 [Test]
239                 public void WaitAll_WaitHandle_TimeSpan ()
240                 {
241                         Assert.AreEqual (Timeout.Infinite, (int) Infinite.TotalMilliseconds, "Infinite");
242                         Assert.IsTrue (WaitHandle.WaitAll (Single, Infinite), "WaitAll-Infinite");
243                         Assert.IsTrue (WaitHandle.WaitAll (Single, SmallNegative), "WaitAll-SmallNegative");
244                 }
245
246                 [Test]
247                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
248                 public void WaitAll_WaitHandle_TimeSpan_Negative ()
249                 {
250                         Assert.IsTrue (WaitHandle.WaitAll (Single, Negative), "WaitAll");
251                 }
252
253                 [Test]
254                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
255                 public void WaitAll_WaitHandle_TimeSpan_MaxValue ()
256                 {
257                         Assert.IsTrue (WaitHandle.WaitAll (Single, TimeSpan.MaxValue), "WaitAll");
258                 }
259
260
261                 [Test]
262                 public void WaitOne ()
263                 {
264                         Assert.IsTrue (Single [0].WaitOne (), "WaitOne");
265                 }
266
267                 [Test]
268                 public void WaitOne_Int ()
269                 {
270                         // -1 is infinite
271                         Assert.IsTrue (Single [0].WaitOne (-1), "WaitOne");
272                 }
273
274                 [Test]
275                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
276                 public void WaitOne_Int_Negative ()
277                 {
278                         Assert.IsTrue (Single [0].WaitOne (-2), "WaitOne");
279                 }
280
281                 [Test]
282                 public void WaitOne_TimeSpan ()
283                 {
284                         Assert.AreEqual (Timeout.Infinite, (int) Infinite.TotalMilliseconds, "Infinite");
285                         Assert.IsTrue (Single [0].WaitOne (Infinite), "WaitOne-Infinite");
286                         Assert.IsTrue (Single [0].WaitOne (SmallNegative), "WaitOne-SmallNegative");
287                 }
288
289                 [Test]
290                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
291                 public void WaitOne_TimeSpan_Negative ()
292                 {
293                         Assert.IsTrue (Single [0].WaitOne (Negative), "WaitOne");
294                 }
295
296                 [Test]
297                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
298                 public void WaitOne_TimeSpan_MaxValue ()
299                 {
300                         Assert.IsTrue (Single [0].WaitOne (TimeSpan.MaxValue), "WaitOne");
301                 }
302
303                 [Test]
304                 [ExpectedException (typeof (ArgumentNullException))]
305                 public void WaitAll_Empty ()
306                 {
307                         WaitHandle.WaitAll (new WaitHandle [0]);
308                 }
309
310                 [Test]
311                 [ExpectedException (typeof (ArgumentException))]
312                 public void WaitAny_Empty ()
313                 {
314                         WaitHandle.WaitAny (new WaitHandle [0]);
315                 }
316
317                 [Test]
318                 public void InterrupedWaitAny ()
319                 {
320                         using (var m1 = new Mutex (true)) {
321                                 using (var m2 = new Mutex (true)) {
322                                         using (var done = new ManualResetEvent (false)) {
323                                                 var thread = new Thread (() =>
324                                                 {
325                                                         try {
326                                                                 WaitHandle.WaitAny (new WaitHandle [] { m1, m2 });
327                                                         } catch (ThreadInterruptedException) {
328                                                                 done.Set ();
329                                                         }
330                                                 });
331                                                 thread.Start ();
332                                                 Thread.Sleep (100); // wait a bit so the thread can enter its wait
333                                                 thread.Interrupt ();
334
335                                                 Assert.IsTrue (thread.Join (1000), "Join");
336                                                 Assert.IsTrue (done.WaitOne (1000), "done");
337
338                                                 m1.ReleaseMutex ();
339                                                 m2.ReleaseMutex ();
340                                         }
341                                 }
342                         }
343                 }
344                 
345                 [Test]
346                 public void InterrupedWaitAll ()
347                 {
348                         using (var m1 = new Mutex (true)) {
349                                 using (var m2 = new Mutex (true)) {
350                                         using (var done = new ManualResetEvent (false)) {
351                                                 var thread = new Thread (() =>
352                                                                          {
353                                                         try {
354                                                                 WaitHandle.WaitAll (new WaitHandle [] { m1, m2 });
355                                                         } catch (ThreadInterruptedException) {
356                                                                 done.Set ();
357                                                         }
358                                                 });
359                                                 thread.Start ();
360                                                 Thread.Sleep (100); // wait a bit so the thread can enter its wait
361                                                 thread.Interrupt ();
362
363                                                 Assert.IsTrue (thread.Join (1000), "Join");
364                                                 Assert.IsTrue (done.WaitOne (1000), "done");
365
366                                                 m1.ReleaseMutex ();
367                                                 m2.ReleaseMutex ();
368                                         }
369                                 }
370                         }
371                 }
372                 
373                 [Test]
374                 public void InterrupedWaitOne ()
375                 {
376                         using (var m1 = new Mutex (true)) {
377                                 using (var done = new ManualResetEvent (false)) {
378                                         var thread = new Thread (() =>
379                                                                  {
380                                                 try {
381                                                         m1.WaitOne ();
382                                                 } catch (ThreadInterruptedException) {
383                                                         done.Set ();
384                                                 }
385                                         });
386                                         thread.Start ();
387                                         Thread.Sleep (100); // wait a bit so the thread can enter its wait
388                                         thread.Interrupt ();
389
390                                         Assert.IsTrue (thread.Join (1000), "Join");
391                                         Assert.IsTrue (done.WaitOne (1000), "done");
392
393                                         m1.ReleaseMutex ();
394                                 }
395                         }
396                 }
397
398 #if MONO_FEATURE_THREAD_SUSPEND_RESUME
399                 [Test]
400                 public void WaitOneWithTimeoutAndSpuriousWake ()
401                 {
402                         /* This is to test that WaitEvent.WaitOne is not going to wait largely
403                          * more than its timeout. In this test, it shouldn't wait more than
404                          * 1500 milliseconds, with its timeout being 1000ms */
405
406                         using (ManualResetEvent mre = new ManualResetEvent (false))
407                         using (ManualResetEvent ready = new ManualResetEvent (false)) {
408                                 var thread = new Thread (() => {
409                                         ready.Set ();
410                                         mre.WaitOne (1000);
411                                 });
412
413                                 thread.Start ();
414                                 ready.WaitOne ();
415
416                                 Thread.Sleep (10); // wait a bit so we enter mre.WaitOne
417
418                                 DateTime end = DateTime.Now.AddMilliseconds (500);
419                                 while (DateTime.Now < end) {
420                                         thread.Suspend ();
421                                         thread.Resume ();
422                                 }
423
424                                 Assert.IsTrue (thread.Join (1000), "#1");
425                         }
426                 }
427
428                 [Test]
429                 public void WaitAnyWithTimeoutAndSpuriousWake ()
430                 {
431                         /* This is to test that WaitEvent.WaitAny is not going to wait largely
432                          * more than its timeout. In this test, it shouldn't wait more than
433                          * 1500 milliseconds, with its timeout being 1000ms */
434
435                         using (ManualResetEvent mre1 = new ManualResetEvent (false))
436                         using (ManualResetEvent mre2 = new ManualResetEvent (false))
437                         using (ManualResetEvent ready = new ManualResetEvent (false)) {
438                                 var thread = new Thread (() => {
439                                         ready.Set ();
440                                         WaitHandle.WaitAny (new [] { mre1, mre2 }, 1000);
441                                 });
442
443                                 thread.Start ();
444                                 ready.WaitOne ();
445
446                                 Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAny ({mre1, mre2})
447
448                                 DateTime end = DateTime.Now.AddMilliseconds (500);
449                                 while (DateTime.Now < end) {
450                                         thread.Suspend ();
451                                         thread.Resume ();
452                                 }
453
454                                 Assert.IsTrue (thread.Join (1000), "#1");
455                         }
456                 }
457
458                 [Test]
459                 public void WaitAllWithTimeoutAndSpuriousWake ()
460                 {
461                         /* This is to test that WaitEvent.WaitAll is not going to wait largely
462                          * more than its timeout. In this test, it shouldn't wait more than
463                          * 1500 milliseconds, with its timeout being 1000ms */
464
465                         using (ManualResetEvent mre1 = new ManualResetEvent (false))
466                         using (ManualResetEvent mre2 = new ManualResetEvent (false))
467                         using (ManualResetEvent ready = new ManualResetEvent (false)) {
468                                 var thread = new Thread (() => {
469                                         ready.Set ();
470                                         WaitHandle.WaitAll (new [] { mre1, mre2 }, 1000);
471                                 });
472
473                                 thread.Start ();
474                                 ready.WaitOne ();
475
476                                 Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAll ({mre1, mre2})
477
478                                 DateTime end = DateTime.Now.AddMilliseconds (500);
479                                 while (DateTime.Now < end) {
480                                         thread.Suspend ();
481                                         thread.Resume ();
482                                 }
483
484                                 Assert.IsTrue (thread.Join (1000), "#1");
485                         }
486                 }
487 #endif // MONO_FEATURE_THREAD_SUSPEND_RESUME
488         }
489 }
490
491