Skip to content

Commit

Permalink
Replace ISystemClock with TimeProvider in OutputCaching, ResponseCach…
Browse files Browse the repository at this point in the history
…ing (#47753)
  • Loading branch information
Tratcher committed Apr 19, 2023
1 parent 8ea2347 commit b362c45
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 149 deletions.
15 changes: 0 additions & 15 deletions src/Middleware/OutputCaching/src/ISystemClock.cs

This file was deleted.

4 changes: 2 additions & 2 deletions src/Middleware/OutputCaching/src/OutputCacheMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ internal async Task<bool> TryServeCachedResponseAsync(OutputCacheContext context
}

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

Expand Down Expand Up @@ -464,7 +464,7 @@ private bool OnStartResponse(OutputCacheContext context)
if (!context.ResponseStarted)
{
context.ResponseStarted = true;
context.ResponseTime = _options.SystemClock.UtcNow;
context.ResponseTime = _options.TimeProvider.GetUtcNow();

return true;
}
Expand Down
5 changes: 1 addition & 4 deletions src/Middleware/OutputCaching/src/OutputCacheOptions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;

namespace Microsoft.AspNetCore.OutputCaching;

/// <summary>
Expand Down Expand Up @@ -45,8 +43,7 @@ public class OutputCacheOptions
/// <summary>
/// For testing purposes only.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal ISystemClock SystemClock { get; set; } = new SystemClock();
internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;

/// <summary>
/// Defines a <see cref="IOutputCachePolicy"/> which can be referenced by name.
Expand Down
15 changes: 0 additions & 15 deletions src/Middleware/OutputCaching/src/SystemClock.cs

This file was deleted.

55 changes: 20 additions & 35 deletions src/Middleware/OutputCaching/test/OutputCacheMiddlewareTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -334,44 +334,38 @@ public void ContentIsNotModified_IfNoneMatch_MatchesAtLeastOneValue_True()
[Fact]
public void StartResponseAsync_IfAllowResponseCaptureIsTrue_SetsResponseTime()
{
var clock = new TestClock
{
UtcNow = DateTimeOffset.UtcNow
};
var timeProvider = new TestTimeProvider();
var middleware = TestUtils.CreateTestMiddleware(options: new OutputCacheOptions
{
SystemClock = clock
TimeProvider = timeProvider
});
var context = TestUtils.CreateTestContext();
context.ResponseTime = null;

middleware.StartResponse(context);

Assert.Equal(clock.UtcNow, context.ResponseTime);
Assert.Equal(timeProvider.GetUtcNow(), context.ResponseTime);
}

[Fact]
public void StartResponseAsync_IfAllowResponseCaptureIsTrue_SetsResponseTimeOnlyOnce()
{
var clock = new TestClock
{
UtcNow = DateTimeOffset.UtcNow
};
var timeProvider = new TestTimeProvider();
var middleware = TestUtils.CreateTestMiddleware(options: new OutputCacheOptions
{
SystemClock = clock
TimeProvider = timeProvider
});
var context = TestUtils.CreateTestContext();
var initialTime = clock.UtcNow;
var initialTime = timeProvider.GetUtcNow();
context.ResponseTime = null;

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

clock.UtcNow += TimeSpan.FromSeconds(10);
timeProvider.Advance(TimeSpan.FromSeconds(10));

middleware.StartResponse(context);
Assert.NotEqual(clock.UtcNow, context.ResponseTime);
Assert.NotEqual(timeProvider.GetUtcNow(), context.ResponseTime);
Assert.Equal(initialTime, context.ResponseTime);
}

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

var clock = new TestClock
{
UtcNow = DateTimeOffset.MinValue
};
var timeProvider = new TestTimeProvider(DateTimeOffset.MinValue);
var options = new OutputCacheOptions
{
SystemClock = clock
TimeProvider = timeProvider
};
var sink = new TestSink();
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
var context = TestUtils.CreateTestContext();

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

middleware.FinalizeCacheHeaders(context);

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

var clock = new TestClock
{
UtcNow = DateTimeOffset.UtcNow
};
var timeProvider = new TestTimeProvider();
var sink = new TestSink();
var options = new OutputCacheOptions
{
SystemClock = clock
TimeProvider = timeProvider
};
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
var context = TestUtils.CreateTestContext();

context.ResponseTime = clock.UtcNow;
context.ResponseTime = timeProvider.GetUtcNow();
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(12)
}.ToString();

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

