Skip to content

Commit b362c45

Browse files
authored
Replace ISystemClock with TimeProvider in OutputCaching, ResponseCaching (#47753)
1 parent 8ea2347 commit b362c45

File tree

12 files changed

+81
-149
lines changed

12 files changed

+81
-149
lines changed

src/Middleware/OutputCaching/src/ISystemClock.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/Middleware/OutputCaching/src/OutputCacheMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ internal async Task<bool> TryServeCachedResponseAsync(OutputCacheContext context
243243
}
244244

245245
context.CachedResponse = cacheEntry;
246-
context.ResponseTime = _options.SystemClock.UtcNow;
246+
context.ResponseTime = _options.TimeProvider.GetUtcNow();
247247
var cacheEntryAge = context.ResponseTime.Value - context.CachedResponse.Created;
248248
context.CachedEntryAge = cacheEntryAge > TimeSpan.Zero ? cacheEntryAge : TimeSpan.Zero;
249249

@@ -464,7 +464,7 @@ private bool OnStartResponse(OutputCacheContext context)
464464
if (!context.ResponseStarted)
465465
{
466466
context.ResponseStarted = true;
467-
context.ResponseTime = _options.SystemClock.UtcNow;
467+
context.ResponseTime = _options.TimeProvider.GetUtcNow();
468468

469469
return true;
470470
}

src/Middleware/OutputCaching/src/OutputCacheOptions.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.ComponentModel;
5-
64
namespace Microsoft.AspNetCore.OutputCaching;
75

86
/// <summary>
@@ -45,8 +43,7 @@ public class OutputCacheOptions
4543
/// <summary>
4644
/// For testing purposes only.
4745
/// </summary>
48-
[EditorBrowsable(EditorBrowsableState.Never)]
49-
internal ISystemClock SystemClock { get; set; } = new SystemClock();
46+
internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;
5047

5148
/// <summary>
5249
/// Defines a <see cref="IOutputCachePolicy"/> which can be referenced by name.

src/Middleware/OutputCaching/src/SystemClock.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/Middleware/OutputCaching/test/OutputCacheMiddlewareTests.cs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -334,44 +334,38 @@ public void ContentIsNotModified_IfNoneMatch_MatchesAtLeastOneValue_True()
334334
[Fact]
335335
public void StartResponseAsync_IfAllowResponseCaptureIsTrue_SetsResponseTime()
336336
{
337-
var clock = new TestClock
338-
{
339-
UtcNow = DateTimeOffset.UtcNow
340-
};
337+
var timeProvider = new TestTimeProvider();
341338
var middleware = TestUtils.CreateTestMiddleware(options: new OutputCacheOptions
342339
{
343-
SystemClock = clock
340+
TimeProvider = timeProvider
344341
});
345342
var context = TestUtils.CreateTestContext();
346343
context.ResponseTime = null;
347344

348345
middleware.StartResponse(context);
349346

350-
Assert.Equal(clock.UtcNow, context.ResponseTime);
347+
Assert.Equal(timeProvider.GetUtcNow(), context.ResponseTime);
351348
}
352349

353350
[Fact]
354351
public void StartResponseAsync_IfAllowResponseCaptureIsTrue_SetsResponseTimeOnlyOnce()
355352
{
356-
var clock = new TestClock
357-
{
358-
UtcNow = DateTimeOffset.UtcNow
359-
};
353+
var timeProvider = new TestTimeProvider();
360354
var middleware = TestUtils.CreateTestMiddleware(options: new OutputCacheOptions
361355
{
362-
SystemClock = clock
356+
TimeProvider = timeProvider
363357
});
364358
var context = TestUtils.CreateTestContext();
365-
var initialTime = clock.UtcNow;
359+
var initialTime = timeProvider.GetUtcNow();
366360
context.ResponseTime = null;
367361

368362
middleware.StartResponse(context);
369363
Assert.Equal(initialTime, context.ResponseTime);
370364

371-
clock.UtcNow += TimeSpan.FromSeconds(10);
365+
timeProvider.Advance(TimeSpan.FromSeconds(10));
372366

373367
middleware.StartResponse(context);
374-
Assert.NotEqual(clock.UtcNow, context.ResponseTime);
368+
Assert.NotEqual(timeProvider.GetUtcNow(), context.ResponseTime);
375369
Assert.Equal(initialTime, context.ResponseTime);
376370
}
377371

@@ -393,20 +387,17 @@ public void FinalizeCacheHeadersAsync_ResponseValidity_IgnoresExpiryIfAvailable(
393387
{
394388
// The Expires header should not be used when set in the response
395389

396-
var clock = new TestClock
397-
{
398-
UtcNow = DateTimeOffset.MinValue
399-
};
390+
var timeProvider = new TestTimeProvider(DateTimeOffset.MinValue);
400391
var options = new OutputCacheOptions
401392
{
402-
SystemClock = clock
393+
TimeProvider = timeProvider
403394
};
404395
var sink = new TestSink();
405396
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
406397
var context = TestUtils.CreateTestContext();
407398

408-
context.ResponseTime = clock.UtcNow;
409-
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(clock.UtcNow + TimeSpan.FromSeconds(11));
399+
context.ResponseTime = timeProvider.GetUtcNow();
400+
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(timeProvider.GetUtcNow() + TimeSpan.FromSeconds(11));
410401

411402
middleware.FinalizeCacheHeaders(context);
412403

@@ -419,25 +410,22 @@ public void FinalizeCacheHeadersAsync_ResponseValidity_UseMaxAgeIfAvailable()
419410
{
420411
// The MaxAge header should not be used if set in the response
421412

422-
var clock = new TestClock
423-
{
424-
UtcNow = DateTimeOffset.UtcNow
425-
};
413+
var timeProvider = new TestTimeProvider();
426414
var sink = new TestSink();
427415
var options = new OutputCacheOptions
428416
{
429-
SystemClock = clock
417+
TimeProvider = timeProvider
430418
};
431419
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
432420
var context = TestUtils.CreateTestContext();
433421

434-
context.ResponseTime = clock.UtcNow;
422+
context.ResponseTime = timeProvider.GetUtcNow();
435423
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
436424
{
437425
MaxAge = TimeSpan.FromSeconds(12)
438426
}.ToString();
439427

440-
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(clock.UtcNow + TimeSpan.FromSeconds(11));
428+
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(timeProvider.GetUtcNow() + TimeSpan.FromSeconds(11));
441429

442430
middleware.FinalizeCacheHeaders(context);
443431

@@ -448,25 +436,22 @@ public void FinalizeCacheHeadersAsync_ResponseValidity_UseMaxAgeIfAvailable()
448436
[Fact]
449437
public void FinalizeCacheHeadersAsync_ResponseValidity_UseSharedMaxAgeIfAvailable()
450438
{
451-
var clock = new TestClock
452-
{
453-
UtcNow = DateTimeOffset.UtcNow
454-
};
439+
var timeProvider = new TestTimeProvider();
455440
var sink = new TestSink();
456441
var options = new OutputCacheOptions
457442
{
458-
SystemClock = clock
443+
TimeProvider = timeProvider
459444
};
460445
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
461446
var context = TestUtils.CreateTestContext();
462447

463-
context.ResponseTime = clock.UtcNow;
448+
context.ResponseTime = timeProvider.GetUtcNow();
464449
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
465450
{
466451
MaxAge = TimeSpan.FromSeconds(12),
467452
SharedMaxAge = TimeSpan.FromSeconds(13)
468453
}.ToString();
469-
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(clock.UtcNow + TimeSpan.FromSeconds(11));
454+
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(timeProvider.GetUtcNow() + TimeSpan.FromSeconds(11));
470455

471456
middleware.FinalizeCacheHeaders(context);
472457

src/Middleware/OutputCaching/test/TestUtils.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private static IEnumerable<IHostBuilder> CreateBuildersWithOutputCaching(
146146
{
147147
outputCachingOptions.MaximumBodySize = options.MaximumBodySize;
148148
outputCachingOptions.UseCaseSensitivePaths = options.UseCaseSensitivePaths;
149-
outputCachingOptions.SystemClock = options.SystemClock;
149+
outputCachingOptions.TimeProvider = options.TimeProvider;
150150
outputCachingOptions.BasePolicies = options.BasePolicies;
151151
outputCachingOptions.DefaultExpirationTimeSpan = options.DefaultExpirationTimeSpan;
152152
outputCachingOptions.SizeLimit = options.SizeLimit;
@@ -347,9 +347,23 @@ public ValueTask SetAsync(string key, byte[] entry, string[]? tags, TimeSpan val
347347
}
348348
}
349349

350-
internal class TestClock : ISystemClock
350+
internal class TestTimeProvider : TimeProvider
351351
{
352-
public DateTimeOffset UtcNow { get; set; }
352+
private DateTimeOffset _current;
353+
354+
public TestTimeProvider() : this(DateTimeOffset.UtcNow) { }
355+
356+
public TestTimeProvider(DateTimeOffset current)
357+
{
358+
_current = current;
359+
}
360+
361+
public override DateTimeOffset GetUtcNow() => _current;
362+
363+
public void Advance(TimeSpan timeSpan)
364+
{
365+
_current += timeSpan;
366+
}
353367
}
354368

355369
internal class AllowTestPolicy : IOutputCachePolicy

src/Middleware/ResponseCaching/src/Interfaces/ISystemClock.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/Middleware/ResponseCaching/src/ResponseCachingMiddleware.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ internal async Task<bool> TryServeCachedResponseAsync(ResponseCachingContext con
142142

143143
context.CachedResponse = cachedResponse;
144144
context.CachedResponseHeaders = cachedResponse.Headers;
145-
context.ResponseTime = _options.SystemClock.UtcNow;
145+
context.ResponseTime = _options.TimeProvider.GetUtcNow();
146146
var cachedEntryAge = context.ResponseTime.Value - context.CachedResponse.Created;
147147
context.CachedEntryAge = cachedEntryAge > TimeSpan.Zero ? cachedEntryAge : TimeSpan.Zero;
148148

@@ -374,7 +374,7 @@ private bool OnStartResponse(ResponseCachingContext context)
374374
if (!context.ResponseStarted)
375375
{
376376
context.ResponseStarted = true;
377-
context.ResponseTime = _options.SystemClock.UtcNow;
377+
context.ResponseTime = _options.TimeProvider.GetUtcNow();
378378

379379
return true;
380380
}

src/Middleware/ResponseCaching/src/ResponseCachingOptions.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System.ComponentModel;
5-
64
namespace Microsoft.AspNetCore.ResponseCaching;
75

86
/// <summary>
@@ -31,6 +29,5 @@ public class ResponseCachingOptions
3129
/// <summary>
3230
/// For testing purposes only.
3331
/// </summary>
34-
[EditorBrowsable(EditorBrowsableState.Never)]
35-
internal ISystemClock SystemClock { get; set; } = new SystemClock();
32+
internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;
3633
}

src/Middleware/ResponseCaching/src/SystemClock.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)