Merge pull request #708 from spicypixel/hotfix/mono-object-to-string
[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 (new TimerCallback (DoNothing), 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                         Timer t = new Timer (new TimerCallback (Callback), bucket, 200, Timeout.Infinite);
44                         Thread.Sleep (50);
45                         Assert.AreEqual (0, bucket.count, "#1");
46                         Thread.Sleep (200);
47                         Assert.AreEqual (1, bucket.count, "#2");
48                         Thread.Sleep (500);
49                         Assert.AreEqual (1, bucket.count, "#3");
50                         t.Change (10, 10);
51                         Thread.Sleep (1000);
52                         Assert.IsTrue(bucket.count > 20, "#4");
53                         t.Dispose ();
54                 }
55
56                 [Test]
57                 public void TestChange ()
58                 {
59                         Bucket bucket = new Bucket();
60                         Timer t = new Timer (new TimerCallback (Callback), bucket, 10, 10);
61                         Thread.Sleep (500);
62                         int c = bucket.count;
63                         Assert.IsTrue(c > 20, "#1");
64                         t.Change (100, 100);
65                         c = bucket.count;
66                         Thread.Sleep (500);
67                         Assert.IsTrue(bucket.count <= c + 20, "#2");
68                         t.Dispose ();
69                 }
70
71                 [Test]
72                 public void TestZeroDueTime ()
73                 {
74                         Bucket bucket = new Bucket();
75
76                         Timer t = new Timer (new TimerCallback (Callback), bucket, 0, Timeout.Infinite);
77                         Thread.Sleep (100);
78                         Assert.AreEqual (1, bucket.count, "#1");
79                         t.Change (0, Timeout.Infinite);
80                         Thread.Sleep (100);
81                         Assert.AreEqual (2, bucket.count, "#2");
82                         t.Dispose ();
83                 }
84
85                 [Test]
86                 public void TestDispose ()
87                 {       
88                         Bucket bucket = new Bucket();
89                         Timer t = new Timer (new TimerCallback (Callback), bucket, 10, 10);
90                         Thread.Sleep (200);
91                         t.Dispose ();
92                         Thread.Sleep (20);
93                         int c = bucket.count;
94                         Assert.IsTrue (bucket.count > 5, "#1");
95                         Thread.Sleep (200);
96                         Assert.AreEqual (c, bucket.count, "#2");
97                 }
98
99                 [Test] // bug #320950
100                 public void TestDispose2 ()
101                 {
102                         Timer t = new Timer (new TimerCallback (Callback), null, 10, 10);
103                         t.Dispose ();
104                         t.Dispose ();
105                 }
106                 
107                 [Test]
108                 public void TestHeavyCreationLoad ()
109                 {
110                         Bucket b = new Bucket ();
111                         for (int i = 0; i < 500; ++i)
112                                 new Timer (new TimerCallback (Callback), b, 10,
113                                         Timeout.Infinite);
114                         // 1000 * 10 msec = 10,000 msec or 10 sec - if everything goes well
115                         // we add some slack to cope with timing issues caused by system load etc.
116                         for (int i = 0; i < 20; ++i) {
117                                 if (b.count == 500)
118                                         break;
119                                 Thread.Sleep (1000);
120                         }
121                         Assert.AreEqual (500, b.count);
122                         
123                 }
124
125                 [Test]
126                 public void TestQuickDisposeDeadlockBug ()
127                 {
128                         int i = 0;
129                         Bucket b = new Bucket ();
130                         ArrayList timers = new ArrayList();
131                         while (i < 500) {
132                                 Timer t = new Timer (new TimerCallback (Callback),
133                                         b, 10, Timeout.Infinite);
134                                 timers.Add (t);
135                                 i++;
136                                 t.Dispose ();
137                         }
138                         Thread.Sleep (11 * 500);
139                 }
140
141                 [Test]
142                 public void TestInt32MaxDelay ()
143                 {
144                         Bucket b = new Bucket ();
145                         new Timer (new TimerCallback (Callback), b, Int32.MaxValue,
146                                 Timeout.Infinite);
147                         Thread.Sleep (50);
148                         Assert.AreEqual (0, b.count);
149                 }
150
151                 [Test]
152                 public void TestInt32MaxPeriod ()
153                 {
154                         Bucket b = new Bucket ();
155                         new Timer (new TimerCallback (Callback), b, 0,
156                                 Int32.MaxValue);
157                         Thread.Sleep (50);
158                         Assert.AreEqual (1, b.count);
159                         
160                 }
161
162                 [Test]
163                 public void TestNegativeDelay ()
164                 {
165                         Bucket b = new Bucket ();
166                         try {
167                                 new Timer (new TimerCallback (Callback), b, -10,
168                                         Timeout.Infinite);
169                                 Assert.Fail ();
170                         } catch (ArgumentOutOfRangeException) {
171                                 return;
172                         }
173                 }
174
175                 [Test]
176                 public void TestNegativePeriod ()
177                 {
178                         Bucket b = new Bucket ();
179                         try {
180                                 new Timer (new TimerCallback (Callback), b, 0,
181                                         -10);
182                                 Assert.Fail ();
183                         } catch (ArgumentOutOfRangeException) {
184                                 return;
185                         }
186                 }
187
188                 [Test]
189                 public void TestDelayZeroPeriodZero()
190                 {
191                         Bucket b = new Bucket();
192                         Timer t = new Timer(new TimerCallback(Callback),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.IsTrue(b.count == 1);
197                         
198                 }
199
200 #if !MONOTOUCH
201                 [Test]
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 (new TimerCallback (CallbackTestDisposeOnCallback), 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 #endif
219
220                 private void Callback (object foo)
221                 {
222                         Bucket b = foo as Bucket;
223                         Interlocked.Increment (ref b.count);
224                 }
225
226                 [Test]
227                 [ExpectedException (typeof (ArgumentNullException))]
228                 public void DisposeNullWaitHandle ()
229                 {
230                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
231                                 t.Dispose (null);
232                         }
233                 }
234
235                 [Test]
236                 public void Change_IntInt_Infinite ()
237                 {
238                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
239                                 t.Change ((int)Timeout.Infinite, (int)Timeout.Infinite);
240                         }
241                 }
242
243                 [Test]
244                 public void Change_IntInt_MaxValue ()
245                 {
246                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
247                                 t.Change (Int32.MaxValue, Int32.MaxValue);
248                         }
249                 }
250
251                 [Test]
252                 public void Change_UIntUInt_Infinite ()
253                 {
254                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
255                                 t.Change (unchecked ((uint) Timeout.Infinite), unchecked ((uint) Timeout.Infinite));
256                         }
257                 }
258
259                 [Test]
260                 public void Change_UIntUInt_MaxValue ()
261                 {
262                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
263                                 // UInt32.MaxValue == Timeout.Infinite == 0xffffffff
264                                 t.Change (UInt32.MaxValue, UInt32.MaxValue);
265                         }
266                 }
267
268                 [Test]
269                 public void Change_LongLong_Infinite ()
270                 {
271                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
272                                 t.Change ((long) Timeout.Infinite, (long) Timeout.Infinite);
273                         }
274                 }
275
276                 [Test]
277                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
278                 public void Change_LongLong_MaxValue ()
279                 {
280                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
281                                 t.Change (Int64.MaxValue, Int64.MaxValue);
282                         }
283                 }
284
285                 [Test]
286                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
287                 public void Change_LongLong_UInt32MaxValue ()
288                 {
289                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
290                                 // not identical to (long)-1
291                                 t.Change ((long)UInt32.MaxValue, (long)UInt32.MaxValue);
292                         }
293                 }
294
295                 [Test]
296                 public void Change_LongLong_UInt32MaxValueMinusOne ()
297                 {
298                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
299                                 // not identical to (long)-1
300                                 t.Change ((long) UInt32.MaxValue - 1, (long) UInt32.MaxValue -1);
301                         }
302                 }
303
304                 [Test]
305                 public void Change_TimeSpanTimeSpan_Infinite ()
306                 {
307                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
308                                 t.Change (new TimeSpan (-1), new TimeSpan (-1));
309                         }
310                 }
311
312                 [Test]
313                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
314                 public void Change_TimeSpanTimeSpan_MaxValue ()
315                 {
316                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
317                                 t.Change (TimeSpan.MaxValue, TimeSpan.MaxValue);
318                         }
319                 }
320
321                 [Test]
322                 public void Change_TimeSpanTimeSpan_UInt32MaxValue ()
323                 {
324                         using (Timer t = new Timer (DoNothing, null, 0, 0)) {
325                                 t.Change (new TimeSpan (UInt32.MaxValue), new TimeSpan (UInt32.MaxValue));
326                         }
327                 }
328         }
329 }