Skip to content

Commit 78f50a2

Browse files
committed
feat: added StartTime to ManualTimeProvider
1 parent a56cb14 commit 78f50a2

File tree

6 files changed

+61
-14
lines changed

6 files changed

+61
-14
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to TimeScheduler will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.0.0-preview.4]
9+
10+
- Added 'StartTime' to `ManualTestProvider`, which represents the initial date/time when the `ManualtTimeProvider` was initialized.
11+
812
## [1.0.0-preview.3]
913

1014
- Changed `ManualTestProvider` sets the local time zone to UTC by default, provides method for overriding during testing.

src/TimeProviderExtensions/ManualTimeProvider.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public class ManualTimeProvider : TimeProvider
2626
private DateTimeOffset utcNow;
2727
private TimeZoneInfo localTimeZone = TimeZoneInfo.Utc;
2828

29+
/// <summary>
30+
/// Gets the date and time which was set when this <see cref="TimeProvider"/> was initialized.
31+
/// </summary>
32+
public DateTimeOffset StartTime { get; }
33+
2934
/// <summary>
3035
/// Gets the frequency of <see cref="GetTimestamp"/> of high-frequency value per second.
3136
/// </summary>
@@ -44,9 +49,8 @@ public class ManualTimeProvider : TimeProvider
4449
/// </summary>
4550
/// <param name="localTimeZone">Optional local time zone to use during testing. Defaults to <see cref="TimeZoneInfo.Utc"/>.</param>
4651
public ManualTimeProvider(TimeZoneInfo? localTimeZone = null)
47-
: this(Epoch)
48-
{
49-
this.localTimeZone = localTimeZone ?? TimeZoneInfo.Utc;
52+
: this(Epoch, localTimeZone)
53+
{
5054
}
5155

5256
/// <summary>
@@ -55,8 +59,8 @@ public ManualTimeProvider(TimeZoneInfo? localTimeZone = null)
5559
/// </summary>
5660
/// <param name="startDateTime">The initial date and time <see cref="GetUtcNow()"/> will return.</param>
5761
public ManualTimeProvider(DateTimeOffset startDateTime)
62+
: this(startDateTime, TimeZoneInfo.Utc)
5863
{
59-
utcNow = startDateTime;
6064
}
6165

6266
/// <summary>
@@ -68,6 +72,7 @@ public ManualTimeProvider(DateTimeOffset startDateTime)
6872
public ManualTimeProvider(DateTimeOffset startDateTime, TimeZoneInfo? localTimeZone = null)
6973
{
7074
utcNow = startDateTime;
75+
StartTime = startDateTime;
7176
this.localTimeZone = localTimeZone ?? TimeZoneInfo.Utc;
7277
}
7378

@@ -165,13 +170,6 @@ public void Advance(TimeSpan delta)
165170
SetUtcNow(utcNow + delta);
166171
}
167172

168-
/// <summary>
169-
/// Advance the date and time represented by <see cref="GetUtcNow()"/>
170-
/// by one millisecond, and triggers any scheduled items that are waiting for time to be forwarded.
171-
/// </summary>
172-
public void Advance()
173-
=> Advance(TimeSpan.FromMilliseconds(1));
174-
175173
/// <summary>
176174
/// Sets the date and time returned by <see cref="GetUtcNow()"/> to <paramref name="newUtcNew"/> and triggers any
177175
/// scheduled items that are waiting for time to be forwarded.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace TimeProviderExtensions;
2+
3+
public static class ManualTimeProviderExtensions
4+
{
5+
/// <summary>
6+
/// Advance the date and time represented by <see cref="GetUtcNow()"/>
7+
/// by one millisecond, and triggers any scheduled items that are waiting for time to be forwarded.
8+
/// </summary>
9+
public static void Advance(this ManualTimeProvider timeProvider)
10+
=> timeProvider.Advance(TimeSpan.FromMilliseconds(1));
11+
}

test/TimeProviderExtensions.Tests/ManualTimeProviderTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,37 @@ await Task.Delay(TimeSpan.FromDays(1))
8181
}
8282
}
8383
#endif
84+
85+
#if NET8_0_OR_GREATER
86+
[Fact]
87+
public async Task Callbacks_happens_in_schedule_order()
88+
{
89+
var sut = new SutTimeProvider();
90+
var periodicTimer = sut.CreatePeriodicTimer(TimeSpan.FromSeconds(10));
91+
var startTime = sut.GetUtcNow();
92+
var callbacks = new List<DateTimeOffset>();
93+
var callbacksTask = AsyncCallbacks(periodicTimer);
94+
95+
sut.Advance(TimeSpan.FromSeconds(23));
96+
97+
callbacks.Should().ContainInOrder(
98+
startTime + TimeSpan.FromSeconds(10),
99+
startTime + TimeSpan.FromSeconds(13),
100+
startTime + TimeSpan.FromSeconds(20),
101+
startTime + TimeSpan.FromSeconds(23));
102+
103+
periodicTimer.Dispose();
104+
await callbacksTask;
105+
106+
async Task AsyncCallbacks(PeriodicTimer periodicTimer)
107+
{
108+
while (await periodicTimer.WaitForNextTickAsync().ConfigureAwait(false))
109+
{
110+
callbacks.Add(sut.GetUtcNow());
111+
await sut.Delay(TimeSpan.FromSeconds(3));
112+
callbacks.Add(sut.GetUtcNow());
113+
}
114+
}
115+
}
116+
#endif
84117
}

test/TimeProviderExtensions.Tests/ManualTimeProviderTimerTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ public void Change_timer()
107107
}
108108

109109
[Fact]
110-
public void Timer_callback_invoked_multiple_times_single_forward()
110+
public void Timer_callback_invoked_multiple_times_single_advance()
111111
{
112-
var callbackCount = 0;
113112
var sut = new SutTimeProvider();
113+
var callbackCount = 0;
114114
var dueTime = TimeSpan.FromSeconds(3);
115115
var period = TimeSpan.FromSeconds(5);
116116
using var timer = sut.CreateTimer(_ => callbackCount++, null, dueTime, period);
@@ -131,7 +131,7 @@ public void GetUtcNow_matches_time_at_callback_time()
131131

132132
sut.Advance(interval + interval + interval);
133133

134-
callbackTimes.Should().Equal(
134+
callbackTimes.Should().ContainInOrder(
135135
startTime + interval,
136136
startTime + interval + interval,
137137
startTime + interval + interval + interval);

test/TimeProviderExtensions.Tests/Microsoft.Extensions.Time.Testing.Test/FakeTimeProviderTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using SutTimeProvider = Microsoft.Extensions.Time.Testing.FakeTimeProvider;
33
#else
44
using SutTimeProvider = TimeProviderExtensions.ManualTimeProvider;
5+
using TimeProviderExtensions;
56
#endif
67

78
// Licensed to the .NET Foundation under one or more agreements.

0 commit comments

Comments
 (0)