|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.ResponseCaching.Tests;
public class ResponseCachingPolicyProviderTests
{
public static TheoryData<string> CacheableMethods
{
get
{
return new TheoryData<string>
{
HttpMethods.Get,
HttpMethods.Head
};
}
}
[Theory]
[MemberData(nameof(CacheableMethods))]
public void AttemptResponseCaching_CacheableMethods_Allowed(string method)
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = method;
Assert.True(new ResponseCachingPolicyProvider().AttemptResponseCaching(context));
Assert.Empty(sink.Writes);
}
public static TheoryData<string> NonCacheableMethods
{
get
{
return new TheoryData<string>
{
HttpMethods.Post,
HttpMethods.Put,
HttpMethods.Delete,
HttpMethods.Trace,
HttpMethods.Connect,
HttpMethods.Options,
"",
null
};
}
}
[Theory]
[MemberData(nameof(NonCacheableMethods))]
public void AttemptResponseCaching_UncacheableMethods_NotAllowed(string method)
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = method;
Assert.False(new ResponseCachingPolicyProvider().AttemptResponseCaching(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestMethodNotCacheable);
}
[Fact]
public void AttemptResponseCaching_AuthorizationHeaders_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.Authorization = "Placeholder";
Assert.False(new ResponseCachingPolicyProvider().AttemptResponseCaching(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithAuthorizationNotCacheable);
}
[Fact]
public void AllowCacheStorage_NoStore_Allowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
NoStore = true
}.ToString();
Assert.True(new ResponseCachingPolicyProvider().AllowCacheLookup(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void AllowCacheLookup_NoCache_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
NoCache = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().AllowCacheLookup(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithNoCacheNotCacheable);
}
[Fact]
public void AllowCacheLookup_LegacyDirectives_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.Pragma = "no-cache";
Assert.False(new ResponseCachingPolicyProvider().AllowCacheLookup(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.RequestWithPragmaNoCacheNotCacheable);
}
[Fact]
public void AllowCacheLookup_LegacyDirectives_OverridenByCacheControl()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.Pragma = "no-cache";
context.HttpContext.Request.Headers.CacheControl = "max-age=10";
Assert.True(new ResponseCachingPolicyProvider().AllowCacheLookup(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void AllowCacheStorage_NoStore_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Method = HttpMethods.Get;
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
NoStore = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().AllowCacheStorage(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsResponseCacheable_NoPublic_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithoutPublicNotCacheable);
}
[Fact]
public void IsResponseCacheable_Public_Allowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsResponseCacheable_NoCache_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
NoCache = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithNoCacheNotCacheable);
}
[Fact]
public void IsResponseCacheable_ResponseNoStore_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
NoStore = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithNoStoreNotCacheable);
}
[Fact]
public void IsResponseCacheable_SetCookieHeader_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
context.HttpContext.Response.Headers.SetCookie = "cookieName=cookieValue";
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithSetCookieNotCacheable);
}
[Fact]
public void IsResponseCacheable_VaryHeaderByStar_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
context.HttpContext.Response.Headers.Vary = "*";
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithVaryStarNotCacheable);
}
[Fact]
public void IsResponseCacheable_Private_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
Private = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithPrivateNotCacheable);
}
[Theory]
[InlineData(StatusCodes.Status200OK)]
public void IsResponseCacheable_SuccessStatusCodes_Allowed(int statusCode)
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = statusCode;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
[Theory]
[InlineData(StatusCodes.Status100Continue)]
[InlineData(StatusCodes.Status101SwitchingProtocols)]
[InlineData(StatusCodes.Status102Processing)]
[InlineData(StatusCodes.Status201Created)]
[InlineData(StatusCodes.Status202Accepted)]
[InlineData(StatusCodes.Status203NonAuthoritative)]
[InlineData(StatusCodes.Status204NoContent)]
[InlineData(StatusCodes.Status205ResetContent)]
[InlineData(StatusCodes.Status206PartialContent)]
[InlineData(StatusCodes.Status207MultiStatus)]
[InlineData(StatusCodes.Status208AlreadyReported)]
[InlineData(StatusCodes.Status226IMUsed)]
[InlineData(StatusCodes.Status300MultipleChoices)]
[InlineData(StatusCodes.Status301MovedPermanently)]
[InlineData(StatusCodes.Status302Found)]
[InlineData(StatusCodes.Status303SeeOther)]
[InlineData(StatusCodes.Status304NotModified)]
[InlineData(StatusCodes.Status305UseProxy)]
[InlineData(StatusCodes.Status306SwitchProxy)]
[InlineData(StatusCodes.Status307TemporaryRedirect)]
[InlineData(StatusCodes.Status308PermanentRedirect)]
[InlineData(StatusCodes.Status400BadRequest)]
[InlineData(StatusCodes.Status401Unauthorized)]
[InlineData(StatusCodes.Status402PaymentRequired)]
[InlineData(StatusCodes.Status403Forbidden)]
[InlineData(StatusCodes.Status404NotFound)]
[InlineData(StatusCodes.Status405MethodNotAllowed)]
[InlineData(StatusCodes.Status406NotAcceptable)]
[InlineData(StatusCodes.Status407ProxyAuthenticationRequired)]
[InlineData(StatusCodes.Status408RequestTimeout)]
[InlineData(StatusCodes.Status409Conflict)]
[InlineData(StatusCodes.Status410Gone)]
[InlineData(StatusCodes.Status411LengthRequired)]
[InlineData(StatusCodes.Status412PreconditionFailed)]
[InlineData(StatusCodes.Status413RequestEntityTooLarge)]
[InlineData(StatusCodes.Status414RequestUriTooLong)]
[InlineData(StatusCodes.Status415UnsupportedMediaType)]
[InlineData(StatusCodes.Status416RequestedRangeNotSatisfiable)]
[InlineData(StatusCodes.Status417ExpectationFailed)]
[InlineData(StatusCodes.Status418ImATeapot)]
[InlineData(StatusCodes.Status419AuthenticationTimeout)]
[InlineData(StatusCodes.Status421MisdirectedRequest)]
[InlineData(StatusCodes.Status422UnprocessableEntity)]
[InlineData(StatusCodes.Status423Locked)]
[InlineData(StatusCodes.Status424FailedDependency)]
[InlineData(StatusCodes.Status426UpgradeRequired)]
[InlineData(StatusCodes.Status428PreconditionRequired)]
[InlineData(StatusCodes.Status429TooManyRequests)]
[InlineData(StatusCodes.Status431RequestHeaderFieldsTooLarge)]
[InlineData(StatusCodes.Status451UnavailableForLegalReasons)]
[InlineData(StatusCodes.Status500InternalServerError)]
[InlineData(StatusCodes.Status501NotImplemented)]
[InlineData(StatusCodes.Status502BadGateway)]
[InlineData(StatusCodes.Status503ServiceUnavailable)]
[InlineData(StatusCodes.Status504GatewayTimeout)]
[InlineData(StatusCodes.Status505HttpVersionNotsupported)]
[InlineData(StatusCodes.Status506VariantAlsoNegotiates)]
[InlineData(StatusCodes.Status507InsufficientStorage)]
[InlineData(StatusCodes.Status508LoopDetected)]
[InlineData(StatusCodes.Status510NotExtended)]
[InlineData(StatusCodes.Status511NetworkAuthenticationRequired)]
public void IsResponseCacheable_NonSuccessStatusCodes_NotAllowed(int statusCode)
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = statusCode;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ResponseWithUnsuccessfulStatusCodeNotCacheable);
}
[Fact]
public void IsResponseCacheable_NoExpiryRequirements_IsAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
var utcNow = DateTimeOffset.UtcNow;
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = DateTimeOffset.MaxValue;
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsResponseCacheable_AtExpiry_NotAllowed()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true
}.ToString();
var utcNow = DateTimeOffset.UtcNow;
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(utcNow);
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = utcNow;
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationExpiresExceeded);
}
[Fact]
public void IsResponseCacheable_MaxAgeOverridesExpiry_ToAllowed()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10)
}.ToString();
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(utcNow);
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = utcNow + TimeSpan.FromSeconds(9);
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsResponseCacheable_MaxAgeOverridesExpiry_ToNotAllowed()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10)
}.ToString();
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(utcNow);
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = utcNow + TimeSpan.FromSeconds(10);
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
}
[Fact]
public void IsResponseCacheable_SharedMaxAgeOverridesMaxAge_ToAllowed()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10),
SharedMaxAge = TimeSpan.FromSeconds(15)
}.ToString();
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = utcNow + TimeSpan.FromSeconds(11);
Assert.True(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsResponseCacheable_SharedMaxAgeOverridesMaxAge_ToNotAllowed()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
context.HttpContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10),
SharedMaxAge = TimeSpan.FromSeconds(5)
}.ToString();
context.HttpContext.Response.Headers.Date = HeaderUtilities.FormatDate(utcNow);
context.ResponseTime = utcNow + TimeSpan.FromSeconds(5);
Assert.False(new ResponseCachingPolicyProvider().IsResponseCacheable(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationSharedMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_NoCachedCacheControl_FallsbackToEmptyCacheControl()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.ResponseTime = DateTimeOffset.MaxValue;
context.CachedEntryAge = TimeSpan.MaxValue;
context.CachedResponseHeaders = new HeaderDictionary();
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsCachedEntryFresh_NoExpiryRequirements_IsFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.ResponseTime = DateTimeOffset.MaxValue;
context.CachedEntryAge = TimeSpan.MaxValue;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true
}.ToString();
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsCachedEntryFresh_AtExpiry_IsNotFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.ResponseTime = utcNow;
context.CachedEntryAge = TimeSpan.Zero;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true
}.ToString();
context.CachedResponseHeaders[HeaderNames.Expires] = HeaderUtilities.FormatDate(utcNow);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationExpiresExceeded);
}
[Fact]
public void IsCachedEntryFresh_MaxAgeOverridesExpiry_ToFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.CachedEntryAge = TimeSpan.FromSeconds(9);
context.ResponseTime = utcNow + context.CachedEntryAge;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10)
}.ToString();
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(utcNow);
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsCachedEntryFresh_MaxAgeOverridesExpiry_ToNotFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.CachedEntryAge = TimeSpan.FromSeconds(10);
context.ResponseTime = utcNow + context.CachedEntryAge;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10)
}.ToString();
context.HttpContext.Response.Headers.Expires = HeaderUtilities.FormatDate(utcNow);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_SharedMaxAgeOverridesMaxAge_ToFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.CachedEntryAge = TimeSpan.FromSeconds(11);
context.ResponseTime = utcNow + context.CachedEntryAge;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10),
SharedMaxAge = TimeSpan.FromSeconds(15)
}.ToString();
context.CachedResponseHeaders[HeaderNames.Expires] = HeaderUtilities.FormatDate(utcNow);
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
Assert.Empty(sink.Writes);
}
[Fact]
public void IsCachedEntryFresh_SharedMaxAgeOverridesMaxAge_ToNotFresh()
{
var utcNow = DateTimeOffset.UtcNow;
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.CachedEntryAge = TimeSpan.FromSeconds(5);
context.ResponseTime = utcNow + context.CachedEntryAge;
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(10),
SharedMaxAge = TimeSpan.FromSeconds(5)
}.ToString();
context.CachedResponseHeaders[HeaderNames.Expires] = HeaderUtilities.FormatDate(utcNow);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationSharedMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_MinFreshReducesFreshness_ToNotFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MinFresh = TimeSpan.FromSeconds(2)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(10),
SharedMaxAge = TimeSpan.FromSeconds(5)
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(3);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMinFreshAdded,
LoggedMessage.ExpirationSharedMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_RequestMaxAgeRestrictAge_ToNotFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(10),
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(5);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_MaxStaleOverridesFreshness_ToFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MaxStale = true, // This value must be set to true in order to specify MaxStaleLimit
MaxStaleLimit = TimeSpan.FromSeconds(2)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxStaleSatisfied);
}
[Fact]
public void IsCachedEntryFresh_MaxStaleInfiniteOverridesFreshness_ToFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MaxStale = true // No value specified means a MaxStaleLimit of infinity
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.True(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationInfiniteMaxStaleSatisfied);
}
[Fact]
public void IsCachedEntryFresh_MaxStaleOverridesFreshness_ButStillNotFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MaxStale = true, // This value must be set to true in order to specify MaxStaleLimit
MaxStaleLimit = TimeSpan.FromSeconds(1)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMaxAgeExceeded);
}
[Fact]
public void IsCachedEntryFresh_MustRevalidateOverridesRequestMaxStale_ToNotFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MaxStale = true, // This value must be set to true in order to specify MaxStaleLimit
MaxStaleLimit = TimeSpan.FromSeconds(2)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MustRevalidate = true
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMustRevalidate);
}
[Fact]
public void IsCachedEntryFresh_ProxyRevalidateOverridesRequestMaxStale_ToNotFresh()
{
var sink = new TestSink();
var context = TestUtils.CreateTestContext(sink);
context.HttpContext.Request.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MaxStale = true, // This value must be set to true in order to specify MaxStaleLimit
MaxStaleLimit = TimeSpan.FromSeconds(2)
}.ToString();
context.CachedResponseHeaders = new HeaderDictionary();
context.CachedResponseHeaders[HeaderNames.CacheControl] = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromSeconds(5),
MustRevalidate = true
}.ToString();
context.CachedEntryAge = TimeSpan.FromSeconds(6);
Assert.False(new ResponseCachingPolicyProvider().IsCachedEntryFresh(context));
TestUtils.AssertLoggedMessages(
sink.Writes,
LoggedMessage.ExpirationMustRevalidate);
}
}
|