From 805071f298cfad7a4eb8327f9e685c09c67239f8 Mon Sep 17 00:00:00 2001 From: ZLoo Date: Sun, 21 Jul 2024 23:41:13 +0300 Subject: [PATCH 1/3] Fix test check InnerException --- test/Polly.Specs/NoOp/NoOpSpecs.cs | 3 ++- test/Polly.Specs/NoOp/NoOpTResultAsyncSpecs.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Polly.Specs/NoOp/NoOpSpecs.cs b/test/Polly.Specs/NoOp/NoOpSpecs.cs index 6ff214de8c7..1bc37b87b5b 100644 --- a/test/Polly.Specs/NoOp/NoOpSpecs.cs +++ b/test/Polly.Specs/NoOp/NoOpSpecs.cs @@ -18,7 +18,8 @@ public void Should_throw_when_action_is_null() var exceptionAssertions = func.Should().Throw(); exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation."); - exceptionAssertions.WithInnerException("action"); + exceptionAssertions.And.InnerException.Should().BeOfType() + .Which.ParamName.Should().Be("action"); } [Fact] diff --git a/test/Polly.Specs/NoOp/NoOpTResultAsyncSpecs.cs b/test/Polly.Specs/NoOp/NoOpTResultAsyncSpecs.cs index 03e24cf3c16..3121fd9ae80 100644 --- a/test/Polly.Specs/NoOp/NoOpTResultAsyncSpecs.cs +++ b/test/Polly.Specs/NoOp/NoOpTResultAsyncSpecs.cs @@ -17,7 +17,8 @@ public void Should_throw_when_action_is_null() var exceptionAssertions = func.Should().Throw(); exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation."); - exceptionAssertions.WithInnerException("action"); + exceptionAssertions.And.InnerException.Should().BeOfType() + .Which.ParamName.Should().Be("action"); } [Fact] From e9f76a967b653ee64cc966061d607abaa7fcf320 Mon Sep 17 00:00:00 2001 From: ZLoo Date: Sun, 21 Jul 2024 23:41:44 +0300 Subject: [PATCH 2/3] Fix warning CA1062#AsyncRateLimitPolicy --- src/Polly/RateLimit/AsyncRateLimitPolicy.cs | 35 +++++++++++++++---- .../RateLimit/AsyncRateLimitPolicySpecs.cs | 26 ++++++++++++++ .../AsyncRateLimitPolicyTResultSpecs.cs | 26 ++++++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/Polly/RateLimit/AsyncRateLimitPolicy.cs b/src/Polly/RateLimit/AsyncRateLimitPolicy.cs index ff4cf9e351a..858d7c6cfa4 100644 --- a/src/Polly/RateLimit/AsyncRateLimitPolicy.cs +++ b/src/Polly/RateLimit/AsyncRateLimitPolicy.cs @@ -4,7 +4,6 @@ namespace Polly.RateLimit; /// /// A rate-limit policy that can be applied to asynchronous delegates. /// -#pragma warning disable CA1062 // Validate arguments of public methods public class AsyncRateLimitPolicy : AsyncPolicy, IRateLimitPolicy { private readonly IRateLimiter _rateLimiter; @@ -14,9 +13,20 @@ internal AsyncRateLimitPolicy(IRateLimiter rateLimiter) => /// [DebuggerStepThrough] - protected override Task ImplementationAsync(Func> action, Context context, CancellationToken cancellationToken, - bool continueOnCapturedContext) => - AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, null, action, context, continueOnCapturedContext, cancellationToken); + protected override Task ImplementationAsync( + Func> action, + Context context, + CancellationToken cancellationToken, + bool continueOnCapturedContext) + { + if (action is null) + { + throw new ArgumentNullException(nameof(action)); + } + + return AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, null, action, context, continueOnCapturedContext, + cancellationToken); + } } /// @@ -38,7 +48,18 @@ internal AsyncRateLimitPolicy( /// [DebuggerStepThrough] - protected override Task ImplementationAsync(Func> action, Context context, CancellationToken cancellationToken, - bool continueOnCapturedContext) => - AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, _retryAfterFactory, action, context, continueOnCapturedContext, cancellationToken); + protected override Task ImplementationAsync( + Func> action, + Context context, + CancellationToken cancellationToken, + bool continueOnCapturedContext) + { + if (action is null) + { + throw new ArgumentNullException(nameof(action)); + } + + return AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, _retryAfterFactory, action, context, + continueOnCapturedContext, cancellationToken); + } } diff --git a/test/Polly.Specs/RateLimit/AsyncRateLimitPolicySpecs.cs b/test/Polly.Specs/RateLimit/AsyncRateLimitPolicySpecs.cs index 85d2b1dc413..cf1321d244c 100644 --- a/test/Polly.Specs/RateLimit/AsyncRateLimitPolicySpecs.cs +++ b/test/Polly.Specs/RateLimit/AsyncRateLimitPolicySpecs.cs @@ -31,4 +31,30 @@ protected override (bool, TimeSpan) TryExecuteThroughPolicy(IRateLimitPolicy pol throw new InvalidOperationException("Unexpected policy type in test construction."); } } + + [Fact] + public void Should_throw_when_action_is_null() + { + var flags = BindingFlags.NonPublic | BindingFlags.Instance; + Func> action = null!; + IRateLimiter rateLimiter = RateLimiterFactory.Create(TimeSpan.FromSeconds(1), 1); + + var instance = Activator.CreateInstance( + typeof(AsyncRateLimitPolicy), + flags, + null, + [rateLimiter], + null)!; + var instanceType = instance.GetType(); + var methods = instanceType.GetMethods(flags); + var methodInfo = methods.First(method => method is { Name: "ImplementationAsync", ReturnType.Name: "Task`1" }); + var generic = methodInfo.MakeGenericMethod(typeof(EmptyStruct)); + + var func = () => generic.Invoke(instance, [action, new Context(), CancellationToken.None, false]); + + var exceptionAssertions = func.Should().Throw(); + exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation."); + exceptionAssertions.And.InnerException.Should().BeOfType() + .Which.ParamName.Should().Be("action"); + } } diff --git a/test/Polly.Specs/RateLimit/AsyncRateLimitPolicyTResultSpecs.cs b/test/Polly.Specs/RateLimit/AsyncRateLimitPolicyTResultSpecs.cs index 00bbe741218..2fc2250fe4d 100644 --- a/test/Polly.Specs/RateLimit/AsyncRateLimitPolicyTResultSpecs.cs +++ b/test/Polly.Specs/RateLimit/AsyncRateLimitPolicyTResultSpecs.cs @@ -47,4 +47,30 @@ protected override TResult TryExecuteThroughPolicy(IRateLimitPolicy> action = null!; + IRateLimiter rateLimiter = RateLimiterFactory.Create(TimeSpan.FromSeconds(1), 1); + Func? retryAfterFactory = null!; + + var instance = Activator.CreateInstance( + typeof(AsyncRateLimitPolicy), + flags, + null, + [rateLimiter, retryAfterFactory], + null)!; + var instanceType = instance.GetType(); + var methods = instanceType.GetMethods(flags); + var methodInfo = methods.First(method => method is { Name: "ImplementationAsync", ReturnType.Name: "Task`1" }); + + var func = () => methodInfo.Invoke(instance, [action, new Context(), CancellationToken.None, false]); + + var exceptionAssertions = func.Should().Throw(); + exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation."); + exceptionAssertions.And.InnerException.Should().BeOfType() + .Which.ParamName.Should().Be("action"); + } } From 15cfcb1c5fa99f8759ecbaa08cc83297b3c15b0e Mon Sep 17 00:00:00 2001 From: Martin Costello Date: Mon, 22 Jul 2024 08:45:31 +0100 Subject: [PATCH 3/3] Adjust formatting One parameter per line. --- src/Polly/RateLimit/AsyncRateLimitPolicy.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Polly/RateLimit/AsyncRateLimitPolicy.cs b/src/Polly/RateLimit/AsyncRateLimitPolicy.cs index 858d7c6cfa4..19f49deb0ae 100644 --- a/src/Polly/RateLimit/AsyncRateLimitPolicy.cs +++ b/src/Polly/RateLimit/AsyncRateLimitPolicy.cs @@ -24,7 +24,12 @@ protected override Task ImplementationAsync( throw new ArgumentNullException(nameof(action)); } - return AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, null, action, context, continueOnCapturedContext, + return AsyncRateLimitEngine.ImplementationAsync( + _rateLimiter, + null, + action, + context, + continueOnCapturedContext, cancellationToken); } } @@ -59,7 +64,12 @@ protected override Task ImplementationAsync( throw new ArgumentNullException(nameof(action)); } - return AsyncRateLimitEngine.ImplementationAsync(_rateLimiter, _retryAfterFactory, action, context, - continueOnCapturedContext, cancellationToken); + return AsyncRateLimitEngine.ImplementationAsync( + _rateLimiter, + _retryAfterFactory, + action, + context, + continueOnCapturedContext, + cancellationToken); } }