// // TimerTest.cs - NUnit Test Cases for System.Timers.Timer // // Author: // Kornél Pál // Robert Jordan // // Copyright (C) 2005 Kornél Pál // // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using NUnit.Framework; using System; using System.Timers; using ST = System.Threading; namespace MonoTests.System.Timers { [TestFixture] public class TimerTest { Timer timer; int _elapsedCount; [SetUp] public void SetUp () { timer = new Timer (); } [TearDown] public void TearDown () { timer.Close (); } [Test] public void Constructor0 () { Assert.IsTrue (timer.AutoReset, "#1"); Assert.IsFalse (timer.Enabled, "#2"); Assert.AreEqual (100, timer.Interval, "#3"); Assert.IsNull (timer.SynchronizingObject, "#4"); } [Test] public void Constructor1 () { timer = new Timer (1); Assert.IsTrue (timer.AutoReset, "#A1"); Assert.IsFalse (timer.Enabled, "#A2"); Assert.AreEqual (1, timer.Interval, "#A3"); Assert.IsNull (timer.SynchronizingObject, "#A4"); timer = new Timer (int.MaxValue); Assert.IsTrue (timer.AutoReset, "#B1"); Assert.IsFalse (timer.Enabled, "#B2"); Assert.AreEqual (int.MaxValue, timer.Interval, "#B3"); Assert.IsNull (timer.SynchronizingObject, "#B4"); } [Test] public void Constructor1_Interval_Negative () { try { new Timer (-1); Assert.Fail ("#1"); } catch (ArgumentException ex) { // Invalid value -1 for parameter interval Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); } } [Test] public void Constructor1_Interval_Zero () { try { new Timer (0); Assert.Fail ("#1"); } catch (ArgumentException ex) { // Invalid value 0 for parameter interval Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); } } [Test] public void Constructor1_Interval_Max () { try { new Timer (0x80000000); Assert.Fail ("#A1"); } catch (ArgumentException ex) { // Invalid value 2147483648 for parameter interval Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2"); Assert.IsNull (ex.InnerException, "#A3"); Assert.IsNotNull (ex.Message, "#A4"); } try { new Timer (double.MaxValue); Assert.Fail ("#B1"); } catch (ArgumentException ex) { // Invalid value 1.79769313486232E+308 for parameter interval Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2"); Assert.IsNull (ex.InnerException, "#B3"); Assert.IsNotNull (ex.Message, "#B4"); } } [Test] [ExpectedException (typeof (ArgumentException))] public void Constructor1_Interval_Max_2 () { timer = new Timer (double.MaxValue); } [Test] [ExpectedException (typeof (ArgumentException))] public void Constructor1_Interval_Min_1 () { timer = new Timer (0); } [Test] [ExpectedException (typeof (ArgumentException))] public void Constructor1_Interval_Min_2 () { timer = new Timer (-5); } [Test] public void Interval_TooHigh_Disabled_NoThrow () { timer.Interval = double.MaxValue; Assert.AreEqual (double.MaxValue, timer.Interval, "#3"); } [Test] public void Interval_TooHigh_ThrowOnEnabled () { timer.Interval = 0x80000000; Assert.AreEqual (0x80000000, timer.Interval, "#1"); try { timer.Enabled = true; Assert.Fail ("#2"); } catch (Exception ex) { Assert.AreEqual (typeof (ArgumentOutOfRangeException), ex.GetType (), "#3"); Assert.IsTrue (timer.Enabled); } } [Test] [ExpectedException (typeof (ArgumentOutOfRangeException))] public void Interval_TooHigh_Enabled_Throw () { timer.Interval = 100; timer.Enabled = true; timer.Interval = double.MaxValue; } [Test] public void DoubleClose_NoThrow () { timer.Interval = 100; timer.Start (); timer.Close (); timer.Close (); } [Test] public void DisposedMeansDisabled_NoThrow () { timer.Interval = 100; timer.Start (); timer.Close (); Assert.IsFalse (timer.Enabled); } [Test] public void Disposed_ThrowOnEnabled () { timer.Interval = 100; timer.Start (); timer.Close (); timer.Enabled = false; } [Test] public void Elapsed_DontFireIfDisposed () { timer.Interval = 500; var countElapsedCalls = 0; timer.Elapsed += (_, __) => { countElapsedCalls++; }; timer.Start (); timer.Close (); ST.Thread.Sleep (500); Assert.AreEqual (countElapsedCalls, 0); } [Test] public void AutoReset () { Assert.IsTrue (timer.AutoReset, "#1"); timer.AutoReset = false; Assert.IsFalse (timer.AutoReset, "#2"); } [Test] public void Interval () { timer.Interval = 1; Assert.AreEqual (1, timer.Interval, "#1"); timer.Interval = 500; Assert.AreEqual (500, timer.Interval, "#2"); timer.Interval = double.MaxValue; Assert.AreEqual (double.MaxValue, timer.Interval, "#3"); } [Test] public void Interval_Negative () { try { timer.Interval = -1; Assert.Fail ("#1"); } catch (ArgumentException ex) { // '0' is not a valid value for 'Interval'. 'Interval' must be greater than 0 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); } } [Test] public void Interval_Zero () { try { timer.Interval = 0; Assert.Fail ("#1"); } catch (ArgumentException ex) { // '0' is not a valid value for 'Interval'. 'Interval' must be greater than 0 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2"); Assert.IsNull (ex.InnerException, "#3"); Assert.IsNotNull (ex.Message, "#4"); } } [Test] public void StartStopEnabled () { timer.Start (); Assert.IsTrue (timer.Enabled, "#1"); timer.Stop (); Assert.IsFalse (timer.Enabled, "#2"); } [Test] public void CloseEnabled () { Assert.IsFalse (timer.Enabled, "#1"); timer.Enabled = true; Assert.IsTrue (timer.Enabled, "#2"); timer.Close (); Assert.IsFalse (timer.Enabled, "#3"); } [Test] // bug #325368 public void EnabledInElapsed () { _elapsedCount = 0; timer = new Timer (50); timer.AutoReset = false; timer.Elapsed += new ElapsedEventHandler (EnabledInElapsed_Elapsed); timer.Start (); ST.Thread.Sleep (200); timer.Stop (); Assert.IsTrue (_elapsedCount == 2, "#1 loss of events"); } [Test] public void TestRaceCondition () { Assert.IsTrue (new RaceTest (true).Success, "#1"); Assert.IsTrue (new RaceTest (false).Success, "#2"); } void EnabledInElapsed_Elapsed (object sender, ElapsedEventArgs e) { _elapsedCount++; Timer t = sender as Timer; if (_elapsedCount == 1) t.Enabled = true; } } class RaceTest { const int Threads = 2; const int Loops = 100; object locker = new object (); Timer timer; int counter; public bool Success { get { return counter > Loops * Threads; } } public RaceTest (bool autoReset) { timer = new Timer (); timer.AutoReset = autoReset; timer.Interval = 100; timer.Elapsed += new ElapsedEventHandler (Tick); timer.Start (); ST.Thread[] tl = new ST.Thread [Threads]; for (int i = 0; i < Threads; i++) { tl [i] = new ST.Thread (new ST.ThreadStart (Run)); tl [i].Start (); } for (int i = 0; i < Threads; i++) { tl [i].Join (); } ST.Thread.Sleep (1000); } void Restart () { lock (locker) { timer.Stop (); timer.Start (); } ST.Interlocked.Increment (ref counter); } void Tick (object sender, ElapsedEventArgs e) { Restart (); } void Run () { for (int i = 0; i < Loops; i++) { ST.Thread.Sleep (0); Restart (); } } } }