Skip to content

[Microsoft.Extensions.TimeProvider.Testing] FakeTimeProvider does not simulate timers correctly, misses executions #5722

Description

@bara-pweber

Description

I am working with a non-periodic Timer that re-schedules itself with the ITimer.Change method. I noticed that FakeTimeProvider.Advance only ever executes the timer once, even if I provide a TimeSpan that covers multiple executions.

Reproduction Steps

public class TimerBugRepro
{
    [Fact]
    public void TestWithSystemTime() // Works
    {
        Assert.Equal(2, RunTestWithTimeProvider(TimeProvider.System, () => Thread.Sleep(TimeSpan.FromSeconds(3))));
    }

    [Fact]
    public void TestWithFakeTime() // Fails
    {
        var fakeTime = new FakeTimeProvider();
        Assert.Equal(2, RunTestWithTimeProvider(fakeTime, () => fakeTime.Advance(TimeSpan.FromSeconds(3))));
    }

    private int RunTestWithTimeProvider(TimeProvider timeProvider, Action sleepAction)
    {
        int count = 0;
        ITimer timer = null;
        timer = timeProvider.CreateTimer(
            _ =>
            {
                Interlocked.Increment(ref count);
                timer.Change(TimeSpan.FromSeconds(2), Timeout.InfiniteTimeSpan);
            },
            null,
            Timeout.InfiniteTimeSpan,
            Timeout.InfiniteTimeSpan);

        timer.Change(TimeSpan.FromMilliseconds(1), Timeout.InfiniteTimeSpan); // Both tests work for TimeSpan.Zero

        sleepAction();

        return count;
    }
}

Expected behavior

The FakeTimeProvider.Advance should correctly simulate the behavior for TimeProvider.System + Thread.Sleep.

Actual behavior

The Fake-Timer does not get re-sheduled correctly.

Regression?

No response

Known Workarounds

No response

Configuration

.NET SDK version: 9.0.100
TargetFramework: net8.0
Microsoft.Extensions.TimeProvider.Testing version: 9.0.0
OS: Windows 10 10.0.19045

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-fundamentalsbugThis issue describes a behavior which is not expected - a bug.untriaged

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions