From 6c7ca6aab71127916f7c91788377b2ce68b0f351 Mon Sep 17 00:00:00 2001 From: ZLoo Date: Tue, 23 Jul 2024 02:20:08 +0300 Subject: [PATCH 1/2] Fix warning CA1062#AsyncCacheSyntax --- src/Polly/Caching/AsyncCacheSyntax.cs | 49 ++++++++++++++++++--- test/Polly.Specs/Caching/CacheAsyncSpecs.cs | 41 +++++++++++++++-- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/Polly/Caching/AsyncCacheSyntax.cs b/src/Polly/Caching/AsyncCacheSyntax.cs index 983e74b46d6..da9812acc75 100644 --- a/src/Polly/Caching/AsyncCacheSyntax.cs +++ b/src/Polly/Caching/AsyncCacheSyntax.cs @@ -1,7 +1,6 @@ #nullable enable namespace Polly; -#pragma warning disable CA1062 // Validate arguments of public methods public partial class Policy { /// @@ -46,8 +45,15 @@ public static AsyncCachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, ITt /// The policy instance. /// Thrown when is . /// Thrown when is . - public static AsyncCachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action? onCacheError = null) => - CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + public static AsyncCachePolicy CacheAsync(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ICacheKeyStrategy cacheKeyStrategy, Action? onCacheError = null) + { + if (cacheKeyStrategy is null) + { + throw new ArgumentNullException(nameof(cacheKeyStrategy)); + } + + return CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError); + } /// /// Builds an that will function like a result cache for delegate executions returning a result. @@ -222,8 +228,22 @@ public static AsyncCachePolicy CacheAsync( Action onCacheMiss, Action onCachePut, Action? onCacheGetError, - Action? onCachePutError) => - CacheAsync(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + Action? onCachePutError) + { + if (cacheKeyStrategy is null) + { + throw new ArgumentNullException(nameof(cacheKeyStrategy)); + } + + return CacheAsync(cacheProvider, + new RelativeTtl(ttl), + cacheKeyStrategy.GetCacheKey, + onCacheGet, + onCacheMiss, + onCachePut, + onCacheGetError, + onCachePutError); + } /// /// Builds an that will function like a result cache for delegate executions returning a result. @@ -254,8 +274,23 @@ public static AsyncCachePolicy CacheAsync( Action onCacheMiss, Action onCachePut, Action? onCacheGetError, - Action? onCachePutError) => - CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError); + Action? onCachePutError) + { + if (cacheKeyStrategy is null) + { + throw new ArgumentNullException(nameof(cacheKeyStrategy)); + } + + return CacheAsync( + cacheProvider, + ttlStrategy, + cacheKeyStrategy.GetCacheKey, + onCacheGet, + onCacheMiss, + onCachePut, + onCacheGetError, + onCachePutError); + } /// /// Builds an that will function like a result cache for delegate executions returning a result. diff --git a/test/Polly.Specs/Caching/CacheAsyncSpecs.cs b/test/Polly.Specs/Caching/CacheAsyncSpecs.cs index 92314aec7c3..974cb684058 100644 --- a/test/Polly.Specs/Caching/CacheAsyncSpecs.cs +++ b/test/Polly.Specs/Caching/CacheAsyncSpecs.cs @@ -26,9 +26,44 @@ public void Should_throw_when_ttl_strategy_is_null() public void Should_throw_when_cache_key_strategy_is_null() { IAsyncCacheProvider cacheProvider = new StubCacheProvider(); - Func cacheKeyStrategy = null!; - Action action = () => Policy.CacheAsync(cacheProvider, TimeSpan.MaxValue, cacheKeyStrategy); - action.Should().Throw().And.ParamName.Should().Be("cacheKeyStrategy"); + var ttl = TimeSpan.MaxValue; + ITtlStrategy ttlStrategy = new ContextualTtl(); + ICacheKeyStrategy cacheKeyStrategy = null!; + Func cacheKeyStrategyFunc = null!; + Action onCacheGet = (_, _) => { }; + Action onCacheMiss = (_, _) => { }; + Action onCachePut = (_, _) => { }; + Action? onCacheGetError = (_, _, _) => { }; + Action? onCachePutError = (_, _, _) => { }; + const string CacheKeyStrategyExpected = "cacheKeyStrategy"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync( + cacheProvider, + ttl, + cacheKeyStrategy, + onCacheGet, + onCacheMiss, + onCachePut, + onCacheGetError, + onCachePutError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync( + cacheProvider, + ttlStrategy, + cacheKeyStrategy, + onCacheGet, + onCacheMiss, + onCachePut, + onCacheGetError, + onCachePutError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); } #endregion From 079cba5b99845539e11fb13fd550626e33f47130 Mon Sep 17 00:00:00 2001 From: ZLoo Date: Tue, 23 Jul 2024 09:35:58 +0300 Subject: [PATCH 2/2] AddTests --- test/Polly.Specs/Caching/CacheAsyncSpecs.cs | 225 ++++++++++++++++++-- 1 file changed, 204 insertions(+), 21 deletions(-) diff --git a/test/Polly.Specs/Caching/CacheAsyncSpecs.cs b/test/Polly.Specs/Caching/CacheAsyncSpecs.cs index 974cb684058..31cfcf4ef0d 100644 --- a/test/Polly.Specs/Caching/CacheAsyncSpecs.cs +++ b/test/Polly.Specs/Caching/CacheAsyncSpecs.cs @@ -9,8 +9,49 @@ public class CacheAsyncSpecs : IDisposable public void Should_throw_when_cache_provider_is_null() { IAsyncCacheProvider cacheProvider = null!; - Action action = () => Policy.CacheAsync(cacheProvider, TimeSpan.MaxValue); - action.Should().Throw().And.ParamName.Should().Be("cacheProvider"); + var ttl = TimeSpan.MaxValue; + ITtlStrategy ttlStrategy = new ContextualTtl(); + ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]); + Func cacheKeyStrategyFunc = (_) => string.Empty; + Action onCache = (_, _) => { }; + Action? onCacheError = null; + const string CacheProviderExpected = "cacheProvider"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttl, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheProviderExpected); } [Fact] @@ -18,8 +59,29 @@ public void Should_throw_when_ttl_strategy_is_null() { IAsyncCacheProvider cacheProvider = new StubCacheProvider(); ITtlStrategy ttlStrategy = null!; - Action action = () => Policy.CacheAsync(cacheProvider, ttlStrategy); - action.Should().Throw().And.ParamName.Should().Be("ttlStrategy"); + ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]); + Func cacheKeyStrategyFunc = (_) => string.Empty; + Action onCache = (_, _) => { }; + Action? onCacheError = null; + const string TtlStrategyExpected = "ttlStrategy"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCache, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(TtlStrategyExpected); } [Fact] @@ -30,40 +92,161 @@ public void Should_throw_when_cache_key_strategy_is_null() ITtlStrategy ttlStrategy = new ContextualTtl(); ICacheKeyStrategy cacheKeyStrategy = null!; Func cacheKeyStrategyFunc = null!; - Action onCacheGet = (_, _) => { }; - Action onCacheMiss = (_, _) => { }; - Action onCachePut = (_, _) => { }; - Action? onCacheGetError = (_, _, _) => { }; - Action? onCachePutError = (_, _, _) => { }; + Action onCache = (_, _) => { }; + Action? onCacheError = null; const string CacheKeyStrategyExpected = "cacheKeyStrategy"; - Action action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy); + Action action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCacheError); action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); - action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc); + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCacheError); action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); action = () => Policy.CacheAsync( cacheProvider, ttl, cacheKeyStrategy, - onCacheGet, - onCacheMiss, - onCachePut, - onCacheGetError, - onCachePutError); + onCache, + onCache, + onCache, + onCacheError, + onCacheError); action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); action = () => Policy.CacheAsync( cacheProvider, ttlStrategy, cacheKeyStrategy, - onCacheGet, - onCacheMiss, - onCachePut, - onCacheGetError, - onCachePutError); + onCache, + onCache, + onCache, + onCacheError, + onCacheError); action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync( + cacheProvider, + ttl, + cacheKeyStrategyFunc, + onCache, + onCache, + onCache, + onCacheError, + onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + + action = () => Policy.CacheAsync( + cacheProvider, + ttlStrategy, + cacheKeyStrategyFunc, + onCache, + onCache, + onCache, + onCacheError, + onCacheError); + action.Should().Throw().And.ParamName.Should().Be(CacheKeyStrategyExpected); + } + + [Fact] + public void Should_throw_when_on_cache_get_is_null() + { + IAsyncCacheProvider cacheProvider = new StubCacheProvider(); + var ttl = TimeSpan.MaxValue; + ITtlStrategy ttlStrategy = new ContextualTtl(); + ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]); + Func cacheKeyStrategyFunc = (_) => string.Empty; + Action onCacheGet = null!; + Action onCache = (_, _) => { }; + Action? onCacheError = null; + const string OnCacheGetExpected = "onCacheGet"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttl, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCacheGet, onCache, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheGetExpected); + } + + [Fact] + public void Should_throw_when_on_cache_miss_is_null() + { + IAsyncCacheProvider cacheProvider = new StubCacheProvider(); + var ttl = TimeSpan.MaxValue; + ITtlStrategy ttlStrategy = new ContextualTtl(); + ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]); + Func cacheKeyStrategyFunc = (_) => string.Empty; + Action onCacheMiss = null!; + Action onCache = (_, _) => { }; + Action? onCacheError = null; + const string OnCacheMissExpected = "onCacheMiss"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttl, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCache, onCacheMiss, onCache, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCacheMissExpected); + } + + [Fact] + public void Should_throw_when_on_cache_put_is_null() + { + IAsyncCacheProvider cacheProvider = new StubCacheProvider(); + var ttl = TimeSpan.MaxValue; + ITtlStrategy ttlStrategy = new ContextualTtl(); + ICacheKeyStrategy cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]); + Func cacheKeyStrategyFunc = (_) => string.Empty; + Action onCachePut = null!; + Action onCache = (_, _) => { }; + Action? onCacheError = null; + const string OnCachePutExpected = "onCachePut"; + + Action action = () => Policy.CacheAsync(cacheProvider, ttl, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategy, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategy, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttl, cacheKeyStrategyFunc, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); + + action = () => Policy.CacheAsync(cacheProvider, ttlStrategy, cacheKeyStrategyFunc, onCache, onCache, onCachePut, onCacheError, onCacheError); + action.Should().Throw().And.ParamName.Should().Be(OnCachePutExpected); } #endregion