dotnet / dotnet/extensions

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

Open
#5,722 2 comments 1 reaction 0 assignees View on GitHub
area-fundamentals bug untriaged
Dominant language
C#
Stars
3.2k
Forks
894
Avg merge
1d 12h
Merged PRs (30d)
23

Description

### 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

```csharp
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_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.