Skip to content

Commit 6d2b4e9

Browse files
authored
Fix CA1062 warnings (#2225)
Fix warnings for `AsyncRetryPolicy`.
1 parent 80421c2 commit 6d2b4e9

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

src/Polly/Retry/AsyncRetryPolicy.cs

+18-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
/// <summary>
44
/// A retry policy that can be applied to asynchronous delegates.
55
/// </summary>
6-
#pragma warning disable CA1062 // Validate arguments of public methods
76
public class AsyncRetryPolicy : AsyncPolicy, IRetryPolicy
87
{
98
private readonly Func<Exception, TimeSpan, int, Context, Task> _onRetryAsync;
@@ -34,6 +33,11 @@ protected override Task<TResult> ImplementationAsync<TResult>(
3433
CancellationToken cancellationToken,
3534
bool continueOnCapturedContext)
3635
{
36+
if (action is null)
37+
{
38+
throw new ArgumentNullException(nameof(action));
39+
}
40+
3741
var sleepDurationProvider = _sleepDurationProvider != null
3842
? (retryCount, outcome, ctx) => _sleepDurationProvider(retryCount, outcome.Exception, ctx)
3943
: (Func<int, DelegateResult<TResult>, Context, TimeSpan>)null;
@@ -79,9 +83,18 @@ internal AsyncRetryPolicy(
7983

8084
/// <inheritdoc/>
8185
[DebuggerStepThrough]
82-
protected override Task<TResult> ImplementationAsync(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken,
83-
bool continueOnCapturedContext) =>
84-
AsyncRetryEngine.ImplementationAsync(
86+
protected override Task<TResult> ImplementationAsync(
87+
Func<Context, CancellationToken, Task<TResult>> action,
88+
Context context,
89+
CancellationToken cancellationToken,
90+
bool continueOnCapturedContext)
91+
{
92+
if (action is null)
93+
{
94+
throw new ArgumentNullException(nameof(action));
95+
}
96+
97+
return AsyncRetryEngine.ImplementationAsync(
8598
action,
8699
context,
87100
ExceptionPredicates,
@@ -92,5 +105,6 @@ protected override Task<TResult> ImplementationAsync(Func<Context, CancellationT
92105
_sleepDurationsEnumerable,
93106
_sleepDurationProvider,
94107
continueOnCapturedContext);
108+
}
95109
}
96110

test/Polly.Specs/Retry/RetryAsyncSpecs.cs

+30
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,36 @@ namespace Polly.Specs.Retry;
44

55
public class RetryAsyncSpecs
66
{
7+
[Fact]
8+
public void Should_throw_when_action_is_null()
9+
{
10+
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
11+
Func<Context, CancellationToken, Task<EmptyStruct>> action = null!;
12+
var policyBuilder = new PolicyBuilder(exception => exception);
13+
Func<Exception, TimeSpan, int, Context, Task> onRetryAsync = (_, _, _, _) => Task.CompletedTask;
14+
int permittedRetryCount = int.MaxValue;
15+
IEnumerable<TimeSpan>? sleepDurationsEnumerable = null;
16+
Func<int, Exception, Context, TimeSpan> sleepDurationProvider = null!;
17+
18+
var instance = Activator.CreateInstance(
19+
typeof(AsyncRetryPolicy),
20+
flags,
21+
null,
22+
[policyBuilder, onRetryAsync, permittedRetryCount, sleepDurationsEnumerable, sleepDurationProvider],
23+
null)!;
24+
var instanceType = instance.GetType();
25+
var methods = instanceType.GetMethods(flags);
26+
var methodInfo = methods.First(method => method is { Name: "ImplementationAsync", ReturnType.Name: "Task`1" });
27+
var generic = methodInfo.MakeGenericMethod(typeof(EmptyStruct));
28+
29+
var func = () => generic.Invoke(instance, [action, new Context(), CancellationToken.None, false]);
30+
31+
var exceptionAssertions = func.Should().Throw<TargetInvocationException>();
32+
exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation.");
33+
exceptionAssertions.And.InnerException.Should().BeOfType<ArgumentNullException>()
34+
.Which.ParamName.Should().Be("action");
35+
}
36+
737
[Fact]
838
public void Should_throw_when_retry_count_is_less_than_zero_without_context()
939
{

test/Polly.Specs/Retry/RetryTResultSpecsAsync.cs

+29
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,35 @@ namespace Polly.Specs.Retry;
44

55
public class RetryTResultSpecsAsync
66
{
7+
[Fact]
8+
public void Should_throw_when_action_is_null()
9+
{
10+
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
11+
Func<Context, CancellationToken, Task<EmptyStruct>> action = null!;
12+
var policyBuilder = new PolicyBuilder<EmptyStruct>(exception => exception);
13+
Func<DelegateResult<EmptyStruct>, TimeSpan, int, Context, Task> onRetryAsync = (_, _, _, _) => Task.CompletedTask;
14+
int permittedRetryCount = int.MaxValue;
15+
IEnumerable<TimeSpan>? sleepDurationsEnumerable = null;
16+
Func<int, DelegateResult<EmptyStruct>, Context, TimeSpan> sleepDurationProvider = null!;
17+
18+
var instance = Activator.CreateInstance(
19+
typeof(AsyncRetryPolicy<EmptyStruct>),
20+
flags,
21+
null,
22+
[policyBuilder, onRetryAsync, permittedRetryCount, sleepDurationsEnumerable, sleepDurationProvider],
23+
null)!;
24+
var instanceType = instance.GetType();
25+
var methods = instanceType.GetMethods(flags);
26+
var methodInfo = methods.First(method => method is { Name: "ImplementationAsync", ReturnType.Name: "Task`1" });
27+
28+
var func = () => methodInfo.Invoke(instance, [action, new Context(), CancellationToken.None, false]);
29+
30+
var exceptionAssertions = func.Should().Throw<TargetInvocationException>();
31+
exceptionAssertions.And.Message.Should().Be("Exception has been thrown by the target of an invocation.");
32+
exceptionAssertions.And.InnerException.Should().BeOfType<ArgumentNullException>()
33+
.Which.ParamName.Should().Be("action");
34+
}
35+
736
[Fact]
837
public void Should_throw_when_retry_count_is_less_than_zero_without_context()
938
{

0 commit comments

Comments
 (0)