public void TryGet_ChecksLocalCacheThenDistributedCache() { var localCache = new MockLocalCache <int, int>(); var distributedCache = new MockDistributedCache <int, int>(); var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default); for (var i = 1; i <= 100; i++) { twoTierCache.TryGet(i).Result.Success.Should().BeFalse(); localCache.TryGetExecutionCount.Should().Be(i); distributedCache.TryGetExecutionCount.Should().Be(i); } for (var i = 1; i <= 100; i++) { twoTierCache.Set(i, i, TimeSpan.FromSeconds(1)).AsTask().Wait(); localCache.SetExecutionCount.Should().Be(i); distributedCache.SetExecutionCount.Should().Be(i); } for (var i = 1; i <= 100; i++) { var(success, value, _) = twoTierCache.TryGet(i).Result; success.Should().BeTrue(); value.Should().Be(i); localCache.TryGetExecutionCount.Should().Be(100 + i); distributedCache.TryGetExecutionCount.Should().Be(100); } }
public void GetMany_SetsValueInLocalCacheIfFoundInDistributedCache() { var localCache = new MockLocalCache <int, int>(); var distributedCache = new MockDistributedCache <int, int>(); var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default); distributedCache .SetMany(Enumerable.Range(0, 50).Select(i => new KeyValuePair <int, int>(i, i)).ToArray(), TimeSpan.FromSeconds(1)) .Wait(); distributedCache.SetManyExecutionCount.Should().Be(1); var values1 = twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result; values1.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50)); localCache.GetManyExecutionCount.Should().Be(1); localCache.SetExecutionCount.Should().Be(50); distributedCache.GetManyExecutionCount.Should().Be(1); var values2 = twoTierCache.GetMany(Enumerable.Range(0, 50).ToArray()).Result; values2.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50)); localCache.GetManyExecutionCount.Should().Be(2); distributedCache.GetManyExecutionCount.Should().Be(1); }
public void TryGet_SetsValueInLocalCacheIfFoundInDistributedCache() { var localCache = new MockLocalCache <int, int>(); var distributedCache = new MockDistributedCache <int, int>(); var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default); for (var i = 1; i <= 100; i++) { distributedCache.Set(i, i, TimeSpan.FromSeconds(100)); distributedCache.SetExecutionCount.Should().Be(i); } for (var i = 1; i <= 100; i++) { var(success, value, _) = twoTierCache.TryGet(i).Result; success.Should().BeTrue(); value.Should().Be(i); localCache.SetExecutionCount.Should().Be(i); localCache.TryGet(i, out var fromLocalCache).Should().BeTrue(); fromLocalCache.Should().Be(i); } }
public void GetMany_ChecksLocalCacheThenDistributedCache() { var localCache = new MockLocalCache <int, int>(); var distributedCache = new MockDistributedCache <int, int>(); var twoTierCache = new TwoTierCache <int, int>(localCache, distributedCache, EqualityComparer <int> .Default); twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result.Should().BeEmpty(); localCache.GetManyExecutionCount.Should().Be(1); distributedCache.GetManyExecutionCount.Should().Be(1); twoTierCache.SetMany(Enumerable.Range(0, 50).Select(i => new KeyValuePair <int, int>(i, i)).ToArray(), TimeSpan.FromSeconds(1)); localCache.SetManyExecutionCount.Should().Be(1); distributedCache.SetManyExecutionCount.Should().Be(1); var results1 = twoTierCache.GetMany(Enumerable.Range(0, 100).ToArray()).Result; results1.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50)); foreach (var(key, value) in results1) { value.Should().Be(key); } localCache.GetManyExecutionCount.Should().Be(2); distributedCache.GetManyExecutionCount.Should().Be(2); var results2 = twoTierCache.GetMany(Enumerable.Range(0, 50).ToArray()).Result; results2.Select(kv => kv.Key).Should().BeEquivalentTo(Enumerable.Range(0, 50)); foreach (var(key, value) in results2) { value.Should().Be(key); } localCache.GetManyExecutionCount.Should().Be(3); distributedCache.GetManyExecutionCount.Should().Be(2); }
public void CacheStats_PopulatedCorrectly(bool localCacheEnabled, bool distributedCacheEnabled) { CacheGetStats lastCacheStats = default; Func <int, int> originalFunction = key => key; var config = CachedFunctionFactory.ConfigureFor(originalFunction) .WithTimeToLive(TimeSpan.FromMinutes(1)) .OnResult(r => lastCacheStats = r.CacheStats) .DontGetFromCacheWhen(k => k == 1) .DontGetFromLocalCacheWhen(k => k == 2) .DontGetFromDistributedCacheWhen(k => k == 3); if (localCacheEnabled) { var localCache = new MockLocalCache <int, int>(); localCache.Set(4, 4, TimeSpan.FromMinutes(1)); config.WithLocalCache(localCache); } if (distributedCacheEnabled) { var distributedCache = new MockDistributedCache <int, int>(); distributedCache.Set(4, 4, TimeSpan.FromMinutes(1)); distributedCache.Set(5, 5, TimeSpan.FromMinutes(1)); config.WithDistributedCache(distributedCache); } var cachedFunction = config.Build(); var cacheEnabled = localCacheEnabled || distributedCacheEnabled; for (var i = 1; i <= 5; i++) { cachedFunction(i).Should().Be(i); VerifyCacheStats(i); } void VerifyCacheStats(int key) { var localCacheKeyRequested = localCacheEnabled && key != 1 && key != 2; var localCacheHit = localCacheEnabled && key == 4; var distributedCacheKeyRequested = distributedCacheEnabled && !localCacheHit && key != 1 && key != 3; var distributedCacheHit = distributedCacheKeyRequested && (key == 4 || key == 5); var cacheKeyRequested = localCacheKeyRequested || distributedCacheKeyRequested; var cacheHit = localCacheHit || distributedCacheHit; lastCacheStats.CacheEnabled.Should().Be(cacheEnabled); lastCacheStats.CacheKeyRequested.Should().Be(cacheKeyRequested); lastCacheStats.CacheSkipped.Should().Be(cacheEnabled && !cacheKeyRequested); lastCacheStats.CacheHit.Should().Be(cacheHit); lastCacheStats.CacheMiss.Should().Be(cacheKeyRequested && !cacheHit); lastCacheStats.LocalCacheEnabled.Should().Be(localCacheEnabled); lastCacheStats.LocalCacheKeyRequested.Should().Be(localCacheKeyRequested); lastCacheStats.LocalCacheSkipped.Should().Be(localCacheEnabled && !localCacheKeyRequested); lastCacheStats.LocalCacheHit.Should().Be(localCacheHit); lastCacheStats.LocalCacheMiss.Should().Be(localCacheKeyRequested && !localCacheHit); lastCacheStats.DistributedCacheEnabled.Should().Be(distributedCacheEnabled); lastCacheStats.DistributedCacheKeyRequested.Should().Be(distributedCacheKeyRequested); lastCacheStats.DistributedCacheSkipped.Should().Be(distributedCacheEnabled && !localCacheHit && !distributedCacheKeyRequested); lastCacheStats.DistributedCacheHit.Should().Be(distributedCacheHit); lastCacheStats.DistributedCacheMiss.Should().Be(distributedCacheKeyRequested && !distributedCacheHit); } }
public void DontGetFromOrStoreInDistributedCacheWhen_ForSingleTierCache_WorksAsExpected( bool flag1, bool flag2, bool flag3, bool flag4) { Func <int, int> originalFunction = key => key; var cache = new MockDistributedCache <int, int>(); var config = CachedFunctionFactory .ConfigureFor(originalFunction) .WithDistributedCache(cache) .WithTimeToLive(TimeSpan.FromSeconds(1)); if (flag1) { config.DontGetFromDistributedCacheWhen(key => key % 2 == 0); } if (flag2) { config.DontStoreInDistributedCacheWhen((key, _) => key % 3 == 0); } if (flag3) { config.DontGetFromDistributedCacheWhen(key => key % 5 == 0); } if (flag4) { config.DontStoreInDistributedCacheWhen((key, _) => key % 7 == 0); } var cachedFunction = config.Build(); var previousTryGetExecutionCount = 0; var previousSetExecutionCount = 0; for (var i = 0; i < 100; i++) { cachedFunction(i); var currentTryGetExecutionCount = cache.TryGetExecutionCount; var currentSetExecutionCount = cache.SetExecutionCount; var skipGet = flag1 && i % 2 == 0 || flag3 && i % 5 == 0; var skipSet = flag2 && i % 3 == 0 || flag4 && i % 7 == 0; if (skipGet) { currentTryGetExecutionCount.Should().Be(previousTryGetExecutionCount); } else { currentTryGetExecutionCount.Should().Be(previousTryGetExecutionCount + 1); } if (skipSet) { currentSetExecutionCount.Should().Be(previousSetExecutionCount); } else { currentSetExecutionCount.Should().Be(previousSetExecutionCount + 1); } previousTryGetExecutionCount = currentTryGetExecutionCount; previousSetExecutionCount = currentSetExecutionCount; } }
public void DontGetFromOrStoreInLocalCacheWhen_DontGetFromOrStoreInDistributedCacheWhen_WorksAsExpected( bool flag1, bool flag2, bool flag3, bool flag4, bool flag5, bool flag6, bool flag7, bool flag8) { Func <int, int> originalFunction = key => key; var localCache = new MockLocalCache <int, int>(); var distributedCache = new MockDistributedCache <int, int>(); var config = CachedFunctionFactory .ConfigureFor(originalFunction) .WithLocalCache(localCache) .WithDistributedCache(distributedCache) .WithTimeToLive(TimeSpan.FromSeconds(1)); if (flag1) { config.DontGetFromLocalCacheWhen(key => key % 2 == 0); } if (flag2) { config.DontStoreInLocalCacheWhen((key, _) => key % 3 == 0); } if (flag3) { config.DontGetFromLocalCacheWhen(key => key % 5 == 0); } if (flag4) { config.DontStoreInLocalCacheWhen((key, _) => key % 7 == 0); } if (flag5) { config.DontGetFromDistributedCacheWhen(key => key % 11 == 0); } if (flag6) { config.DontStoreInDistributedCacheWhen((key, _) => key % 13 == 0); } if (flag7) { config.DontGetFromDistributedCacheWhen(key => key % 17 == 0); } if (flag8) { config.DontStoreInDistributedCacheWhen((key, _) => key % 19 == 0); } var cachedFunction = config.Build(); var previousLocalTryGetExecutionCount = 0; var previousLocalSetExecutionCount = 0; var previousDistributedTryGetExecutionCount = 0; var previousDistributedSetExecutionCount = 0; for (var i = 0; i < 100; i++) { cachedFunction(i); var currentLocalTryGetExecutionCount = localCache.TryGetExecutionCount; var currentLocalSetExecutionCount = localCache.SetExecutionCount; var currentDistributedTryGetExecutionCount = distributedCache.TryGetExecutionCount; var currentDistributedSetExecutionCount = distributedCache.SetExecutionCount; var skipLocalGet = flag1 && i % 2 == 0 || flag3 && i % 5 == 0; var skipLocalSet = flag2 && i % 3 == 0 || flag4 && i % 7 == 0; var skipDistributedGet = flag5 && i % 11 == 0 || flag7 && i % 17 == 0; var skipDistributedSet = flag6 && i % 13 == 0 || flag8 && i % 19 == 0; if (skipLocalGet) { currentLocalTryGetExecutionCount.Should().Be(previousLocalTryGetExecutionCount); } else { currentLocalTryGetExecutionCount.Should().Be(previousLocalTryGetExecutionCount + 1); } if (skipLocalSet) { currentLocalSetExecutionCount.Should().Be(previousLocalSetExecutionCount); } else { currentLocalSetExecutionCount.Should().Be(previousLocalSetExecutionCount + 1); } if (skipDistributedGet) { currentDistributedTryGetExecutionCount.Should().Be(previousDistributedTryGetExecutionCount); } else { currentDistributedTryGetExecutionCount.Should().Be(previousDistributedTryGetExecutionCount + 1); } if (skipDistributedSet) { currentDistributedSetExecutionCount.Should().Be(previousDistributedSetExecutionCount); } else { currentDistributedSetExecutionCount.Should().Be(previousDistributedSetExecutionCount + 1); } previousLocalTryGetExecutionCount = currentLocalTryGetExecutionCount; previousLocalSetExecutionCount = currentLocalSetExecutionCount; previousDistributedTryGetExecutionCount = currentDistributedTryGetExecutionCount; previousDistributedSetExecutionCount = currentDistributedSetExecutionCount; } }
public async Task TryRemove_EventsAreTriggeredSuccessfully(bool flag1, bool flag2) { var config = new DistributedCacheEventsWrapperConfig <int, int, int>(); var successfulResults = new List <(int, int, bool, TimeSpan)>(); var failedResults = new List <(int, int, TimeSpan, Exception)>(); if (flag1) { config.OnTryRemoveCompletedSuccessfully = (outerKey, innerKey, wasRemoved, duration) => { successfulResults.Add((outerKey, innerKey, wasRemoved, duration)); }; } if (flag2) { config.OnTryRemoveException = (outerKey, innerKey, duration, exception) => { failedResults.Add((outerKey, innerKey, duration, exception)); return(innerKey == 3); }; } var innerCache = new MockDistributedCache <int, int, int>(); var cache = new DistributedCacheEventsWrapper <int, int, int>(config, innerCache); await cache.TryRemove(1, 1).ConfigureAwait(false); if (flag1) { successfulResults.Should().ContainSingle(); successfulResults.Last().Item1.Should().Be(1); successfulResults.Last().Item2.Should().Be(1); successfulResults.Last().Item3.Should().BeFalse(); successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { successfulResults.Should().BeEmpty(); } await cache.Set(1, 2, 3, TimeSpan.FromSeconds(1)).ConfigureAwait(false); await cache.TryRemove(1, 2).ConfigureAwait(false); if (flag1) { successfulResults.Should().HaveCount(2); successfulResults.Last().Item1.Should().Be(1); successfulResults.Last().Item2.Should().Be(2); successfulResults.Last().Item3.Should().BeTrue(); successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { successfulResults.Should().BeEmpty(); } innerCache.ThrowExceptionOnNextAction(); Func <Task> action = () => cache.TryRemove(1, 3); if (flag2) { await action().ConfigureAwait(false); failedResults.Should().ContainSingle(); failedResults.Last().Item1.Should().Be(1); failedResults.Last().Item2.Should().Be(3); failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { await action.Should().ThrowAsync <Exception>().ConfigureAwait(false); failedResults.Should().BeEmpty(); } }
public async Task GetMany_EventsAreTriggeredSuccessfully(bool flag1, bool flag2) { var config = new DistributedCacheEventsWrapperConfig <int, int, int>(); var successfulResults = new List <(int, IReadOnlyCollection <int>, IReadOnlyCollection <KeyValuePair <int, ValueAndTimeToLive <int> > >, TimeSpan)>(); var failedResults = new List <(int, IReadOnlyCollection <int>, TimeSpan, Exception)>(); if (flag1) { config.OnGetManyCompletedSuccessfully = (outerKey, innerKeys, values, duration) => { successfulResults.Add((outerKey, innerKeys, values, duration)); }; } if (flag2) { config.OnGetManyException = (outerKey, innerKeys, duration, exception) => { failedResults.Add((outerKey, innerKeys, duration, exception)); return(innerKeys.Contains(4)); }; } var innerCache = new MockDistributedCache <int, int, int>(); var cache = new DistributedCacheEventsWrapper <int, int, int>(config, innerCache); var innerKeys = new[] { 2, 3 }; await cache.SetMany(1, new[] { new KeyValuePair <int, int>(2, 3) }, TimeSpan.FromSeconds(1)).ConfigureAwait(false); await cache.GetMany(1, innerKeys).ConfigureAwait(false); if (flag1) { successfulResults.Should().ContainSingle(); successfulResults.Last().Item1.Should().Be(1); successfulResults.Last().Item2.Should().BeEquivalentTo(innerKeys); successfulResults.Last().Item3.ToArray().Select(kv => kv.Key).Should().BeEquivalentTo(2); successfulResults.Last().Item4.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { successfulResults.Should().BeEmpty(); } innerCache.ThrowExceptionOnNextAction(); Func <Task> action = () => cache.GetMany(1, innerKeys); await action.Should().ThrowAsync <Exception>().ConfigureAwait(false); if (flag2) { failedResults.Should().ContainSingle(); failedResults.Last().Item1.Should().Be(1); failedResults.Last().Item2.Should().BeEquivalentTo(innerKeys); failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { failedResults.Should().BeEmpty(); } innerKeys[1] = 4; innerCache.ThrowExceptionOnNextAction(); action = () => cache.GetMany(1, innerKeys); if (flag2) { await action().ConfigureAwait(false); failedResults.Should().HaveCount(2); failedResults.Last().Item1.Should().Be(1); failedResults.Last().Item2.Should().BeEquivalentTo(innerKeys); failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { await action.Should().ThrowAsync <Exception>().ConfigureAwait(false); failedResults.Should().BeEmpty(); } }
public async Task SetMany_EventsAreTriggeredSuccessfully(bool flag1, bool flag2) { var config = new DistributedCacheEventsWrapperConfig <int, int>(); var successfulResults = new List <(IReadOnlyCollection <KeyValuePair <int, int> >, TimeSpan, TimeSpan)>(); var failedResults = new List <(IReadOnlyCollection <KeyValuePair <int, int> >, TimeSpan, TimeSpan, Exception)>(); if (flag1) { config.OnSetManyCompletedSuccessfully = (values, timeToLive, duration) => { successfulResults.Add((values, timeToLive, duration)); }; } if (flag2) { config.OnSetManyException = (values, timeToLive, duration, exception) => { failedResults.Add((values, timeToLive, duration, exception)); return(values.Any(kv => kv.Key == 5)); }; } var innerCache = new MockDistributedCache <int, int>(); var cache = new DistributedCacheEventsWrapper <int, int>(config, innerCache); var values = new[] { new KeyValuePair <int, int>(1, 2), new KeyValuePair <int, int>(3, 4) }; await cache.SetMany(values, TimeSpan.FromSeconds(1)).ConfigureAwait(false); if (flag1) { successfulResults.Should().ContainSingle(); successfulResults.Last().Item1.Should().BeEquivalentTo(values); successfulResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1)); successfulResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { successfulResults.Should().BeEmpty(); } innerCache.ThrowExceptionOnNextAction(); Func <Task> action = () => cache.SetMany(values, TimeSpan.FromSeconds(1)); await action.Should().ThrowAsync <Exception>().ConfigureAwait(false); if (flag2) { failedResults.Should().ContainSingle(); failedResults.Last().Item1.Should().BeEquivalentTo(values); failedResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1)); failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { failedResults.Should().BeEmpty(); } values[1] = new KeyValuePair <int, int>(5, 6); innerCache.ThrowExceptionOnNextAction(); action = () => cache.SetMany(values, TimeSpan.FromSeconds(1)); if (flag2) { await action().ConfigureAwait(false); failedResults.Should().HaveCount(2); failedResults.Last().Item1.Should().BeEquivalentTo(values); failedResults.Last().Item2.Should().Be(TimeSpan.FromSeconds(1)); failedResults.Last().Item3.Should().BePositive().And.BeCloseTo(TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); } else { await action.Should().ThrowAsync <Exception>().ConfigureAwait(false); failedResults.Should().BeEmpty(); } }