2014-08-13 10:39:27 +01:00
|
|
|
//
|
|
|
|
// TimerTest.cs - NUnit test cases for System.Threading.Timer
|
|
|
|
//
|
|
|
|
// 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]
|
|
|
|
public class TimerTest {
|
|
|
|
// this bucket is used to avoid non-theadlocal issues
|
|
|
|
class Bucket {
|
|
|
|
public int count;
|
2017-03-15 10:36:24 +00:00
|
|
|
public ManualResetEventSlim mre = new ManualResetEventSlim (false);
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[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.
|
2016-02-22 11:00:01 -05:00
|
|
|
new Timer (o => DoNothing (o), null, Timeout.Infinite, 0);
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DoNothing (object foo)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-03-15 10:36:24 +00:00
|
|
|
private void Callback2 (object foo)
|
|
|
|
{
|
|
|
|
Bucket b = foo as Bucket;
|
|
|
|
Interlocked.Increment (ref b.count);
|
|
|
|
b.mre.Set ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-13 10:39:27 +01:00
|
|
|
[Test]
|
|
|
|
public void TestDueTime ()
|
|
|
|
{
|
|
|
|
Bucket bucket = new Bucket();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
2017-03-15 10:36:24 +00:00
|
|
|
using (Timer t = new Timer (o => Callback2 (o), bucket, 200, Timeout.Infinite)) {
|
|
|
|
Assert.IsTrue (bucket.mre.Wait (5000), "#-1");
|
|
|
|
Assert.AreEqual (1, bucket.count, "#1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestDispose ()
|
|
|
|
{
|
|
|
|
Bucket bucket = new Bucket();
|
|
|
|
|
|
|
|
using (Timer t = new Timer (o => Callback2 (o), bucket, 10, 10)) {
|
|
|
|
Assert.IsTrue (bucket.mre.Wait (5000), "#-1");
|
2016-02-22 11:00:01 -05:00
|
|
|
}
|
2017-03-15 10:36:24 +00:00
|
|
|
//If the callback is called after dispose, it will NRE and be reported
|
|
|
|
bucket.mre = null;
|
|
|
|
int c = bucket.count;
|
|
|
|
Assert.IsTrue (c > 0, "#1");
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestChange ()
|
|
|
|
{
|
|
|
|
Bucket bucket = new Bucket();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
2017-03-15 10:36:24 +00:00
|
|
|
using (Timer t = new Timer (o => Callback2 (o), bucket, 10, 10)) {
|
|
|
|
Assert.IsTrue (bucket.mre.Wait (5000), "#-1");
|
2016-02-22 11:00:01 -05:00
|
|
|
int c = bucket.count;
|
2017-03-15 10:36:24 +00:00
|
|
|
Assert.IsTrue (c > 0, "#1 " + c);
|
|
|
|
t.Change (100000, 1000000);
|
2016-02-22 11:00:01 -05:00
|
|
|
c = bucket.count;
|
|
|
|
Thread.Sleep (500);
|
2017-03-15 10:36:24 +00:00
|
|
|
Assert.IsTrue (bucket.count <= c + 1, "#2 " + c);
|
2016-02-22 11:00:01 -05:00
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestZeroDueTime ()
|
|
|
|
{
|
|
|
|
Bucket bucket = new Bucket();
|
|
|
|
|
2017-03-15 10:36:24 +00:00
|
|
|
using (Timer t = new Timer (o => Callback2 (o), bucket, 0, Timeout.Infinite)) {
|
|
|
|
Assert.IsTrue (bucket.mre.Wait (5000), "#-1");
|
|
|
|
bucket.mre.Reset ();
|
2016-02-22 11:00:01 -05:00
|
|
|
Assert.AreEqual (1, bucket.count, "#1");
|
|
|
|
t.Change (0, Timeout.Infinite);
|
2017-03-15 10:36:24 +00:00
|
|
|
Assert.IsTrue (bucket.mre.Wait (5000), "#1.5");
|
2016-02-22 11:00:01 -05:00
|
|
|
Assert.AreEqual (2, bucket.count, "#2");
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test] // bug #320950
|
|
|
|
public void TestDispose2 ()
|
|
|
|
{
|
2016-06-14 09:39:34 +00:00
|
|
|
Timer t = new Timer (o => DoNothing (o), null, 10, 10);
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Dispose ();
|
|
|
|
t.Dispose ();
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestHeavyCreationLoad ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
2014-08-13 10:39:27 +01:00
|
|
|
for (int i = 0; i < 500; ++i)
|
2016-02-22 11:00:01 -05:00
|
|
|
new Timer (o => Callback (o), b, 10, Timeout.Infinite);
|
|
|
|
|
2014-08-13 10:39:27 +01:00
|
|
|
// 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);
|
|
|
|
}
|
2016-02-22 11:00:01 -05:00
|
|
|
|
2014-08-13 10:39:27 +01:00
|
|
|
Assert.AreEqual (500, b.count);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestQuickDisposeDeadlockBug ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
2016-02-22 11:00:01 -05:00
|
|
|
ArrayList timers = new ArrayList (500);
|
|
|
|
|
|
|
|
for (int i = 0; i < 500; ++i) {
|
|
|
|
using (Timer t = new Timer (o => Callback (o), b, 10, Timeout.Infinite)) {
|
|
|
|
timers.Add (t);
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
2016-02-22 11:00:01 -05:00
|
|
|
|
2014-08-13 10:39:27 +01:00
|
|
|
Thread.Sleep (11 * 500);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestInt32MaxDelay ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
|
|
|
using (new Timer (o => Callback (o), b, Int32.MaxValue, Timeout.Infinite)) {
|
|
|
|
Thread.Sleep (50);
|
|
|
|
Assert.AreEqual (0, b.count);
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestInt32MaxPeriod ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
|
|
|
|
2016-02-22 11:00:01 -05:00
|
|
|
using (new Timer (o => Callback (o), b, 0, Int32.MaxValue)) {
|
|
|
|
Thread.Sleep (50);
|
|
|
|
Assert.AreEqual (1, b.count);
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
2016-02-22 11:00:01 -05:00
|
|
|
[ExpectedException (typeof (ArgumentOutOfRangeException))]
|
2014-08-13 10:39:27 +01:00
|
|
|
public void TestNegativeDelay ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
|
|
|
using (new Timer (o => Callback (o), b, -10, Timeout.Infinite)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
2016-02-22 11:00:01 -05:00
|
|
|
[ExpectedException (typeof (ArgumentOutOfRangeException))]
|
2014-08-13 10:39:27 +01:00
|
|
|
public void TestNegativePeriod ()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket ();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
|
|
|
using (new Timer (o => Callback (o), b, 0, -10)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void TestDelayZeroPeriodZero()
|
|
|
|
{
|
|
|
|
Bucket b = new Bucket();
|
2016-02-22 11:00:01 -05:00
|
|
|
|
|
|
|
using (Timer t = new Timer(o => Callback (o),b,0,0)) {
|
|
|
|
Thread.Sleep(100);
|
|
|
|
t.Change (int.MaxValue, Timeout.Infinite);
|
|
|
|
// since period is 0 the callback should happen once (bug #340212)
|
|
|
|
Assert.AreEqual (1, b.count, "only once");
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[Ignore ()]
|
|
|
|
public void TestDisposeOnCallback ()
|
|
|
|
{
|
|
|
|
// this test is bad, as the provided `state` (t1) is null and will throw an NRE inside the callback
|
|
|
|
// that was ignored before 238785a3e3d510528228fc551625975bc508c2f3 and most unit test runner won't
|
|
|
|
// report it since the NRE will not happen on the main thread (but Touch.Unit will)
|
|
|
|
Timer t1 = null;
|
2016-02-22 11:00:01 -05:00
|
|
|
t1 = new Timer (o => CallbackTestDisposeOnCallback (o), t1, 0, 10);
|
2014-08-13 10:39:27 +01:00
|
|
|
Thread.Sleep (200);
|
|
|
|
Assert.IsNotNull (t1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void CallbackTestDisposeOnCallback (object foo)
|
|
|
|
{
|
|
|
|
((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 ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Dispose (null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_IntInt_Infinite ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change ((int)Timeout.Infinite, (int)Timeout.Infinite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_IntInt_MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (Int32.MaxValue, Int32.MaxValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_UIntUInt_Infinite ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (unchecked ((uint) Timeout.Infinite), unchecked ((uint) Timeout.Infinite));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_UIntUInt_MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
// UInt32.MaxValue == Timeout.Infinite == 0xffffffff
|
|
|
|
t.Change (UInt32.MaxValue, UInt32.MaxValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_LongLong_Infinite ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change ((long) Timeout.Infinite, (long) Timeout.Infinite);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[ExpectedException (typeof (ArgumentOutOfRangeException))]
|
|
|
|
public void Change_LongLong_MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (Int64.MaxValue, Int64.MaxValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[ExpectedException (typeof (ArgumentOutOfRangeException))]
|
|
|
|
public void Change_LongLong_UInt32MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
// not identical to (long)-1
|
|
|
|
t.Change ((long)UInt32.MaxValue, (long)UInt32.MaxValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_LongLong_UInt32MaxValueMinusOne ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
// not identical to (long)-1
|
|
|
|
t.Change ((long) UInt32.MaxValue - 1, (long) UInt32.MaxValue -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_TimeSpanTimeSpan_Infinite ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (new TimeSpan (-1), new TimeSpan (-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
[ExpectedException (typeof (ArgumentOutOfRangeException))]
|
|
|
|
public void Change_TimeSpanTimeSpan_MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (TimeSpan.MaxValue, TimeSpan.MaxValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
public void Change_TimeSpanTimeSpan_UInt32MaxValue ()
|
|
|
|
{
|
2016-02-22 11:00:01 -05:00
|
|
|
using (Timer t = new Timer (o => DoNothing (o), null, 0, 0)) {
|
2014-08-13 10:39:27 +01:00
|
|
|
t.Change (new TimeSpan (UInt32.MaxValue), new TimeSpan (UInt32.MaxValue));
|
|
|
|
}
|
|
|
|
}
|
2018-01-24 17:04:36 +00:00
|
|
|
|
|
|
|
[Test]
|
|
|
|
[ExpectedException (typeof (ObjectDisposedException))]
|
|
|
|
public void Change_After_Dispose ()
|
|
|
|
{
|
|
|
|
var t = new Timer (o => DoNothing (o), null, 0, 0);
|
|
|
|
t.Dispose ();
|
|
|
|
t.Change (1, 1);
|
|
|
|
}
|
2014-08-13 10:39:27 +01:00
|
|
|
}
|
|
|
|
}
|