| File: ExpirationTests.cs | Web Access |
| Project: src\test\Libraries\Microsoft.Extensions.Caching.Hybrid.Tests\Microsoft.Extensions.Caching.Hybrid.Tests.csproj (Microsoft.Extensions.Caching.Hybrid.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Internal; using Xunit.Abstractions; using static Microsoft.Extensions.Caching.Hybrid.Tests.DistributedCacheTests; using static Microsoft.Extensions.Caching.Hybrid.Tests.L2Tests; namespace Microsoft.Extensions.Caching.Hybrid.Tests; public class ExpirationTests(ITestOutputHelper log) { [Fact] public async Task ExpirationRespected() { // we want set up separate cache instances with a shared L2 to show relative expiration // being respected var clock = new FakeTime(); using var l1 = new MemoryCache(new MemoryCacheOptions { Clock = clock }); var l2 = new LoggingCache(log, new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions { Clock = clock }))); Guid guid0; string key = nameof(ExpirationRespected); Func<CancellationToken, ValueTask<Guid>> callback = static _ => new(Guid.NewGuid()); HybridCacheEntryOptions options = new() { Expiration = TimeSpan.FromMinutes(2), LocalCacheExpiration = TimeSpan.FromMinutes(1) }; ServiceCollection services = new(); services.AddSingleton<ISystemClock>(clock); services.AddSingleton<TimeProvider>(clock); services.AddSingleton<IMemoryCache>(l1); services.AddSingleton<IDistributedCache>(l2); services.AddHybridCache(); using var provider = services.BuildServiceProvider(); var cache = provider.GetRequiredService<HybridCache>(); guid0 = await cache.GetOrCreateAsync(key, callback, options); // should be fine immediately Assert.Equal(guid0, await cache.GetOrCreateAsync(key, callback, options)); clock.Add(TimeSpan.FromSeconds(45)); // should still be fine from L1 (L1 has 1 minute expiration) Assert.Equal(guid0, await cache.GetOrCreateAsync(key, callback, options)); clock.Add(TimeSpan.FromSeconds(45)); // should still be fine from L2 (L1 now expired, but fetches from L2 and detects 0:30 remaining, which limits L1 to 0:30) Assert.Equal(guid0, await cache.GetOrCreateAsync(key, callback, options)); clock.Add(TimeSpan.FromSeconds(45)); // should now be expired Assert.NotEqual(guid0, await cache.GetOrCreateAsync(key, callback, options)); } }