Files
linux-packaging-mono/external/corefx/src/System.Threading.Timer/tests/TimerFiringTests.cs
Xamarin Public Jenkins (auto-signing) 6bdd276d05 Imported Upstream version 5.0.0.42
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
2017-04-10 11:41:01 +00:00

187 lines
6.2 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using System.Threading;
using Xunit;
public partial class TimerFiringTests
{
internal const int MaxPositiveTimeoutInMs = 30000;
[Fact]
public void Timer_Fires_After_DueTime_Ellapses()
{
AutoResetEvent are = new AutoResetEvent(false);
using (var t = new Timer(new TimerCallback((object s) =>
{
are.Set();
}), null, TimeSpan.FromMilliseconds(250), TimeSpan.FromMilliseconds(Timeout.Infinite) /* not relevant */))
{
Assert.True(are.WaitOne(TimeSpan.FromMilliseconds(MaxPositiveTimeoutInMs)));
}
}
[Fact]
public void Timer_Fires_AndPassesStateThroughCallback()
{
AutoResetEvent are = new AutoResetEvent(false);
object state = new object();
using (var t = new Timer(new TimerCallback((object s) =>
{
Assert.Same(s, state);
are.Set();
}), state, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(Timeout.Infinite) /* not relevant */))
{
Assert.True(are.WaitOne(TimeSpan.FromMilliseconds(MaxPositiveTimeoutInMs)));
}
}
[Fact]
public void Timer_Fires_AndPassesNullStateThroughCallback()
{
AutoResetEvent are = new AutoResetEvent(false);
using (var t = new Timer(new TimerCallback((object s) =>
{
Assert.Null(s);
are.Set();
}), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(Timeout.Infinite) /* not relevant */))
{
Assert.True(are.WaitOne(TimeSpan.FromMilliseconds(MaxPositiveTimeoutInMs)));
}
}
[Fact]
public void Timer_Fires_After_DueTime_AndOn_Period()
{
int count = 0;
AutoResetEvent are = new AutoResetEvent(false);
using (var t = new Timer(new TimerCallback((object s) =>
{
if (Interlocked.Increment(ref count) >= 2)
{
are.Set();
}
}), null, TimeSpan.FromMilliseconds(250), TimeSpan.FromMilliseconds(50)))
{
Assert.True(are.WaitOne(TimeSpan.FromMilliseconds(MaxPositiveTimeoutInMs)));
}
}
[Fact]
public void Timer_FiresOnlyOnce_OnDueTime_With_InfinitePeriod()
{
int count = 0;
AutoResetEvent are = new AutoResetEvent(false);
using (var t = new Timer(new TimerCallback((object s) =>
{
if (Interlocked.Increment(ref count) >= 2)
{
are.Set();
}
}), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(Timeout.Infinite) /* not relevant */))
{
Assert.False(are.WaitOne(TimeSpan.FromMilliseconds(250 /*enough for 2 fires + buffer*/)));
}
}
[Fact]
public void Timer_CanDisposeSelfInCallback()
{
Timer t = null;
AutoResetEvent are = new AutoResetEvent(false);
TimerCallback tc = new TimerCallback((object o) =>
{
t.Dispose();
are.Set();
});
t = new Timer(tc, null, -1, -1);
t.Change(1, -1);
Assert.True(are.WaitOne(MaxPositiveTimeoutInMs));
GC.KeepAlive(t);
}
[Fact]
public void Timer_CanBeDisposedMultipleTimes()
{
// There's nothing to validate besides that we don't throw an exception, so rely on xunit
// to catch any exception that would be thrown and signal a test failure
TimerCallback tc = new TimerCallback((object o) => { });
var t = new Timer(tc, null, 100, -1);
for (int i = 0; i < 10; i++)
t.Dispose();
}
[Fact]
public void NonRepeatingTimer_ThatHasAlreadyFired_CanChangeAndFireAgain()
{
AutoResetEvent are = new AutoResetEvent(false);
TimerCallback tc = new TimerCallback((object o) => are.Set());
using (var t = new Timer(tc, null, 1, Timeout.Infinite))
{
Assert.True(are.WaitOne(MaxPositiveTimeoutInMs), "Should have received first timer event");
Assert.False(are.WaitOne(500), "Should not have received a second timer event");
t.Change(10, Timeout.Infinite);
Assert.True(are.WaitOne(MaxPositiveTimeoutInMs), "Should have received a second timer event after changing it");
}
}
[Fact]
public void Running_Timer_CanBeFinalizedAndStopsFiring()
{
AutoResetEvent are = new AutoResetEvent(false);
TimerCallback tc = new TimerCallback((object o) => are.Set());
var t = new Timer(tc, null, 1, 500);
Assert.True(are.WaitOne(MaxPositiveTimeoutInMs), "Failed to get first timer fire");
t = null; // Remove our refence so the timer can be GC'd
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Assert.False(are.WaitOne(500), "Should not have received a timer fire after it was collected");
}
[Fact]
public void MultpleTimers_PeriodicTimerIsntBlockedByBlockedCallback()
{
int callbacks = 2;
Barrier b = new Barrier(callbacks + 1);
Timer t = null;
t = new Timer(_ =>
{
if (Interlocked.Decrement(ref callbacks) >= 0)
{
Assert.True(b.SignalAndWait(MaxPositiveTimeoutInMs));
}
t.Dispose();
}, null, -1, -1);
t.Change(1, 50);
Assert.True(b.SignalAndWait(MaxPositiveTimeoutInMs));
GC.KeepAlive(t);
}
[Fact]
public void ManyTimers_EachTimerDoesFire()
{
int maxTimers = 10000;
CountdownEvent ce = new CountdownEvent(maxTimers);
Timer[] timers = System.Linq.Enumerable.Range(0, maxTimers).Select(_ => new Timer(s => ce.Signal(), null, 100 /* enough time to wait on the are */, -1)).ToArray();
try
{
Assert.True(ce.Wait(MaxPositiveTimeoutInMs), String.Format("Not all timers fired, {0} left of {1}", ce.CurrentCount, maxTimers));
}
finally
{
foreach (Timer t in timers)
t.Dispose();
}
}
}