middleware.FinalizeCacheHeaders(context);

Expand All @@ -448,25 +436,22 @@ public void FinalizeCacheHeadersAsync_ResponseValidity_UseMaxAgeIfAvailable()
[Fact]
public void FinalizeCacheHeadersAsync_ResponseValidity_UseSharedMaxAgeIfAvailable()
{
var clock = new TestClock
{
UtcNow = DateTimeOffset.UtcNow
};
var timeProvider = new TestTimeProvider();
var sink = new TestSink();
var options = new OutputCacheOptions
{
SystemClock = clock
TimeProvider = timeProvider
};
var middleware = TestUtils.CreateTestMiddleware(testSink: sink, options: options);
var context = TestUtils.CreateTestContext();

context.ResponseTime = clock.UtcNow;
context.ResponseTime = timeProvider.GetUtcNow();
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(12),
SharedMaxAge = TimeSpan.FromSeconds(13)
}.ToString();
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(clock.UtcNow + TimeSpan.FromSeconds(11));
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(timeProvider.GetUtcNow() + TimeSpan.FromSeconds(11));

middleware.FinalizeCacheHeaders(context);

Expand Down
20 changes: 17 additions & 3 deletions src/Middleware/OutputCaching/test/TestUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ internal static IOutputCacheKeyProvider CreateTestKeyProvider(OutputCacheOptions
{
outputCachingOptions.MaximumBodySize = options.MaximumBodySize;
outputCachingOptions.UseCaseSensitivePaths = options.UseCaseSensitivePaths;
outputCachingOptions.SystemClock = options.SystemClock;
outputCachingOptions.TimeProvider = options.TimeProvider;
outputCachingOptions.BasePolicies = options.BasePolicies;
outputCachingOptions.DefaultExpirationTimeSpan = options.DefaultExpirationTimeSpan;
outputCachingOptions.SizeLimit = options.SizeLimit;
Expand Down Expand Up @@ -347,9 +347,23 @@ public ValueTask SetAsync(string key, byte[] entry, string[]? tags, TimeSpan val
}
}

internal class TestClock : ISystemClock
internal class TestTimeProvider : TimeProvider
{
public DateTimeOffset UtcNow { get; set; }
private DateTimeOffset _current;

public TestTimeProvider() : this(DateTimeOffset.UtcNow) { }

public TestTimeProvider(DateTimeOffset current)
{
_current = current;
}

public override DateTimeOffset GetUtcNow() => _current;

public void Advance(TimeSpan timeSpan)
{
_current += timeSpan;
}
}

internal class AllowTestPolicy : IOutputCachePolicy
Expand Down
15 changes: 0 additions & 15 deletions src/Middleware/ResponseCaching/src/Interfaces/ISystemClock.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ internal async Task<bool> TryServeCachedResponseAsync(ResponseCachingContext con

context.CachedResponse = cachedResponse;
context.CachedResponseHeaders = cachedResponse.Headers;
context.ResponseTime = _options.SystemClock.UtcNow;
context.ResponseTime = _options.TimeProvider.GetUtcNow();
var cachedEntryAge = context.ResponseTime.Value - context.CachedResponse.Created;
context.CachedEntryAge = cachedEntryAge > TimeSpan.Zero ? cachedEntryAge : TimeSpan.Zero;

Expand Down Expand Up @@ -374,7 +374,7 @@ private bool OnStartResponse(ResponseCachingContext context)
if (!context.ResponseStarted)
{
context.ResponseStarted = true;
context.ResponseTime = _options.SystemClock.UtcNow;
context.ResponseTime = _options.TimeProvider.GetUtcNow();

return true;
}
Expand Down
5 changes: 1 addition & 4 deletions src/Middleware/ResponseCaching/src/ResponseCachingOptions.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;

namespace Microsoft.AspNetCore.ResponseCaching;

/// <summary>
Expand Down Expand Up @@ -31,6 +29,5 @@ public class ResponseCachingOptions
/// <summary>
/// For testing purposes only.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
internal ISystemClock SystemClock { get; set; } = new SystemClock();
internal TimeProvider TimeProvider { get; set; } = TimeProvider.System;
}
15 changes: 0 additions & 15 deletions src/Middleware/ResponseCaching/src/SystemClock.cs

This file was deleted.

Loading

0 comments on commit b362c45

Please sign in to comment.