You've already forked linux-packaging-mono
187 lines
6.2 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|