Skip to content

Commit 7f265fc

Browse files
committed
refactor: replaced AutoAdvanceAmount with AutoAdvanceBehavior
1 parent c0fbde4 commit 7f265fc

File tree

9 files changed

+104
-60
lines changed

9 files changed

+104
-60
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717

1818
Overriding `CreateManualTimer` makes it possible to intercept a `TimerCallback` and perform actions before and after the timer callback has been invoked.
1919

20+
- Replace `AutoAdvanceAmount` property with the `AutoAdvanceBehavior` property on `ManualTimeProvider`, and introduced the `AutoAdvanceBehavior` type.
21+
2022
## [1.0.0-rc.1]
2123

2224
- Updated Microsoft.Bcl.TimeProvider package dependency to rc.1 version.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#### [TimeProviderExtensions](index.md 'index')
2+
### [TimeProviderExtensions](index.md#TimeProviderExtensions 'TimeProviderExtensions')
3+
4+
## AutoAdvanceBehavior Class
5+
6+
The [AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior') type provides a way to enable and customize the automatic advance of time.
7+
8+
```csharp
9+
public sealed class AutoAdvanceBehavior :
10+
System.IEquatable<TimeProviderExtensions.AutoAdvanceBehavior>
11+
```
12+
13+
Inheritance [System.Object](https://docs.microsoft.com/en-us/dotnet/api/System.Object 'System.Object') &#129106; AutoAdvanceBehavior
14+
15+
Implements [System.IEquatable&lt;](https://docs.microsoft.com/en-us/dotnet/api/System.IEquatable-1 'System.IEquatable`1')[AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior')[&gt;](https://docs.microsoft.com/en-us/dotnet/api/System.IEquatable-1 'System.IEquatable`1')
16+
### Properties
17+
18+
<a name='TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount'></a>
19+
20+
## AutoAdvanceBehavior.ClockAdvanceAmount Property
21+
22+
Gets or sets the amount of time by which time advances whenever the clock is read via [System.TimeProvider.GetUtcNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetUtcNow 'System.TimeProvider.GetUtcNow') or [System.TimeProvider.GetLocalNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetLocalNow 'System.TimeProvider.GetLocalNow').
23+
24+
```csharp
25+
public System.TimeSpan ClockAdvanceAmount { get; set; }
26+
```
27+
28+
#### Property Value
29+
[System.TimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan 'System.TimeSpan')
30+
31+
#### Exceptions
32+
33+
[System.ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/System.ArgumentOutOfRangeException 'System.ArgumentOutOfRangeException')
34+
Thrown when set to a value than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
35+
36+
### Remarks
37+
Set to [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero') to disable auto advance. The default value is [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').

docs/TimeProviderExtensions.ManualTimeProvider.md

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,18 @@ public int ActiveTimers { get; }
9191
#### Property Value
9292
[System.Int32](https://docs.microsoft.com/en-us/dotnet/api/System.Int32 'System.Int32')
9393
94-
<a name='TimeProviderExtensions.ManualTimeProvider.AutoAdvanceAmount'></a>
94+
<a name='TimeProviderExtensions.ManualTimeProvider.AutoAdvanceBehavior'></a>
9595

96-
## ManualTimeProvider.AutoAdvanceAmount Property
96+
## ManualTimeProvider.AutoAdvanceBehavior Property
9797

98-
Gets or sets the amount of time by which time advances whenever the clock is read via [GetUtcNow()](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.GetUtcNow() 'TimeProviderExtensions.ManualTimeProvider.GetUtcNow()').
98+
Gets or sets the auto advance behavior of this [ManualTimeProvider](TimeProviderExtensions.ManualTimeProvider.md 'TimeProviderExtensions.ManualTimeProvider').
9999

100100
```csharp
101-
public System.TimeSpan AutoAdvanceAmount { get; set; }
101+
public TimeProviderExtensions.AutoAdvanceBehavior AutoAdvanceBehavior { get; set; }
102102
```
103103

104104
#### Property Value
105-
[System.TimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan 'System.TimeSpan')
106-
107-
#### Exceptions
108-
109-
[System.ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/System.ArgumentOutOfRangeException 'System.ArgumentOutOfRangeException')
110-
Thrown when set to a value than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
111-
112-
### Remarks
113-
Set to [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero') to disable auto advance. The default value is [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
105+
[AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior')
114106

115107
<a name='TimeProviderExtensions.ManualTimeProvider.LocalTimeZone'></a>
116108

@@ -350,8 +342,8 @@ public override System.DateTimeOffset GetUtcNow();
350342
[System.DateTimeOffset](https://docs.microsoft.com/en-us/dotnet/api/System.DateTimeOffset 'System.DateTimeOffset')
351343
352344
### Remarks
353-
If [AutoAdvanceAmount](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.AutoAdvanceAmount 'TimeProviderExtensions.ManualTimeProvider.AutoAdvanceAmount') is greater than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero'), calling this
354-
method will move time forward by the amount specified by [AutoAdvanceAmount](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.AutoAdvanceAmount 'TimeProviderExtensions.ManualTimeProvider.AutoAdvanceAmount').
345+
If [AutoAdvanceAmount](https://docs.microsoft.com/en-us/dotnet/api/AutoAdvanceAmount 'AutoAdvanceAmount') is greater than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero'), calling this
346+
method will move time forward by the amount specified by [AutoAdvanceAmount](https://docs.microsoft.com/en-us/dotnet/api/AutoAdvanceAmount 'AutoAdvanceAmount').
355347
The [System.DateTimeOffset](https://docs.microsoft.com/en-us/dotnet/api/System.DateTimeOffset 'System.DateTimeOffset') returned from this method will reflect the time before
356348
the auto advance was applied, if any.
357349

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818

1919
| Classes | |
2020
| :--- | :--- |
21+
| [AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior') | The [AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior') type provides a way to enable and customize the automatic advance of time. |
2122
| [ManualTimeProvider](TimeProviderExtensions.ManualTimeProvider.md 'TimeProviderExtensions.ManualTimeProvider') | Represents a synthetic time provider that can be used to enable deterministic behavior in tests. |
2223
| [ManualTimer](TimeProviderExtensions.ManualTimer.md 'TimeProviderExtensions.ManualTimer') | A implementaiton of a [System.Threading.ITimer](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.ITimer 'System.Threading.ITimer') whose callbacks are scheduled via a [ManualTimeProvider](TimeProviderExtensions.ManualTimeProvider.md 'TimeProviderExtensions.ManualTimeProvider'). |
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace TimeProviderExtensions;
4+
5+
/// <summary>
6+
/// The <see cref="AutoAdvanceBehavior"/> type provides a way to enable and customize the automatic advance of time.
7+
/// </summary>
8+
public sealed record class AutoAdvanceBehavior
9+
{
10+
private TimeSpan clockAdvanceAmount = TimeSpan.Zero;
11+
12+
/// <summary>
13+
/// Gets or sets the amount of time by which time advances whenever the clock is read via <see cref="TimeProvider.GetUtcNow"/> or <see cref="TimeProvider.GetLocalNow"/>.
14+
/// </summary>
15+
/// <remarks>
16+
/// Set to <see cref="TimeSpan.Zero"/> to disable auto advance. The default value is <see cref="TimeSpan.Zero"/>.
17+
/// </remarks>
18+
/// <exception cref="ArgumentOutOfRangeException">Thrown when set to a value than <see cref="TimeSpan.Zero"/>.</exception>
19+
public TimeSpan ClockAdvanceAmount { get => clockAdvanceAmount; set { ThrowIfLessThanZero(value); clockAdvanceAmount = value; } }
20+
21+
private static void ThrowIfLessThanZero(TimeSpan value, [CallerMemberName] string? parameterName = null)
22+
{
23+
if (value < TimeSpan.Zero)
24+
{
25+
throw new ArgumentOutOfRangeException(parameterName, "Auto advance amounts cannot be less than zero.");
26+
}
27+
}
28+
}

src/TimeProviderExtensions/ManualTimeProvider.cs

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace TimeProviderExtensions;
99
/// <remarks>
1010
/// Learn more at <see href="https://github.com/egil/TimeProviderExtensions"/>.
1111
/// </remarks>
12-
[DebuggerDisplay("UtcNow: {ToString(),nq}. Active timers: {ActiveTimers}. Auto advance amount: {AutoAdvanceAmount,nq}.")]
12+
[DebuggerDisplay("UtcNow: {ToString(),nq}. Active timers: {ActiveTimers}. {AutoAdvanceBehavior,nq}.")]
1313
public class ManualTimeProvider : TimeProvider
1414
{
1515
internal const uint MaxSupportedTimeout = 0xfffffffe;
@@ -19,7 +19,7 @@ public class ManualTimeProvider : TimeProvider
1919
private readonly List<ManualTimerScheduler> callbacks = new();
2020
private DateTimeOffset utcNow;
2121
private TimeZoneInfo localTimeZone;
22-
private TimeSpan autoAdvanceAmount = TimeSpan.Zero;
22+
private AutoAdvanceBehavior autoAdvanceBehavior = new AutoAdvanceBehavior();
2323

2424
/// <summary>
2525
/// Gets the number of active <see cref="ManualTimer"/>, that have callbacks that are scheduled to be triggered at some point in the future.
@@ -32,25 +32,9 @@ public class ManualTimeProvider : TimeProvider
3232
public DateTimeOffset Start { get; init; }
3333

3434
/// <summary>
35-
/// Gets or sets the amount of time by which time advances whenever the clock is read via <see cref="GetUtcNow"/>.
35+
/// Gets or sets the auto advance behavior of this <see cref="ManualTimeProvider"/>.
3636
/// </summary>
37-
/// <remarks>
38-
/// Set to <see cref="TimeSpan.Zero"/> to disable auto advance. The default value is <see cref="TimeSpan.Zero"/>.
39-
/// </remarks>
40-
/// <exception cref="ArgumentOutOfRangeException">Thrown when set to a value than <see cref="TimeSpan.Zero"/>.</exception>
41-
public TimeSpan AutoAdvanceAmount
42-
{
43-
get => autoAdvanceAmount;
44-
set
45-
{
46-
if (value < TimeSpan.Zero)
47-
{
48-
throw new ArgumentOutOfRangeException(nameof(AutoAdvanceAmount), "Auto advance amount cannot be less than zero. ");
49-
}
50-
51-
autoAdvanceAmount = value;
52-
}
53-
}
37+
public AutoAdvanceBehavior AutoAdvanceBehavior { get => autoAdvanceBehavior; set => autoAdvanceBehavior = value ?? new AutoAdvanceBehavior(); }
5438

5539
/// <summary>
5640
/// Gets the amount by which the value from <see cref="GetTimestamp"/> increments per second.
@@ -120,8 +104,8 @@ public ManualTimeProvider(DateTimeOffset startDateTime, TimeZoneInfo localTimeZo
120104
/// all according to this <see cref="ManualTimeProvider"/>'s notion of time.
121105
/// </summary>
122106
/// <remarks>
123-
/// If <see cref="AutoAdvanceAmount"/> is greater than <see cref="TimeSpan.Zero"/>, calling this
124-
/// method will move time forward by the amount specified by <see cref="AutoAdvanceAmount"/>.
107+
/// If <see cref="AutoAdvanceBehavior.ClockAdvanceAmount"/> is greater than <see cref="TimeSpan.Zero"/>, calling this
108+
/// method will move time forward by the amount specified by <see cref="AutoAdvanceBehavior.ClockAdvanceAmount"/>.
125109
/// The <see cref="DateTimeOffset"/> returned from this method will reflect the time before
126110
/// the auto advance was applied, if any.
127111
/// </remarks>
@@ -132,7 +116,7 @@ public override DateTimeOffset GetUtcNow()
132116
lock (callbacks)
133117
{
134118
result = utcNow;
135-
Advance(AutoAdvanceAmount);
119+
Advance(AutoAdvanceBehavior.ClockAdvanceAmount);
136120
}
137121

138122
return result;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace TimeProviderExtensions;
2+
3+
public class AutoAdvanceBehaviorTests
4+
{
5+
[Fact]
6+
public void ClockAdvanceAmount_throws_when_lt_zero()
7+
{
8+
var sut = new AutoAdvanceBehavior();
9+
10+
var throws = () => sut.ClockAdvanceAmount = TimeSpan.FromTicks(-1);
11+
12+
throws.Should().Throw<ArgumentOutOfRangeException>()
13+
.And.ParamName.Should().Be(nameof(AutoAdvanceBehavior.ClockAdvanceAmount));
14+
}
15+
}

test/TimeProviderExtensions.Tests/ManualTimeProviderTests.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ async Task AsyncCallbacks(PeriodicTimer periodicTimer)
150150
public void Timer_callback_GetUtcNow_AutoAdvance()
151151
{
152152
var oneSecond = TimeSpan.FromSeconds(1);
153-
var timeProvider = new ManualTimeProvider() { AutoAdvanceAmount = oneSecond };
153+
var timeProvider = new ManualTimeProvider() { AutoAdvanceBehavior = { ClockAdvanceAmount = oneSecond } };
154154

155155
using var t1 = timeProvider.CreateTimer(_ =>
156156
{
@@ -180,16 +180,6 @@ public void Jump_zero()
180180
sut.GetUtcNow().Should().Be(sut.Start);
181181
}
182182

183-
[Fact]
184-
public void AutoAdvanceAmount_throws_when_lt_zero()
185-
{
186-
var sut = new ManualTimeProvider();
187-
188-
var throws = () => sut.AutoAdvanceAmount = TimeSpan.FromTicks(-1);
189-
190-
throws.Should().Throw<ArgumentOutOfRangeException>();
191-
}
192-
193183
[Fact]
194184
public void Jump_throws_when_lt_zero()
195185
{

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Microsoft.Extensions.Time.Testing.Test;
99

10+
using TimeProviderExtensions;
1011
using FakeTimeProvider = TimeProviderExtensions.ManualTimeProvider;
1112

1213
public class ManualTimeProviderTests
@@ -29,7 +30,7 @@ public void DefaultCtor()
2930
Assert.Equal(0, now.Millisecond);
3031
Assert.Equal(TimeSpan.Zero, now.Offset);
3132
Assert.Equal(10_000_000, frequency);
32-
Assert.Equal(TimeSpan.Zero, timeProvider.AutoAdvanceAmount);
33+
Assert.Equal(new AutoAdvanceBehavior(), timeProvider.AutoAdvanceBehavior);
3334

3435
var timestamp2 = timeProvider.GetTimestamp();
3536
var frequency2 = timeProvider.TimestampFrequency;
@@ -59,7 +60,7 @@ public void RichCtor()
5960
Assert.Equal(TimeSpan.Zero, now.Offset);
6061
Assert.Equal(8, now.Millisecond);
6162
Assert.Equal(10_000_000, frequency);
62-
Assert.Equal(TimeSpan.Zero, timeProvider.AutoAdvanceAmount);
63+
Assert.Equal(new AutoAdvanceBehavior(), timeProvider.AutoAdvanceBehavior);
6364

6465
timeProvider.Advance(TimeSpan.FromMilliseconds(8));
6566
var pnow2 = timeProvider.GetTimestamp();
@@ -305,10 +306,7 @@ public async Task WaitAsync_Cancel()
305306
[Fact]
306307
public void AutoAdvance()
307308
{
308-
var timeProvider = new FakeTimeProvider(DateTimeOffset.UtcNow)
309-
{
310-
AutoAdvanceAmount = TimeSpan.FromSeconds(1)
311-
};
309+
var timeProvider = new FakeTimeProvider { AutoAdvanceBehavior = { ClockAdvanceAmount = TimeSpan.FromSeconds(1) } };
312310

313311
var first = timeProvider.GetUtcNow();
314312
var second = timeProvider.GetUtcNow();
@@ -332,14 +330,11 @@ public void ToString_AutoAdvance_off()
332330
[Fact]
333331
public void ToString_AutoAdvance_on()
334332
{
335-
var timeProvider = new FakeTimeProvider
336-
{
337-
AutoAdvanceAmount = TimeSpan.FromSeconds(1)
338-
};
333+
var timeProvider = new FakeTimeProvider { AutoAdvanceBehavior = { ClockAdvanceAmount = TimeSpan.FromSeconds(1) } };
339334

340335
_ = timeProvider.ToString();
341336

342-
timeProvider.AutoAdvanceAmount = TimeSpan.Zero;
337+
timeProvider.AutoAdvanceBehavior.ClockAdvanceAmount = TimeSpan.Zero;
343338
Assert.Equal(timeProvider.Start, timeProvider.GetUtcNow());
344339
}
345340
}

0 commit comments

Comments
 (0)