public void AbsoluteExpirationExpiresInBackground() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var value = new object(); var callbackInvoked = new ManualResetEvent(false); var options = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(clock.UtcNow + TimeSpan.FromMinutes(1)) .RegisterPostEvictionCallback((subkey, subValue, reason, state) => { // TODO: Verify params var localCallbackInvoked = (ManualResetEvent)state; localCallbackInvoked.Set(); }, callbackInvoked); var result = cache.Set(key, value, options); Assert.Same(value, result); var found = cache.TryGetValue(key, out result); Assert.True(found); Assert.Same(value, result); clock.Add(TimeSpan.FromMinutes(2)); var ignored = cache.Get("otherKey"); // Background expiration checks are triggered by misc cache activity. Assert.True(callbackInvoked.WaitOne(TimeSpan.FromSeconds(30)), "Callback"); found = cache.TryGetValue(key, out result); Assert.False(found); Assert.Null(result); }
public void AbsoluteExpirationInThePastThrows() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var obj = new object(); var expected = clock.UtcNow - TimeSpan.FromMinutes(1); ExceptionAssert.ThrowsArgumentOutOfRange(() => { var result = cache.Set(key, obj, new MemoryCacheEntryOptions().SetAbsoluteExpiration(expected)); }, nameof(MemoryCacheEntryOptions.AbsoluteExpiration), "The absolute expiration value must be in the future.", expected.ToString(CultureInfo.CurrentCulture)); }
public void AbsoluteExpirationExpires() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var value = new object(); var result = cache.Set(key, value, new MemoryCacheEntryOptions() .SetAbsoluteExpiration(clock.UtcNow + TimeSpan.FromMinutes(1))); Assert.Same(value, result); var found = cache.TryGetValue(key, out result); Assert.True(found); Assert.Same(value, result); clock.Add(TimeSpan.FromMinutes(2)); found = cache.TryGetValue(key, out result); Assert.False(found); Assert.Null(result); }
public void AbsoluteExpiration_WorksAcrossLink() { var clock = new TestClock(); var cache = CreateCache(clock); var obj = new object(); string key = "myKey"; string key1 = "myKey1"; var expirationToken = new TestExpirationToken() { ActiveChangeCallbacks = true }; using (var link = cache.CreateLinkingScope()) { cache.Set(key, obj, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(5))); cache.Set(key1, obj, new MemoryCacheEntryOptions().AddEntryLink(link)); } Assert.Same(obj, cache.Get(key)); Assert.Same(obj, cache.Get(key1)); clock.Add(TimeSpan.FromSeconds(10)); object value; Assert.False(cache.TryGetValue(key1, out value)); Assert.False(cache.TryGetValue(key, out value)); }
public void NestedLinkContextsCanAggregate() { var clock = new TestClock(); var cache = CreateCache(clock); var obj = new object(); string key2 = "myKey2"; string key3 = "myKey3"; var expirationToken2 = new TestExpirationToken() { ActiveChangeCallbacks = true }; var expirationToken3 = new TestExpirationToken() { ActiveChangeCallbacks = true }; IEntryLink link1 = null; IEntryLink link2 = null; using (link1 = cache.CreateLinkingScope()) { cache.Set(key2, obj, new MemoryCacheEntryOptions() .AddExpirationToken(expirationToken2) .SetAbsoluteExpiration(TimeSpan.FromSeconds(10))); using (link2 = cache.CreateLinkingScope()) { cache.Set(key3, obj, new MemoryCacheEntryOptions() .AddExpirationToken(expirationToken3) .SetAbsoluteExpiration(TimeSpan.FromSeconds(15))); } } Assert.Equal(1, link1.ExpirationTokens.Count()); Assert.NotNull(link1.AbsoluteExpiration); Assert.Equal(clock.UtcNow + TimeSpan.FromSeconds(10), link1.AbsoluteExpiration); Assert.Equal(1, link2.ExpirationTokens.Count()); Assert.NotNull(link2.AbsoluteExpiration); Assert.Equal(clock.UtcNow + TimeSpan.FromSeconds(15), link2.AbsoluteExpiration); }
public void SlidingExpirationRenewedByAccessUntilAbsoluteExpiration() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var value = new object(); var result = cache.Set(key, value, new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromMinutes(1)) .SetAbsoluteExpiration(TimeSpan.FromMinutes(2))); Assert.Same(value, result); var found = cache.TryGetValue(key, out result); Assert.True(found); Assert.Same(value, result); for (int i = 0; i < 7; i++) { clock.Add(TimeSpan.FromSeconds(15)); found = cache.TryGetValue(key, out result); Assert.True(found); Assert.Same(value, result); } clock.Add(TimeSpan.FromSeconds(15)); found = cache.TryGetValue(key, out result); Assert.False(found); Assert.Null(result); }
public void ZeroSlidingExpirationThrows() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var value = new object(); ExceptionAssert.ThrowsArgumentOutOfRange(() => { var result = cache.Set(key, value, new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.Zero)); }, nameof(MemoryCacheEntryOptions.SlidingExpiration), "The sliding expiration value must be positive.", TimeSpan.Zero); }
public void NegativeRelativeExpirationThrows() { var clock = new TestClock(); var cache = CreateCache(clock); var key = "myKey"; var value = new object(); ExceptionAssert.ThrowsArgumentOutOfRange(() => { var result = cache.Set(key, value, new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(-1))); }, nameof(MemoryCacheEntryOptions.AbsoluteExpirationRelativeToNow), "The relative expiration value must be positive.", TimeSpan.FromMinutes(-1)); }
public async Task RefreshesSession_WhenSessionData_IsNotModified() { var clock = new TestClock(); using (var server = TestServer.Create(app => { app.UseSession(); app.Run(context => { string responseData = string.Empty; if (context.Request.Path == new PathString("/AddDataToSession")) { context.Session.SetInt32("Key", 10); responseData = "added data to session"; } else if (context.Request.Path == new PathString("/AccessSessionData")) { var value = context.Session.GetInt32("Key"); responseData = (value == null) ? "No value found in session." : value.ToString(); } else if (context.Request.Path == new PathString("/DoNotAccessSessionData")) { responseData = "did not access session data"; } return context.Response.WriteAsync(responseData); }); }, services => { services.AddInstance(typeof(ILoggerFactory), new NullLoggerFactory()); services.AddCaching(); services.AddSession(o => o.IdleTimeout = TimeSpan.FromMinutes(20)); services.Configure<MemoryCacheOptions>(o => o.Clock = clock); })) { var client = server.CreateClient(); var response = await client.GetAsync("AddDataToSession"); response.EnsureSuccessStatusCode(); client = server.CreateClient(); var cookie = SetCookieHeaderValue.ParseList(response.Headers.GetValues("Set-Cookie").ToList()).First(); client.DefaultRequestHeaders.Add( "Cookie", new CookieHeaderValue(cookie.Name, cookie.Value).ToString()); for (var i = 0; i < 5; i++) { clock.Add(TimeSpan.FromMinutes(10)); await client.GetStringAsync("/DoNotAccessSessionData"); } var data = await client.GetStringAsync("/AccessSessionData"); Assert.Equal("10", data); } }
public void ExpiredLazyTokenRemovesItemInBackground() { var clock = new TestClock(); var cache = CreateCache(clock); string key = "myKey"; var value = new object(); var callbackInvoked = new ManualResetEvent(false); var expirationToken = new TestExpirationToken() { ActiveChangeCallbacks = false }; cache.Set(key, value, new MemoryCacheEntryOptions() .AddExpirationToken(expirationToken) .RegisterPostEvictionCallback((subkey, subValue, reason, state) => { // TODO: Verify params var localCallbackInvoked = (ManualResetEvent)state; localCallbackInvoked.Set(); }, state: callbackInvoked)); var found = cache.TryGetValue(key, out value); Assert.True(found); clock.Add(TimeSpan.FromMinutes(2)); expirationToken.HasChanged = true; var ignored = cache.Get("otherKey"); // Background expiration checks are triggered by misc cache activity. Assert.True(callbackInvoked.WaitOne(TimeSpan.FromSeconds(30)), "Callback"); found = cache.TryGetValue(key, out value); Assert.False(found); }