Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / corlib / Test / System.Threading / TimerTest.cs
index cc0e3976950ee738ba52fbe1cee3ed69dcb4a180..67737cbef0f7dbd51622aea789f61b762c849aad 100644 (file)
@@ -3,6 +3,7 @@
 //
 // Author:
 //   Zoltan Varga (vargaz@freemail.hu)
+//   Rafael Ferreira (raf@ophion.org)
 //
 // (C) 2004 Novell, Inc (http://www.novell.com)
 //
 using NUnit.Framework;
 using System;
 using System.Threading;
+using System.Collections;
 
 namespace MonoTests.System.Threading {
-
        [TestFixture]
-       //
-       // This whole test seems to fail randomly. Either
-       // - It is relying on a race it might not win (that the timer code runs)
-       // - We have a very obscure bug with appdomains.
-       //
-       // Am going with door #1, but it would be nice to investigate this.
-       // -- Ben
-       //
-       public class TimerTest : Assertion {
-               [Test]
-               [Category ("NotWorking")]
+       public class TimerTest {
+               // this bucket is used to avoid non-theadlocal issues
+               class Bucket {
+                       public int count;
+               }
+
+               [SetUp]
+               public void Setup ()
+               {
+                       //creating a timer that will never run just to make sure the
+                       // scheduler is warm for the unit tests
+                       // this makes fair for the "DueTime" test since it 
+                       // doesn't have to wait for the scheduler thread to be 
+                       // created. 
+                       new Timer (new TimerCallback (DoNothing), null, Timeout.Infinite, 0);
+               }
+
+               void DoNothing (object foo)
+               {
+               }
+
+               [Test]
                public void TestDueTime ()
                {
-                       counter = 0;
-                       Timer t = new Timer (new TimerCallback (Callback), null, 200, Timeout.Infinite);
+                       Bucket bucket = new Bucket();
+                       Timer t = new Timer (new TimerCallback (Callback), bucket, 200, Timeout.Infinite);
                        Thread.Sleep (50);
-                       AssertEquals ("t0", 0, counter);
+                       Assert.AreEqual (0, bucket.count, "#1");
                        Thread.Sleep (200);
-                       AssertEquals ("t1", 1, counter);
+                       Assert.AreEqual (1, bucket.count, "#2");
                        Thread.Sleep (500);
-                       AssertEquals ("t2", 1, counter);
-                       
+                       Assert.AreEqual (1, bucket.count, "#3");
                        t.Change (10, 10);
-                       Thread.Sleep (500);
-                       Assert ("t3", counter > 20);
+                       Thread.Sleep (1000);
+                       Assert.IsTrue(bucket.count > 20, "#4");
                        t.Dispose ();
                }
 
                [Test]
-               [Category ("NotWorking")]
                public void TestChange ()
                {
-                       counter = 0;
-                       Timer t = new Timer (new TimerCallback (Callback), null, 1, 1);
+                       Bucket bucket = new Bucket();
+                       Timer t = new Timer (new TimerCallback (Callback), bucket, 10, 10);
                        Thread.Sleep (500);
-                       int c = counter;
-                       Assert ("t1", c > 20);
+                       int c = bucket.count;
+                       Assert.IsTrue(c > 20, "#1");
                        t.Change (100, 100);
+                       c = bucket.count;
                        Thread.Sleep (500);
-                       Assert ("t2", counter <= c + 6);
+                       Assert.IsTrue(bucket.count <= c + 20, "#2");
                        t.Dispose ();
                }
 
                [Test]
-               [Category ("NotWorking")]
-               public void TestZeroDueTime () {
-                       counter = 0;
+               public void TestZeroDueTime ()
+               {
+                       Bucket bucket = new Bucket();
 
-                       Timer t = new Timer (new TimerCallback (Callback), null, 0, Timeout.Infinite);
+                       Timer t = new Timer (new TimerCallback (Callback), bucket, 0, Timeout.Infinite);
                        Thread.Sleep (100);
-                       AssertEquals (1, counter);
+                       Assert.AreEqual (1, bucket.count, "#1");
                        t.Change (0, Timeout.Infinite);
                        Thread.Sleep (100);
-                       AssertEquals (2, counter);
+                       Assert.AreEqual (2, bucket.count, "#2");
                        t.Dispose ();
                }
 
                [Test]
-               [Category ("NotWorking")]
                public void TestDispose ()
-               {
-                       counter = 0;
-                       Timer t = new Timer (new TimerCallback (CallbackTestDispose), null, 10, 10);
+               {       
+                       Bucket bucket = new Bucket();
+                       Timer t = new Timer (new TimerCallback (Callback), bucket, 10, 10);
                        Thread.Sleep (200);
                        t.Dispose ();
                        Thread.Sleep (20);
-                       int c = counter;
-                       Assert (counter > 5);
+                       int c = bucket.count;
+                       Assert.IsTrue (bucket.count > 5, "#1");
                        Thread.Sleep (200);
-                       AssertEquals (c, counter);
+                       Assert.AreEqual (c, bucket.count, "#2");
                }
 
-               [Test] // bug #78208
+               [Test] // bug #320950
                public void TestDispose2 ()
                {
-                       Timer t = new Timer (new TimerCallback (CallbackTestDispose), null, 10, 10);
+                       Timer t = new Timer (new TimerCallback (Callback), null, 10, 10);
                        t.Dispose ();
                        t.Dispose ();
                }
                
                [Test]
-               [Category ("NotWorking")]
-               public void TestDisposeOnCallback () {
-                       counter = 0;
-                       t1 = new Timer (new TimerCallback (CallbackTestDisposeOnCallback), null, 0, 10);
-                       Thread.Sleep (200);
-                       AssertNull (t1);
+               public void TestHeavyCreationLoad ()
+               {
+                       Bucket b = new Bucket ();
+                       for (int i = 0; i < 500; ++i)
+                               new Timer (new TimerCallback (Callback), b, 10,
+                                       Timeout.Infinite);
+                       // 1000 * 10 msec = 10,000 msec or 10 sec - if everything goes well
+                       // we add some slack to cope with timing issues caused by system load etc.
+                       for (int i = 0; i < 20; ++i) {
+                               if (b.count == 500)
+                                       break;
+                               Thread.Sleep (1000);
+                       }
+                       Assert.AreEqual (500, b.count);
+                       
+               }
+
+               [Test]
+               public void TestQuickDisposeDeadlockBug ()
+               {
+                       int i = 0;
+                       Bucket b = new Bucket ();
+                       ArrayList timers = new ArrayList();
+                       while (i < 500) {
+                               Timer t = new Timer (new TimerCallback (Callback),
+                                       b, 10, Timeout.Infinite);
+                               timers.Add (t);
+                               i++;
+                               t.Dispose ();
+                       }
+                       Thread.Sleep (11 * 500);
+               }
+
+               [Test]
+               public void TestInt32MaxDelay ()
+               {
+                       Bucket b = new Bucket ();
+                       new Timer (new TimerCallback (Callback), b, Int32.MaxValue,
+                               Timeout.Infinite);
+                       Thread.Sleep (50);
+                       Assert.AreEqual (0, b.count);
+               }
+
+               [Test]
+               public void TestInt32MaxPeriod ()
+               {
+                       Bucket b = new Bucket ();
+                       new Timer (new TimerCallback (Callback), b, 0,
+                               Int32.MaxValue);
+                       Thread.Sleep (50);
+                       Assert.AreEqual (1, b.count);
+                       
+               }
+
+               [Test]
+               public void TestNegativeDelay ()
+               {
+                       Bucket b = new Bucket ();
+                       try {
+                               new Timer (new TimerCallback (Callback), b, -10,
+                                       Timeout.Infinite);
+                               Assert.Fail ();
+                       } catch (ArgumentOutOfRangeException) {
+                               return;
+                       }
+               }
+
+               [Test]
+               public void TestNegativePeriod ()
+               {
+                       Bucket b = new Bucket ();
+                       try {
+                               new Timer (new TimerCallback (Callback), b, 0,
+                                       -10);
+                               Assert.Fail ();
+                       } catch (ArgumentOutOfRangeException) {
+                               return;
+                       }
+               }
+
+               [Test]
+               public void TestDelayZeroPeriodZero()
+               {
+                       Bucket b = new Bucket();
+                       Timer t = new Timer(new TimerCallback(Callback),b,0,0);
+                       Thread.Sleep(100);
+                       t.Change (int.MaxValue, Timeout.Infinite);
+                       // since period is 0 the callback should happen once (bug #340212)
+                       Assert.IsTrue(b.count == 1);
                        
-                       counter = 2;
-                       t1 = new Timer (new TimerCallback (CallbackTestDisposeOnCallback), null, 50, 0);
+               }
+
+               [Test]
+               public void TestDisposeOnCallback ()
+               {
+                       Timer t1 = null;
+                       t1 = new Timer (new TimerCallback (CallbackTestDisposeOnCallback), t1, 0, 10);
                        Thread.Sleep (200);
-                       AssertNull (t1);
+                       Assert.IsNotNull (t1);
+                       
                }
-               
+
                private void CallbackTestDisposeOnCallback (object foo)
                {
-                       if (++counter == 3) {
-                               t1.Dispose ();
-                               t1 = null;
+                       ((Timer) foo).Dispose ();
+               }
+               
+               private void Callback (object foo)
+               {
+                       Bucket b = foo as Bucket;
+                       Interlocked.Increment (ref b.count);
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentNullException))]
+               public void DisposeNullWaitHandle ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Dispose (null);
                        }
                }
 
-               private void CallbackTestDispose (object foo)
+               [Test]
+               public void Change_IntInt_Infinite ()
                {
-                       counter++;
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change ((int)Timeout.Infinite, (int)Timeout.Infinite);
+                       }
                }
 
-               private void Callback (object foo)
+               [Test]
+               public void Change_IntInt_MaxValue ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (Int32.MaxValue, Int32.MaxValue);
+                       }
+               }
+
+               [Test]
+               public void Change_UIntUInt_Infinite ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (unchecked ((uint) Timeout.Infinite), unchecked ((uint) Timeout.Infinite));
+                       }
+               }
+
+               [Test]
+               public void Change_UIntUInt_MaxValue ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               // UInt32.MaxValue == Timeout.Infinite == 0xffffffff
+                               t.Change (UInt32.MaxValue, UInt32.MaxValue);
+                       }
+               }
+
+               [Test]
+               public void Change_LongLong_Infinite ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change ((long) Timeout.Infinite, (long) Timeout.Infinite);
+                       }
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentOutOfRangeException))]
+               public void Change_LongLong_MaxValue ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (Int64.MaxValue, Int64.MaxValue);
+                       }
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentOutOfRangeException))]
+               public void Change_LongLong_UInt32MaxValue ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               // not identical to (long)-1
+                               t.Change ((long)UInt32.MaxValue, (long)UInt32.MaxValue);
+                       }
+               }
+
+               [Test]
+               public void Change_LongLong_UInt32MaxValueMinusOne ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               // not identical to (long)-1
+                               t.Change ((long) UInt32.MaxValue - 1, (long) UInt32.MaxValue -1);
+                       }
+               }
+
+               [Test]
+               public void Change_TimeSpanTimeSpan_Infinite ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (new TimeSpan (-1), new TimeSpan (-1));
+                       }
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentOutOfRangeException))]
+               public void Change_TimeSpanTimeSpan_MaxValue ()
                {
-                       counter++;
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (TimeSpan.MaxValue, TimeSpan.MaxValue);
+                       }
                }
 
-               Timer t1;
-               int counter;
+               [Test]
+               public void Change_TimeSpanTimeSpan_UInt32MaxValue ()
+               {
+                       using (Timer t = new Timer (DoNothing, null, 0, 0)) {
+                               t.Change (new TimeSpan (UInt32.MaxValue), new TimeSpan (UInt32.MaxValue));
+                       }
+               }
        }
 }