From 1af60f33efaafa6a67aad7924aa0ba32cacaa138 Mon Sep 17 00:00:00 2001 From: reisenberger Date: Wed, 1 Nov 2017 22:45:55 +0000 Subject: [PATCH] Handle TimeSpan.MaxValue expiration and matching boundary tests --- .../MemoryCacheProvider.cs | 10 +- .../MemoryCacheProviderSpecs.cs | 134 ++++++++++++++++++ 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/src/Polly.Caching.MemoryCache.Shared/MemoryCacheProvider.cs b/src/Polly.Caching.MemoryCache.Shared/MemoryCacheProvider.cs index eb2a07c..0de336a 100644 --- a/src/Polly.Caching.MemoryCache.Shared/MemoryCacheProvider.cs +++ b/src/Polly.Caching.MemoryCache.Shared/MemoryCacheProvider.cs @@ -62,27 +62,29 @@ public object Get(String key) /// The time-to-live for the cache entry. public void Put(string key, object value, Ttl ttl) { + TimeSpan remaining = DateTimeOffset.MaxValue - SystemClock.DateTimeOffsetUtcNow(); + #if PORTABLE using (Microsoft.Extensions.Caching.Memory.ICacheEntry entry = _cache.CreateEntry(key)) { entry.Value = value; if (ttl.SlidingExpiration) { - entry.SlidingExpiration = ttl.Timespan; + entry.SlidingExpiration = ttl.Timespan < remaining ? ttl.Timespan : remaining; } else { - entry.AbsoluteExpirationRelativeToNow = ttl.Timespan; + entry.AbsoluteExpirationRelativeToNow = ttl.Timespan < remaining ? ttl.Timespan : remaining; } } #else System.Runtime.Caching.CacheItemPolicy cacheItemPolicy = new System.Runtime.Caching.CacheItemPolicy(); if (ttl.SlidingExpiration) { - cacheItemPolicy.SlidingExpiration = ttl.Timespan; + cacheItemPolicy.SlidingExpiration = ttl.Timespan < remaining ? ttl.Timespan : remaining; } else { - cacheItemPolicy.AbsoluteExpiration = SystemClock.DateTimeOffsetUtcNow().Add(ttl.Timespan); + cacheItemPolicy.AbsoluteExpiration = ttl.Timespan < remaining ? SystemClock.DateTimeOffsetUtcNow().Add(ttl.Timespan) : DateTimeOffset.MaxValue; } _cache.Set(key, value, cacheItemPolicy); #endif diff --git a/src/Polly.Caching.MemoryCache.SharedSpecs/MemoryCacheProviderSpecs.cs b/src/Polly.Caching.MemoryCache.SharedSpecs/MemoryCacheProviderSpecs.cs index 9cb396a..7859544 100644 --- a/src/Polly.Caching.MemoryCache.SharedSpecs/MemoryCacheProviderSpecs.cs +++ b/src/Polly.Caching.MemoryCache.SharedSpecs/MemoryCacheProviderSpecs.cs @@ -189,6 +189,140 @@ public void Put_should_put_item_using_passed_sliding_ttl() } } + #region Boundary tests + + [Fact] + public void Put_should_put_item_using_passed_nonsliding_ttl_maxvalue() + { +#if PORTABLE + MemoryCacheImplementation memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); +#else + MemoryCacheImplementation memoryCache = System.Runtime.Caching.MemoryCache.Default; +#endif + + string key = "anything"; + object value = new object(); + + MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); + Ttl ttl = new Ttl(TimeSpan.MaxValue, false); + provider.Put(key, value, ttl); + +#if PORTABLE + object got; + memoryCache.TryGetValue(key, out got); +#else + object got = memoryCache[key]; +#endif + got.Should().BeSameAs(value); + } + + [Fact] + public void Put_should_put_item_using_passed_sliding_ttl_maxvalue() + { +#if PORTABLE + MemoryCacheImplementation memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); +#else + MemoryCacheImplementation memoryCache = System.Runtime.Caching.MemoryCache.Default; +#endif + + string key = "anything"; + object value = new object(); + + MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); + + TimeSpan maxSlidingExpiration = +#if PORTABLE + TimeSpan.MaxValue +#else + TimeSpan.FromDays(365) // This is the maximum permitted sliding ttl for .NetFramework4.0 and 4.5 MemoryCache. +#endif + ; + + Ttl ttl = new Ttl(maxSlidingExpiration, true); + provider.Put(key, value, ttl); + +#if PORTABLE + object got; + memoryCache.TryGetValue(key, out got); +#else + object got = memoryCache[key]; +#endif + got.Should().BeSameAs(value); + } + + [Fact] + public void Put_should_put_item_using_passed_nonsliding_ttl_zero() + { +#if PORTABLE + MemoryCacheImplementation memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); +#else + MemoryCacheImplementation memoryCache = System.Runtime.Caching.MemoryCache.Default; +#endif + + string key = "anything"; + object value = new object(); + + MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); + + TimeSpan minExpiration = +#if PORTABLE + TimeSpan.FromMilliseconds(1) // This is the minimum permitted non-sliding ttl for .NetStandard +#else + TimeSpan.Zero +#endif + ; + + Ttl ttl = new Ttl(minExpiration, false); + provider.Put(key, value, ttl); + + Thread.Sleep(TimeSpan.FromMilliseconds(10)); + +#if PORTABLE + object got; + memoryCache.TryGetValue(key, out got); +#else + object got = memoryCache[key]; +#endif + got.Should().BeNull(); + } + + [Fact] + public void Put_should_put_item_using_passed_sliding_ttl_zero() + { +#if PORTABLE + MemoryCacheImplementation memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); +#else + MemoryCacheImplementation memoryCache = System.Runtime.Caching.MemoryCache.Default; +#endif + + string key = "anything"; + object value = new object(); + + MemoryCacheProvider provider = new MemoryCacheProvider(memoryCache); + + TimeSpan minExpiration = +#if PORTABLE + TimeSpan.FromMilliseconds(1) // This is the minimum permitted sliding ttl for .NetStandard +#else + TimeSpan.Zero +#endif + ; + + Ttl ttl = new Ttl(minExpiration, false); + provider.Put(key, value, ttl); + + Thread.Sleep(TimeSpan.FromMilliseconds(10)); + +#if PORTABLE + object got; + memoryCache.TryGetValue(key, out got); +#else + object got = memoryCache[key]; +#endif + got.Should().BeNull(); + } + #endregion + #endregion } } \ No newline at end of file