[threads] Don't ignore abort requests in abort protected blocks
[mono.git] / mcs / class / corlib / Test / System.Threading / TimerTest.cs
1 //
2 // TimerTest.cs - NUnit test cases for System.Threading.Timer
3 //
4 // Author:
5 //   Zoltan Varga (vargaz@freemail.hu)
6 //   Rafael Ferreira (raf@ophion.org)
7 //
8 // (C) 2004 Novell, Inc (http://www.novell.com)
9 //
10
11 using NUnit.Framework;
12 using System;
13 using System.Threading;
14 using System.Collections;
15
16 namespace MonoTests.System.Threading {
17         [TestFixture]
18         public class TimerTest {
19                 // this bucket is used to avoid non-theadlocal issues
20                 class Bucket {
21                         public int count;
22                 }
23
24                 [SetUp]
25                 public void Setup ()
26                 {
27                         //creating a timer that will never run just to make sure the
28                         // scheduler is warm for the unit tests
29                         // this makes fair for the "DueTime" test since it 
30                         // doesn't have to wait for the scheduler thread to be 
31                         // created. 
32                         new Timer (o => DoNothing (o), null, Timeout.Infinite, 0);
33                 }
34
35                 void DoNothing (object foo)
36                 {
37                 }
38
39                 [Test]
40                 public void TestDueTime ()
41                 {
42                         Bucket bucket = new Bucket();
43
44                         using (Timer t = new Timer (o => Callback (o), bucket, 200, Timeout.Infinite)) {
45                                 Thread.Sleep (50);
46                                 Assert.AreEqual (0, bucket.count, "#1");
47                                 Thread.Sleep (200);
48                                 Assert.AreEqual (1, bucket.count, "#2");
49                                 Thread.Sleep (500);
50                                 Assert.AreEqual (1, bucket.count, "#3");
51                                 t.Change (10, 10);
52                                 Thread.Sleep (1000);
53                                 Assert.IsTrue(bucket.count > 20, "#4");
54                         }
55                 }
56
57                 [Test]
58                 public void TestChange ()
59                 {
60                         Bucket bucket = new Bucket();
61
62                         using (Timer t = new Timer (o => Callback (o), bucket, 10, 10)) {
63                                 Thread.Sleep (500);
64                                 int c = bucket.count;
65                                 Assert.IsTrue (c > 20, "#1 " + c.ToString ());
66                                 t.Change (100, 100);
67                                 c = bucket.count;
68                                 Thread.Sleep (500);
69                                 Assert.IsTrue (bucket.count <= c + 20, "#2 " + c.ToString ());
70                         }
71                 }
72
73                 [Test]
74                 public void TestZeroDueTime ()
75                 {
76                         Bucket bucket = new Bucket();
77
78                         using (Timer t = new Timer (o => Callback (o), bucket, 0, Timeout.Infinite)) {
79                                 Thread.Sleep (100);
80                                 Assert.AreEqual (1, bucket.count, "#1");
81                                 t.Change (0, Timeout.Infinite);
82                                 Thread.Sleep (100);
83                                 Assert.AreEqual (2, bucket.count, "#2");
84                         }
85                 }
86
87                 [Test]
88                 public void TestDispose ()
89                 {       
90                         Bucket bucket = new Bucket();
91
92                         using (Timer t = new Timer (o => Callback (o), bucket, 10, 10)) {
93                                 Thread.Sleep (200);
94                         }
95
96                         Thread.Sleep (20);
97                         int c = bucket.count;
98                         Assert.IsTrue (bucket.count > 5, "#1");
99                         Thread.Sleep (200);
100                         Assert.AreEqual (c, bucket.count, "#2");
101                 }
102
103                 [Test] // bug #320950
104                 public void TestDispose2 ()
105                 {
106                         Timer t = new Timer (o => DoNothing (o), null, 10, 10);
107                         t.Dispose ();
108                         t.Dispose ();
109                 }
110                 
111                 [Test]
112                 public void TestHeavyCreationLoad ()
113                 {
114                         Bucket b = new Bucket ();
115
116                         for (int i = 0; i < 500; ++i)
117                                 new Timer (o => Callback (o), b, 10, Timeout.Infinite);
118
119                         // 1000 * 10 msec = 10,000 msec or 10 sec - if everything goes well
120                         // we add some slack to cope with timing issues caused by system load etc.
121                         for (int i = 0; i < 20; ++i) {
122                                 if (b.count == 500)
123                                         break;
124                                 Thread.Sleep (1000);
125                         }
126
127                         Assert.AreEqual (500, b.count);
128                 }
129
130                 [Test]
131                 public void TestQuickDisposeDeadlockBug ()
132                 {
133                         Bucket b = new Bucket ();
134                         ArrayList timers = new ArrayList (500);
135
136                         for (int i = 0; i < 500; ++i) {
137                                 using (Timer t = new Timer (o => Callback (o), b, 10, Timeout.Infinite)) {
138                                         timers.Add (t);
139                                 }
140                         }
141
142                         Thread.Sleep (11 * 500);
143                 }
144
145                 [Test]
146                 public void TestInt32MaxDelay ()
147                 {
148                         Bucket b = new Bucket ();
149
150                         using (new Timer (o => Callback (o), b, Int32.MaxValue, Timeout.Infinite)) {
151                                 Thread.Sleep (50);
152                                 Assert.AreEqual (0, b.count);
153                         }
154                 }
155
156                 [Test]
157                 public void TestInt32MaxPeriod ()
158                 {
159                         Bucket b = new Bucket ();
160                         
161                         using (new Timer (o => Callback (o), b, 0, Int32.MaxValue)) {
162                                 Thread.Sleep (50);
163                                 Assert.AreEqual (1, b.count);
164                         }
165                 }
166
167                 [Test]
168                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
169                 public void TestNegativeDelay ()
170                 {
171                         Bucket b = new Bucket ();
172
173                         using (new Timer (o => Callback (o), b, -10, Timeout.Infinite)) {
174                         }
175                 }
176
177                 [Test]
178                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
179                 public void TestNegativePeriod ()
180                 {
181                         Bucket b = new Bucket ();
182
183                         using (new Timer (o => Callback (o), b, 0, -10)) {
184                         }
185                 }
186
187                 [Test]
188                 public void TestDelayZeroPeriodZero()
189                 {
190                         Bucket b = new Bucket();
191
192                         using (Timer t = new Timer(o => Callback (o),b,0,0)) {
193                                 Thread.Sleep(100);
194                                 t.Change (int.MaxValue, Timeout.Infinite);
195                                 // since period is 0 the callback should happen once (bug #340212)
196                                 Assert.AreEqual (1, b.count, "only once");
197                         }
198                 }
199
200                 [Test]
201                 [Ignore ()]
202                 public void TestDisposeOnCallback ()
203                 {
204                         // this test is bad, as the provided `state` (t1) is null and will throw an NRE inside the callback
205                         // that was ignored before 238785a3e3d510528228fc551625975bc508c2f3 and most unit test runner won't
206                         // report it since the NRE will not happen on the main thread (but Touch.Unit will)
207                         Timer t1 = null;
208                         t1 = new Timer (o => CallbackTestDisposeOnCallback (o), t1, 0, 10);
209                         Thread.Sleep (200);
210                         Assert.IsNotNull (t1);
211                         
212                 }
213
214                 private void CallbackTestDisposeOnCallback (object foo)
215                 {
216                         ((Timer) foo).Dispose ();
217                 }
218
219                 private void Callback (object foo)
220                 {
221                         Bucket b = foo as Bucket;
222                         Interlocked.Increment (ref b.count);
223                 }
224
225                 [Test]
226                 [ExpectedException (typeof (ArgumentNullException))]
227                 public void DisposeNullWaitHandle ()
228                 {
229                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
230                                 t.Dispose (null);
231                         }
232                 }
233
234                 [Test]
235                 public void Change_IntInt_Infinite ()
236                 {
237                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
238                                 t.Change ((int)Timeout.Infinite, (int)Timeout.Infinite);
239                         }
240                 }
241
242                 [Test]
243                 public void Change_IntInt_MaxValue ()
244                 {
245                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
246                                 t.Change (Int32.MaxValue, Int32.MaxValue);
247                         }
248                 }
249
250                 [Test]
251                 public void Change_UIntUInt_Infinite ()
252                 {
253                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
254                                 t.Change (unchecked ((uint) Timeout.Infinite), unchecked ((uint) Timeout.Infinite));
255                         }
256                 }
257
258                 [Test]
259                 public void Change_UIntUInt_MaxValue ()
260                 {
261                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
262                                 // UInt32.MaxValue == Timeout.Infinite == 0xffffffff
263                                 t.Change (UInt32.MaxValue, UInt32.MaxValue);
264                         }
265                 }
266
267                 [Test]
268                 public void Change_LongLong_Infinite ()
269                 {
270                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
271                                 t.Change ((long) Timeout.Infinite, (long) Timeout.Infinite);
272                         }
273                 }
274
275                 [Test]
276                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
277                 public void Change_LongLong_MaxValue ()
278                 {
279                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
280                                 t.Change (Int64.MaxValue, Int64.MaxValue);
281                         }
282                 }
283
284                 [Test]
285                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
286                 public void Change_LongLong_UInt32MaxValue ()
287                 {
288                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
289                                 // not identical to (long)-1
290                                 t.Change ((long)UInt32.MaxValue, (long)UInt32.MaxValue);
291                         }
292                 }
293
294                 [Test]
295                 public void Change_LongLong_UInt32MaxValueMinusOne ()
296                 {
297                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
298                                 // not identical to (long)-1
299                                 t.Change ((long) UInt32.MaxValue - 1, (long) UInt32.MaxValue -1);
300                         }
301                 }
302
303                 [Test]
304                 public void Change_TimeSpanTimeSpan_Infinite ()
305                 {
306                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
307                                 t.Change (new TimeSpan (-1), new TimeSpan (-1));
308                         }
309                 }
310
311                 [Test]
312                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
313                 public void Change_TimeSpanTimeSpan_MaxValue ()
314                 {
315                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
316                                 t.Change (TimeSpan.MaxValue, TimeSpan.MaxValue);
317                         }
318                 }
319
320                 [Test]
321                 public void Change_TimeSpanTimeSpan_UInt32MaxValue ()
322                 {
323                         using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
324                                 t.Change (new TimeSpan (UInt32.MaxValue), new TimeSpan (UInt32.MaxValue));
325                         }
326                 }
327         }
328 }