diff --git a/src/Polly.Core/ResiliencePipelineBuilderExtensions.cs b/src/Polly.Core/ResiliencePipelineBuilderExtensions.cs index 0b5a4b06160..1826ad6c5af 100644 --- a/src/Polly.Core/ResiliencePipelineBuilderExtensions.cs +++ b/src/Polly.Core/ResiliencePipelineBuilderExtensions.cs @@ -147,12 +147,7 @@ public static TBuilder AddStrategy( this TBuilder builder, Func factory) where TBuilder : ResiliencePipelineBuilderBase - { - Guard.NotNull(builder); - Guard.NotNull(factory); - - return builder.AddStrategy(factory, EmptyOptions.Instance); - } + => builder.AddStrategy(factory, EmptyOptions.Instance); /// /// Adds a proactive resilience strategy to the builder. @@ -170,12 +165,7 @@ public static TBuilder AddStrategy( public static ResiliencePipelineBuilder AddStrategy( this ResiliencePipelineBuilder builder, Func> factory) - { - Guard.NotNull(builder); - Guard.NotNull(factory); - - return builder.AddStrategy(factory, EmptyOptions.Instance); - } + => builder.AddStrategy(factory, EmptyOptions.Instance); /// /// Adds a reactive resilience strategy to the builder. @@ -194,12 +184,7 @@ public static ResiliencePipelineBuilder AddStrategy( public static ResiliencePipelineBuilder AddStrategy( this ResiliencePipelineBuilder builder, Func> factory) - { - Guard.NotNull(builder); - Guard.NotNull(factory); - - return builder.AddStrategy(factory, EmptyOptions.Instance); - } + => builder.AddStrategy(factory, EmptyOptions.Instance); internal sealed class EmptyOptions : ResilienceStrategyOptions { diff --git a/src/Polly.Core/ResiliencePipelineT.Async.cs b/src/Polly.Core/ResiliencePipelineT.Async.cs index 897c603b874..fa8c2cb6cd3 100644 --- a/src/Polly.Core/ResiliencePipelineT.Async.cs +++ b/src/Polly.Core/ResiliencePipelineT.Async.cs @@ -19,12 +19,7 @@ public ValueTask ExecuteAsync( ResilienceContext context, TState state) where TResult : T - { - Guard.NotNull(callback); - Guard.NotNull(context); - - return Pipeline.ExecuteAsync(callback, context, state); - } + => Pipeline.ExecuteAsync(callback, context, state); /// /// Executes the specified callback. @@ -38,12 +33,7 @@ public ValueTask ExecuteAsync( Func> callback, ResilienceContext context) where TResult : T - { - Guard.NotNull(callback); - Guard.NotNull(context); - - return Pipeline.ExecuteAsync(callback, context); - } + => Pipeline.ExecuteAsync(callback, context); /// /// Executes the specified callback. @@ -60,11 +50,7 @@ public ValueTask ExecuteAsync( TState state, CancellationToken cancellationToken = default) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.ExecuteAsync(callback, state, cancellationToken); - } + => Pipeline.ExecuteAsync(callback, state, cancellationToken); /// /// Executes the specified callback. @@ -78,11 +64,7 @@ public ValueTask ExecuteAsync( Func> callback, CancellationToken cancellationToken = default) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.ExecuteAsync(callback, cancellationToken); - } + => Pipeline.ExecuteAsync(callback, cancellationToken); /// /// Executes the specified outcome-based callback. @@ -103,10 +85,5 @@ public ValueTask> ExecuteOutcomeAsync( ResilienceContext context, TState state) where TResult : T - { - Guard.NotNull(callback); - Guard.NotNull(context); - - return Pipeline.ExecuteOutcomeAsync(callback, context, state); - } + => Pipeline.ExecuteOutcomeAsync(callback, context, state); } diff --git a/src/Polly.Core/ResiliencePipelineT.Sync.cs b/src/Polly.Core/ResiliencePipelineT.Sync.cs index 2874630813a..04e48098547 100644 --- a/src/Polly.Core/ResiliencePipelineT.Sync.cs +++ b/src/Polly.Core/ResiliencePipelineT.Sync.cs @@ -19,12 +19,7 @@ public TResult Execute( ResilienceContext context, TState state) where TResult : T - { - Guard.NotNull(callback); - Guard.NotNull(context); - - return Pipeline.Execute(callback, context, state); - } + => Pipeline.Execute(callback, context, state); /// /// Executes the specified callback. @@ -38,12 +33,7 @@ public TResult Execute( Func callback, ResilienceContext context) where TResult : T - { - Guard.NotNull(callback); - Guard.NotNull(context); - - return Pipeline.Execute(callback, context); - } + => Pipeline.Execute(callback, context); /// /// Executes the specified callback. @@ -57,11 +47,7 @@ public TResult Execute( Func callback, CancellationToken cancellationToken = default) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.Execute(callback, cancellationToken); - } + => Pipeline.Execute(callback, cancellationToken); /// /// Executes the specified callback. @@ -72,11 +58,7 @@ public TResult Execute( /// Thrown when is . public TResult Execute(Func callback) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.Execute(callback); - } + => Pipeline.Execute(callback); /// /// Executes the specified callback. @@ -89,11 +71,7 @@ public TResult Execute(Func callback) /// Thrown when is . public TResult Execute(Func callback, TState state) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.Execute(callback, state); - } + => Pipeline.Execute(callback, state); /// /// Executes the specified callback. @@ -110,9 +88,5 @@ public TResult Execute( TState state, CancellationToken cancellationToken = default) where TResult : T - { - Guard.NotNull(callback); - - return Pipeline.Execute(callback, state, cancellationToken); - } + => Pipeline.Execute(callback, state, cancellationToken); } diff --git a/src/Polly.Core/Telemetry/TelemetryUtil.cs b/src/Polly.Core/Telemetry/TelemetryUtil.cs index 18d83777064..8da5902503b 100644 --- a/src/Polly.Core/Telemetry/TelemetryUtil.cs +++ b/src/Polly.Core/Telemetry/TelemetryUtil.cs @@ -49,11 +49,9 @@ private static void ReportAttempt( Outcome outcome, ExecutionAttemptArguments args) { - if (!telemetry.Enabled) + if (telemetry.Enabled) { - return; + telemetry.Report(resilienceEvent, context, outcome, args); } - - telemetry.Report(resilienceEvent, context, outcome, args); } } diff --git a/src/Polly.Core/Timeout/TimeoutResiliencePipelineBuilderExtensions.cs b/src/Polly.Core/Timeout/TimeoutResiliencePipelineBuilderExtensions.cs index 2c97afe0864..0a75b890d36 100644 --- a/src/Polly.Core/Timeout/TimeoutResiliencePipelineBuilderExtensions.cs +++ b/src/Polly.Core/Timeout/TimeoutResiliencePipelineBuilderExtensions.cs @@ -20,14 +20,10 @@ public static class TimeoutResiliencePipelineBuilderExtensions /// Thrown when the options produced from the arguments are invalid. public static TBuilder AddTimeout(this TBuilder builder, TimeSpan timeout) where TBuilder : ResiliencePipelineBuilderBase - { - Guard.NotNull(builder); - - return builder.AddTimeout(new TimeoutStrategyOptions + => builder.AddTimeout(new TimeoutStrategyOptions { Timeout = timeout }); - } /// /// Adds a timeout to the builder. diff --git a/src/Polly.Extensions/DependencyInjection/AddResiliencePipelineContext.cs b/src/Polly.Extensions/DependencyInjection/AddResiliencePipelineContext.cs index a7b6ffe3729..c3b77fa4075 100644 --- a/src/Polly.Extensions/DependencyInjection/AddResiliencePipelineContext.cs +++ b/src/Polly.Extensions/DependencyInjection/AddResiliencePipelineContext.cs @@ -2,7 +2,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Polly.Registry; -using Polly.Utils; namespace Polly.DependencyInjection; @@ -69,9 +68,5 @@ internal AddResiliencePipelineContext(ConfigureBuilderContext registryCont /// /// The callback delegate. public void OnPipelineDisposed(Action callback) - { - Guard.NotNull(callback); - - RegistryContext.OnPipelineDisposed(callback); - } + => RegistryContext.OnPipelineDisposed(callback); } diff --git a/src/Polly.Extensions/Telemetry/TelemetryListenerImpl.cs b/src/Polly.Extensions/Telemetry/TelemetryListenerImpl.cs index 0d5c50a3d0e..90a87855ae3 100644 --- a/src/Polly.Extensions/Telemetry/TelemetryListenerImpl.cs +++ b/src/Polly.Extensions/Telemetry/TelemetryListenerImpl.cs @@ -117,31 +117,27 @@ private void MeterEvent(in TelemetryEventArguments(args.Arguments, out var executionFinished)) { - if (!ExecutionDuration.Enabled) + if (ExecutionDuration.Enabled) { - return; + var tags = TagsList.Get(); + var context = new EnrichmentContext(in args, tags.Tags); + UpdateEnrichmentContext(in context, severity); + ExecutionDuration.Record(executionFinished.Duration.TotalMilliseconds, tags.TagsSpan); + TagsList.Return(tags); } - - var tags = TagsList.Get(); - var context = new EnrichmentContext(in args, tags.Tags); - UpdateEnrichmentContext(in context, severity); - ExecutionDuration.Record(executionFinished.Duration.TotalMilliseconds, tags.TagsSpan); - TagsList.Return(tags); } else if (GetArgs(args.Arguments, out var executionAttempt)) { - if (!AttemptDuration.Enabled) + if (AttemptDuration.Enabled) { - return; + var tags = TagsList.Get(); + var context = new EnrichmentContext(in args, tags.Tags); + UpdateEnrichmentContext(in context, severity); + context.Tags.Add(new(ResilienceTelemetryTags.AttemptNumber, executionAttempt.AttemptNumber.AsBoxedInt())); + context.Tags.Add(new(ResilienceTelemetryTags.AttemptHandled, executionAttempt.Handled.AsBoxedBool())); + AttemptDuration.Record(executionAttempt.Duration.TotalMilliseconds, tags.TagsSpan); + TagsList.Return(tags); } - - var tags = TagsList.Get(); - var context = new EnrichmentContext(in args, tags.Tags); - UpdateEnrichmentContext(in context, severity); - context.Tags.Add(new(ResilienceTelemetryTags.AttemptNumber, executionAttempt.AttemptNumber.AsBoxedInt())); - context.Tags.Add(new(ResilienceTelemetryTags.AttemptHandled, executionAttempt.Handled.AsBoxedBool())); - AttemptDuration.Record(executionAttempt.Duration.TotalMilliseconds, tags.TagsSpan); - TagsList.Return(tags); } else if (Counter.Enabled) { diff --git a/src/Polly.RateLimiting/RateLimiterResiliencePipelineBuilderExtensions.cs b/src/Polly.RateLimiting/RateLimiterResiliencePipelineBuilderExtensions.cs index 1006684bb10..d81efa31f94 100644 --- a/src/Polly.RateLimiting/RateLimiterResiliencePipelineBuilderExtensions.cs +++ b/src/Polly.RateLimiting/RateLimiterResiliencePipelineBuilderExtensions.cs @@ -27,8 +27,6 @@ public static TBuilder AddConcurrencyLimiter( int queueLimit = 0) where TBuilder : ResiliencePipelineBuilderBase { - Guard.NotNull(builder); - return builder.AddConcurrencyLimiter(new ConcurrencyLimiterOptions { PermitLimit = permitLimit, diff --git a/src/Polly/Caching/CacheSyntax.cs b/src/Polly/Caching/CacheSyntax.cs index fc275845184..aa5c5e5f79c 100644 --- a/src/Polly/Caching/CacheSyntax.cs +++ b/src/Polly/Caching/CacheSyntax.cs @@ -124,24 +124,7 @@ public static CachePolicy Cache(ISyncCacheProvider cacheProvider, TimeSpan ttl, /// Thrown when is . /// Thrown when is . public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func cacheKeyStrategy, Action? onCacheError = null) - { - if (cacheProvider == null) - { - throw new ArgumentNullException(nameof(cacheProvider)); - } - - if (ttlStrategy == null) - { - throw new ArgumentNullException(nameof(ttlStrategy)); - } - - if (cacheKeyStrategy == null) - { - throw new ArgumentNullException(nameof(cacheKeyStrategy)); - } - - return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy, EmptyCallback, EmptyCallback, EmptyCallback, onCacheError, onCacheError); - } + => Cache(cacheProvider, ttlStrategy, cacheKeyStrategy, EmptyCallback, EmptyCallback, EmptyCallback, onCacheError, onCacheError); /// /// Builds a that will function like a result cache for delegate executions returning a result. diff --git a/src/Polly/CircuitBreaker/AdvancedCircuitBreakerTResultSyntax.cs b/src/Polly/CircuitBreaker/AdvancedCircuitBreakerTResultSyntax.cs index 5b521b5a0f7..31ff8da264b 100644 --- a/src/Polly/CircuitBreaker/AdvancedCircuitBreakerTResultSyntax.cs +++ b/src/Polly/CircuitBreaker/AdvancedCircuitBreakerTResultSyntax.cs @@ -29,17 +29,12 @@ public static class AdvancedCircuitBreakerTResultSyntax /// minimumThroughput;Value must be greater than one. /// durationOfBreak;Value must be greater than zero. /// (see "Release It!" by Michael T. Nygard fi). - public static CircuitBreakerPolicy AdvancedCircuitBreaker(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak) - { - Action, TimeSpan> doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.AdvancedCircuitBreaker( + public static CircuitBreakerPolicy AdvancedCircuitBreaker(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak) => + policyBuilder.AdvancedCircuitBreaker( failureThreshold, samplingDuration, minimumThroughput, durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + static (_, _) => { }, + static () => { }); /// /// The circuit will break if, within any timeslice of duration , the proportion of actions resulting in a handled exception or result exceeds , provided also that the number of actions through the circuit in the timeslice is at least . @@ -102,15 +97,14 @@ public static CircuitBreakerPolicy AdvancedCircuitBreaker(this /// durationOfBreak;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static CircuitBreakerPolicy AdvancedCircuitBreaker(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - return policyBuilder.AdvancedCircuitBreaker(failureThreshold, samplingDuration, minimumThroughput, + public static CircuitBreakerPolicy AdvancedCircuitBreaker(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) => + policyBuilder.AdvancedCircuitBreaker( + failureThreshold, + samplingDuration, minimumThroughput, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + static () => { }); /// /// The circuit will break if, within any timeslice of duration , the proportion of actions resulting in a handled exception or result exceeds , provided also that the number of actions through the circuit in the timeslice is at least . diff --git a/src/Polly/CircuitBreaker/AsyncAdvancedCircuitBreakerTResultSyntax.cs b/src/Polly/CircuitBreaker/AsyncAdvancedCircuitBreakerTResultSyntax.cs index 7d4b43f6ebe..4dba8f4e848 100644 --- a/src/Polly/CircuitBreaker/AsyncAdvancedCircuitBreakerTResultSyntax.cs +++ b/src/Polly/CircuitBreaker/AsyncAdvancedCircuitBreakerTResultSyntax.cs @@ -29,17 +29,12 @@ public static class AsyncAdvancedCircuitBreakerTResultSyntax /// samplingDuration;Value must be equal to or greater than the minimum resolution of the CircuitBreaker timer. /// minimumThroughput;Value must be greater than one. /// durationOfBreak;Value must be greater than zero. - public static AsyncCircuitBreakerPolicy AdvancedCircuitBreakerAsync(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak) - { - Action, TimeSpan> doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.AdvancedCircuitBreakerAsync( + public static AsyncCircuitBreakerPolicy AdvancedCircuitBreakerAsync(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak) => + policyBuilder.AdvancedCircuitBreakerAsync( failureThreshold, samplingDuration, minimumThroughput, durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + static (_, _) => { }, + static () => { }); /// /// Builds a that will function like a Circuit Breaker. @@ -104,17 +99,13 @@ public static AsyncCircuitBreakerPolicy AdvancedCircuitBreakerAsyncdurationOfBreak;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static AsyncCircuitBreakerPolicy AdvancedCircuitBreakerAsync(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - - return policyBuilder.AdvancedCircuitBreakerAsync( + public static AsyncCircuitBreakerPolicy AdvancedCircuitBreakerAsync(this PolicyBuilder policyBuilder, double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) => + policyBuilder.AdvancedCircuitBreakerAsync( failureThreshold, samplingDuration, minimumThroughput, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + static () => { }); /// /// Builds a that will function like a Circuit Breaker. diff --git a/src/Polly/CircuitBreaker/AsyncCircuitBreakerSyntax.cs b/src/Polly/CircuitBreaker/AsyncCircuitBreakerSyntax.cs index 8869618ce95..1e1abdace88 100644 --- a/src/Polly/CircuitBreaker/AsyncCircuitBreakerSyntax.cs +++ b/src/Polly/CircuitBreaker/AsyncCircuitBreakerSyntax.cs @@ -23,17 +23,12 @@ public static class AsyncCircuitBreakerSyntax /// The policy instance. /// (see "Release It!" by Michael T. Nygard fi). /// exceptionsAllowedBeforeBreaking;Value must be greater than zero. - public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak) - { - Action doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.CircuitBreakerAsync( - exceptionsAllowedBeforeBreaking, - durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak) => + policyBuilder.CircuitBreakerAsync( + exceptionsAllowedBeforeBreaking, + durationOfBreak, + static (_, _) => { }, + static () => { }); /// /// Builds a that will function like a Circuit Breaker. @@ -86,17 +81,13 @@ public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder p /// exceptionsAllowedBeforeBreaking;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - - return policyBuilder.CircuitBreakerAsync( + public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action onBreak, Action onReset) => + policyBuilder.CircuitBreakerAsync( exceptionsAllowedBeforeBreaking, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + static () => { }); /// /// Builds a that will function like a Circuit Breaker. diff --git a/src/Polly/CircuitBreaker/AsyncCircuitBreakerTResultSyntax.cs b/src/Polly/CircuitBreaker/AsyncCircuitBreakerTResultSyntax.cs index 08b164941be..114770a9a28 100644 --- a/src/Polly/CircuitBreaker/AsyncCircuitBreakerTResultSyntax.cs +++ b/src/Polly/CircuitBreaker/AsyncCircuitBreakerTResultSyntax.cs @@ -24,17 +24,12 @@ public static class AsyncCircuitBreakerTResultSyntax /// The policy instance. /// (see "Release It!" by Michael T. Nygard fi). /// handledEventsAllowedBeforeBreaking;Value must be greater than zero. - public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak) - { - Action, TimeSpan> doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.CircuitBreakerAsync( - handledEventsAllowedBeforeBreaking, - durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak) => + policyBuilder.CircuitBreakerAsync( + handledEventsAllowedBeforeBreaking, + durationOfBreak, + static (_, _) => { }, + static () => { }); /// /// Builds a that will function like a Circuit Breaker. @@ -89,17 +84,13 @@ public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(th /// handledEventsAllowedBeforeBreaking;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - - return policyBuilder.CircuitBreakerAsync( + public static AsyncCircuitBreakerPolicy CircuitBreakerAsync(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) => + policyBuilder.CircuitBreakerAsync( handledEventsAllowedBeforeBreaking, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + static () => { }); /// /// Builds a that will function like a Circuit Breaker. diff --git a/src/Polly/CircuitBreaker/CircuitBreakerSyntax.cs b/src/Polly/CircuitBreaker/CircuitBreakerSyntax.cs index aa8a4afe319..87c4ca70979 100644 --- a/src/Polly/CircuitBreaker/CircuitBreakerSyntax.cs +++ b/src/Polly/CircuitBreaker/CircuitBreakerSyntax.cs @@ -23,17 +23,12 @@ public static class CircuitBreakerSyntax /// The policy instance. /// (see "Release It!" by Michael T. Nygard fi). /// exceptionsAllowedBeforeBreaking;Value must be greater than zero. - public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak) - { - Action doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.CircuitBreaker( + public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak) => + policyBuilder.CircuitBreaker( exceptionsAllowedBeforeBreaking, durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + static (_, _) => { }, + static () => { }); /// /// Builds a that will function like a Circuit Breaker. @@ -86,16 +81,12 @@ public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuild /// exceptionsAllowedBeforeBreaking;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - - return policyBuilder.CircuitBreaker(exceptionsAllowedBeforeBreaking, + public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int exceptionsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action onBreak, Action onReset) => + policyBuilder.CircuitBreaker(exceptionsAllowedBeforeBreaking, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + static () => { }); /// /// Builds a that will function like a Circuit Breaker. diff --git a/src/Polly/CircuitBreaker/CircuitBreakerTResultSyntax.cs b/src/Polly/CircuitBreaker/CircuitBreakerTResultSyntax.cs index 6cdfde61ffd..3e8987b1454 100644 --- a/src/Polly/CircuitBreaker/CircuitBreakerTResultSyntax.cs +++ b/src/Polly/CircuitBreaker/CircuitBreakerTResultSyntax.cs @@ -24,17 +24,12 @@ public static class CircuitBreakerTResultSyntax /// The policy instance. /// (see "Release It!" by Michael T. Nygard fi). /// handledEventsAllowedBeforeBreaking;Value must be greater than zero. - public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak) - { - Action, TimeSpan> doNothingOnBreak = (_, _) => { }; - Action doNothingOnReset = () => { }; - - return policyBuilder.CircuitBreaker( + public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak) => + policyBuilder.CircuitBreaker( handledEventsAllowedBeforeBreaking, durationOfBreak, - doNothingOnBreak, - doNothingOnReset); - } + static (_, _) => { }, + static () => { }); /// /// Builds a that will function like a Circuit Breaker. @@ -89,16 +84,12 @@ public static CircuitBreakerPolicy CircuitBreaker(this PolicyB /// handledEventsAllowedBeforeBreaking;Value must be greater than zero. /// Thrown when is . /// Thrown when is . - public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) - { - Action doNothingOnHalfOpen = () => { }; - - return policyBuilder.CircuitBreaker(handledEventsAllowedBeforeBreaking, + public static CircuitBreakerPolicy CircuitBreaker(this PolicyBuilder policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action, TimeSpan, Context> onBreak, Action onReset) => + policyBuilder.CircuitBreaker(handledEventsAllowedBeforeBreaking, durationOfBreak, onBreak, onReset, - doNothingOnHalfOpen); - } + EmptyCallback); /// /// Builds a that will function like a Circuit Breaker. @@ -228,4 +219,9 @@ public static CircuitBreakerPolicy CircuitBreaker(this PolicyB policyBuilder, breakerController); } + + private static void EmptyCallback() + { + // No-op + } } diff --git a/src/Polly/Fallback/AsyncFallbackSyntax.cs b/src/Polly/Fallback/AsyncFallbackSyntax.cs index b4c5fcb24ff..7b3507c0bf2 100644 --- a/src/Polly/Fallback/AsyncFallbackSyntax.cs +++ b/src/Polly/Fallback/AsyncFallbackSyntax.cs @@ -58,11 +58,6 @@ public static AsyncFallbackPolicy FallbackAsync(this PolicyBuilder policyBuilder throw new ArgumentNullException(nameof(fallbackAction)); } - if (onFallbackAsync == null) - { - throw new ArgumentNullException(nameof(onFallbackAsync)); - } - return policyBuilder.FallbackAsync((_, ctx, ct) => fallbackAction(ctx, ct), onFallbackAsync); } @@ -203,11 +198,6 @@ public static AsyncFallbackPolicy FallbackAsync(this PolicyBui throw new ArgumentNullException(nameof(fallbackAction)); } - if (onFallbackAsync == null) - { - throw new ArgumentNullException(nameof(onFallbackAsync)); - } - return policyBuilder.FallbackAsync((_, ctx, ct) => fallbackAction(ctx, ct), onFallbackAsync); } diff --git a/src/Polly/Fallback/FallbackSyntax.cs b/src/Polly/Fallback/FallbackSyntax.cs index 616f291930b..c3685fc8846 100644 --- a/src/Polly/Fallback/FallbackSyntax.cs +++ b/src/Polly/Fallback/FallbackSyntax.cs @@ -90,11 +90,6 @@ public static FallbackPolicy Fallback(this PolicyBuilder policyBuilder, Action fallbackAction(ctx), onFallback); } @@ -114,11 +109,6 @@ public static FallbackPolicy Fallback(this PolicyBuilder policyBuilder, Action fallbackAction(ctx, ct), onFallback); } @@ -297,11 +287,6 @@ public static FallbackPolicy Fallback(this PolicyBuilder fallbackAction(ctx), onFallback); } @@ -322,11 +307,6 @@ public static FallbackPolicy Fallback(this PolicyBuilder fallbackAction(ctx, ct), onFallback); } diff --git a/src/Polly/Retry/AsyncRetrySyntax.cs b/src/Polly/Retry/AsyncRetrySyntax.cs index e3182973aed..63b1f16f753 100644 --- a/src/Polly/Retry/AsyncRetrySyntax.cs +++ b/src/Polly/Retry/AsyncRetrySyntax.cs @@ -495,8 +495,11 @@ public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilde /// The policy instance. /// retryCount;Value must be greater than or equal to zero. /// Thrown when or is . - public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, int retryCount, - Func sleepDurationProvider, Func onRetryAsync) + public static AsyncRetryPolicy WaitAndRetryAsync( + this PolicyBuilder policyBuilder, + int retryCount, + Func sleepDurationProvider, + Func onRetryAsync) { if (retryCount < 0) { @@ -508,11 +511,6 @@ public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilde throw new ArgumentNullException(nameof(sleepDurationProvider)); } - if (onRetryAsync == null) - { - throw new ArgumentNullException(nameof(onRetryAsync)); - } - IEnumerable sleepDurations = Enumerable.Range(1, retryCount) .Select(sleepDurationProvider); @@ -536,8 +534,11 @@ public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilde /// The policy instance. /// retryCount;Value must be greater than or equal to zero. /// Thrown when or is . - public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, int retryCount, - Func sleepDurationProvider, Action onRetry) + public static AsyncRetryPolicy WaitAndRetryAsync( + this PolicyBuilder policyBuilder, + int retryCount, + Func sleepDurationProvider, + Action onRetry) { if (onRetry == null) { @@ -565,8 +566,11 @@ public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilde /// The policy instance. /// retryCount;Value must be greater than or equal to zero. /// Thrown when or is . - public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, int retryCount, - Func sleepDurationProvider, Func onRetryAsync) + public static AsyncRetryPolicy WaitAndRetryAsync( + this PolicyBuilder policyBuilder, + int retryCount, + Func sleepDurationProvider, + Func onRetryAsync) { if (onRetryAsync == null) { @@ -620,8 +624,11 @@ public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilde /// The policy instance. /// retryCount;Value must be greater than or equal to zero. /// Thrown when or is . - public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, int retryCount, - Func sleepDurationProvider, Func onRetryAsync) + public static AsyncRetryPolicy WaitAndRetryAsync( + this PolicyBuilder policyBuilder, + int retryCount, + Func sleepDurationProvider, + Func onRetryAsync) { if (sleepDurationProvider == null) { @@ -943,8 +950,8 @@ public static AsyncRetryPolicy WaitAndRetryForeverAsync(this PolicyBuilder polic } return policyBuilder.WaitAndRetryForeverAsync( - (retryCount, _) => sleepDurationProvider(retryCount), - (exception, timespan, _) => onRetryAsync(exception, timespan)); + (retryCount, _) => sleepDurationProvider(retryCount), + (exception, timespan, _) => onRetryAsync(exception, timespan)); } /// diff --git a/src/Polly/Timeout/AsyncTimeoutSyntax.cs b/src/Polly/Timeout/AsyncTimeoutSyntax.cs index eebee5757b1..373731be6ac 100644 --- a/src/Polly/Timeout/AsyncTimeoutSyntax.cs +++ b/src/Polly/Timeout/AsyncTimeoutSyntax.cs @@ -11,9 +11,7 @@ public partial class Policy public static AsyncTimeoutPolicy TimeoutAsync(int seconds) { TimeoutValidator.ValidateSecondsTimeout(seconds); - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, EmptyHandlerAsync); } /// @@ -26,9 +24,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds) public static AsyncTimeoutPolicy TimeoutAsync(int seconds, TimeoutStrategy timeoutStrategy) { TimeoutValidator.ValidateSecondsTimeout(seconds); - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), timeoutStrategy, EmptyHandlerAsync); } /// @@ -43,11 +39,6 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds, TimeoutStrategy timeo public static AsyncTimeoutPolicy TimeoutAsync(int seconds, Func onTimeoutAsync) { TimeoutValidator.ValidateSecondsTimeout(seconds); - if (onTimeoutAsync == null) - { - throw new ArgumentNullException(nameof(onTimeoutAsync)); - } - return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, onTimeoutAsync); } @@ -67,11 +58,6 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds, Func TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, onTimeoutAsync); } @@ -121,9 +107,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds, TimeoutStrategy timeo public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout) { TimeoutValidator.ValidateTimeSpanTimeout(timeout); - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, EmptyHandlerAsync); } /// @@ -136,9 +120,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout) public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout, TimeoutStrategy timeoutStrategy) { TimeoutValidator.ValidateTimeSpanTimeout(timeout); - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(_ => timeout, timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => timeout, timeoutStrategy, EmptyHandlerAsync); } /// @@ -220,8 +202,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider) throw new ArgumentNullException(nameof(timeoutProvider)); } - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - return TimeoutAsync(_ => timeoutProvider(), TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => timeoutProvider(), TimeoutStrategy.Optimistic, EmptyHandlerAsync); } /// @@ -238,8 +219,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider, Ti throw new ArgumentNullException(nameof(timeoutProvider)); } - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - return TimeoutAsync(_ => timeoutProvider(), timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => timeoutProvider(), timeoutStrategy, EmptyHandlerAsync); } /// @@ -327,11 +307,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider, Ti /// Thrown when is . /// The policy instance. public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider) - { - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(timeoutProvider, TimeoutStrategy.Optimistic, doNothingAsync); - } + => TimeoutAsync(timeoutProvider, TimeoutStrategy.Optimistic, EmptyHandlerAsync); /// /// Builds an that will wait asynchronously for a delegate to complete for a specified period of time. A will be thrown if the delegate does not complete within the configured timeout. @@ -341,11 +317,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutPro /// The policy instance. /// Thrown when is . public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider, TimeoutStrategy timeoutStrategy) - { - Func doNothingAsync = (_, _, _, _) => TaskHelper.EmptyTask; - - return TimeoutAsync(timeoutProvider, timeoutStrategy, doNothingAsync); - } + => TimeoutAsync(timeoutProvider, timeoutStrategy, EmptyHandlerAsync); /// /// Builds an that will wait asynchronously for a delegate to complete for a specified period of time. A will be thrown if the delegate does not complete within the configured timeout. @@ -421,4 +393,7 @@ public static AsyncTimeoutPolicy TimeoutAsync( timeoutStrategy, onTimeoutAsync); } + + private static Task EmptyHandlerAsync(Context context, TimeSpan timeout, Task task, Exception exception) + => TaskHelper.EmptyTask; } diff --git a/src/Polly/Timeout/AsyncTimeoutTResultSyntax.cs b/src/Polly/Timeout/AsyncTimeoutTResultSyntax.cs index 7e9bbc34a4b..55a8c9e2276 100644 --- a/src/Polly/Timeout/AsyncTimeoutTResultSyntax.cs +++ b/src/Polly/Timeout/AsyncTimeoutTResultSyntax.cs @@ -12,9 +12,7 @@ public partial class Policy public static AsyncTimeoutPolicy TimeoutAsync(int seconds) { TimeoutValidator.ValidateSecondsTimeout(seconds); - - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), TimeoutStrategy.Optimistic, EmptyHandlerOfT); } /// @@ -28,9 +26,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds) public static AsyncTimeoutPolicy TimeoutAsync(int seconds, TimeoutStrategy timeoutStrategy) { TimeoutValidator.ValidateSecondsTimeout(seconds); - - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => TimeSpan.FromSeconds(seconds), timeoutStrategy, EmptyHandlerOfT); } /// @@ -119,9 +115,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(int seconds, Tim public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout) { TimeoutValidator.ValidateTimeSpanTimeout(timeout); - - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, EmptyHandlerOfT); } /// @@ -135,9 +129,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout, TimeoutStrategy timeoutStrategy) { TimeoutValidator.ValidateTimeSpanTimeout(timeout); - - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => timeout, timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => timeout, timeoutStrategy, EmptyHandlerOfT); } /// @@ -153,11 +145,6 @@ public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout, Func onTimeoutAsync) { TimeoutValidator.ValidateTimeSpanTimeout(timeout); - if (onTimeoutAsync == null) - { - throw new ArgumentNullException(nameof(onTimeoutAsync)); - } - return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, onTimeoutAsync); } @@ -178,11 +165,6 @@ public static AsyncTimeoutPolicy TimeoutAsync(TimeSpan timeout throw new ArgumentOutOfRangeException(nameof(timeout)); } - if (onTimeoutAsync == null) - { - throw new ArgumentNullException(nameof(onTimeoutAsync)); - } - return TimeoutAsync(_ => timeout, TimeoutStrategy.Optimistic, onTimeoutAsync); } @@ -238,8 +220,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func t throw new ArgumentNullException(nameof(timeoutProvider)); } - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => timeoutProvider(), TimeoutStrategy.Optimistic, doNothingAsync); + return TimeoutAsync(_ => timeoutProvider(), TimeoutStrategy.Optimistic, EmptyHandlerOfT); } /// @@ -257,8 +238,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func t throw new ArgumentNullException(nameof(timeoutProvider)); } - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(_ => timeoutProvider(), timeoutStrategy, doNothingAsync); + return TimeoutAsync(_ => timeoutProvider(), timeoutStrategy, EmptyHandlerOfT); } /// @@ -351,10 +331,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func t /// Thrown when is . /// The policy instance. public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider) - { - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(timeoutProvider, TimeoutStrategy.Optimistic, doNothingAsync); - } + => TimeoutAsync(timeoutProvider, TimeoutStrategy.Optimistic, EmptyHandlerOfT); /// /// Builds an that will wait asynchronously for a delegate to complete for a specified period of time. A will be thrown if the delegate does not complete within the configured timeout. @@ -365,10 +342,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(FuncThrown when is . /// The policy instance. public static AsyncTimeoutPolicy TimeoutAsync(Func timeoutProvider, TimeoutStrategy timeoutStrategy) - { - Func doNothingAsync = (_, _, _, _) => Task.FromResult(default(TResult)); - return TimeoutAsync(timeoutProvider, timeoutStrategy, doNothingAsync); - } + => TimeoutAsync(timeoutProvider, timeoutStrategy, EmptyHandlerOfT); /// /// Builds an that will wait asynchronously for a delegate to complete for a specified period of time. A will be thrown if the delegate does not complete within the configured timeout. @@ -445,4 +419,7 @@ public static AsyncTimeoutPolicy TimeoutAsync(Func(Context context, TimeSpan timeout, Task action, Exception exception) + => Task.FromResult(default(T)); } diff --git a/test/Polly.Core.Tests/OutcomeTests.cs b/test/Polly.Core.Tests/OutcomeTests.cs index 3a35539645c..c2a3ccbb8eb 100644 --- a/test/Polly.Core.Tests/OutcomeTests.cs +++ b/test/Polly.Core.Tests/OutcomeTests.cs @@ -60,4 +60,12 @@ public void EnsureSuccess_Exception() Should.Throw(outcome.ThrowIfException); } + + [Fact] + public void FromException_Throws_If_Null() => + Assert.Throws("exception", () => Outcome.FromException(null!)); + + [Fact] + public async Task FromExceptionAsValueTask_Throws_If_Null() => + await Assert.ThrowsAsync("exception", async () => await Outcome.FromExceptionAsValueTask(null!)); } diff --git a/test/Polly.Core.Tests/PredicateBuilderTests.cs b/test/Polly.Core.Tests/PredicateBuilderTests.cs index 463e5237f0b..d12f4098916 100644 --- a/test/Polly.Core.Tests/PredicateBuilderTests.cs +++ b/test/Polly.Core.Tests/PredicateBuilderTests.cs @@ -136,6 +136,39 @@ public async Task Operator_AdvancedCircuitBreakerStrategyOptions_Ok() handled.ShouldBeTrue(); } + [Fact] + public void Handle_Throws_If_Predicate_Null() + { + var builder = new PredicateBuilder(); + Assert.Throws("predicate", () => builder.Handle(null!)); + + var builderGeneric = new PredicateBuilder(); + Assert.Throws("predicate", () => builderGeneric.HandleInner(null!)); + } + + [Fact] + public void HandleInner_Throws_If_Predicate_Null() + { + var builder = new PredicateBuilder(); + var builderGeneric = new PredicateBuilder(); + + Assert.Throws("predicate", () => builder.HandleInner(null!)); + Assert.Throws("predicate", () => builderGeneric.HandleInner(null!)); + } + + [Fact] + public void Operators_Throw_If_Builder_Null() + { + PredicateBuilder builder = null!; + + Assert.Throws("builder", () => Cast>(builder)); + Assert.Throws("builder", () => Cast>(builder)); + Assert.Throws("builder", () => Cast>(builder)); + Assert.Throws("builder", () => Cast>(builder)); + + static Func> Cast(Func> self) => self; + } + private static Outcome CreateOutcome(Exception exception) => Outcome.FromException(exception); diff --git a/test/Polly.Core.Tests/ResiliencePipelineTTests.Sync.cs b/test/Polly.Core.Tests/ResiliencePipelineTTests.Sync.cs index 465ec1969cc..511632cd494 100644 --- a/test/Polly.Core.Tests/ResiliencePipelineTTests.Sync.cs +++ b/test/Polly.Core.Tests/ResiliencePipelineTTests.Sync.cs @@ -93,4 +93,51 @@ public void Execute_GenericStrategy_Ok(Action> execut execute(pipeline); } + + [Fact] + public void Execute_GenericStrategy_NullArgument_Throws() + { + var pipeline = new ResiliencePipeline(PipelineComponentFactory.FromStrategy(new TestResilienceStrategy()), DisposeBehavior.Allow, null); + var context = new ResilienceContext(); + + Assert.Throws("callback", () => pipeline.Execute(null!)); + Assert.Throws("callback", () => pipeline.Execute(null!, context)); + Assert.Throws("callback", () => pipeline.Execute(null!, context, string.Empty)); + Assert.Throws("context", () => pipeline.Execute((_) => string.Empty, null!)); + Assert.Throws("context", () => pipeline.Execute((_, _) => string.Empty, null!, string.Empty)); + } + + [Fact] + public async Task ExecuteAsync_GenericStrategy_NullArgument_Throws() + { + var pipeline = new ResiliencePipeline(PipelineComponentFactory.FromStrategy(new TestResilienceStrategy()), DisposeBehavior.Allow, null); + var context = new ResilienceContext(); + + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!)); + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!, context)); + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!, context, string.Empty)); + } + + [Fact] + public void Execute_Strategy_NullArgument_Throws() + { + var pipeline = new ResiliencePipeline(PipelineComponentFactory.FromStrategy(new TestResilienceStrategy()), DisposeBehavior.Allow, null); + var context = new ResilienceContext(); + + Assert.Throws("callback", () => pipeline.Execute(null!)); + Assert.Throws("callback", () => pipeline.Execute(null!, context)); + Assert.Throws("context", () => pipeline.Execute((_) => string.Empty, null!)); + Assert.Throws("context", () => pipeline.Execute((_, _) => string.Empty, null!, string.Empty)); + } + + [Fact] + public async Task ExecuteAsync_Strategy_NullArgument_Throws() + { + var pipeline = new ResiliencePipeline(PipelineComponentFactory.FromStrategy(new TestResilienceStrategy()), DisposeBehavior.Allow, null); + var context = new ResilienceContext(); + + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!)); + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!, context)); + await Assert.ThrowsAsync("callback", async () => await pipeline.ExecuteAsync(null!, context, string.Empty)); + } } diff --git a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs index a3908bffd2e..e57866808be 100644 --- a/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs +++ b/test/Polly.Core.Tests/Telemetry/ResilienceStrategyTelemetryTests.cs @@ -112,4 +112,12 @@ public void SetTelemetrySource_ShouldThrow() Should.Throw(() => _sut.SetTelemetrySource(exception!)); } + + [Fact] + public void Report_ShouldThrow() + { + ResilienceEvent resilienceEvent = default; + + Assert.Throws("context", () => _sut.Report(resilienceEvent, null!, string.Empty)); + } } diff --git a/test/Polly.Core.Tests/Utils/LegacySupportTests.cs b/test/Polly.Core.Tests/Utils/LegacySupportTests.cs index d2dad52cbc9..d413d5ed5e5 100644 --- a/test/Polly.Core.Tests/Utils/LegacySupportTests.cs +++ b/test/Polly.Core.Tests/Utils/LegacySupportTests.cs @@ -14,4 +14,16 @@ public void SetProperties_Ok() resilienceProperties.Options.ShouldBeSameAs(newProps); oldProperties2.ShouldBeSameAs(oldProps); } + + [Fact] + public void SetProperties_Throws_Arguments_Null() + { + var resilienceProperties = new ResilienceProperties(); + + Assert.Throws("properties", () => resilienceProperties.SetProperties(null!, out _)); + + resilienceProperties = null!; + + Assert.Throws("resilienceProperties", () => resilienceProperties.SetProperties(new Dictionary(), out _)); + } } diff --git a/test/Polly.Extensions.Tests/DependencyInjection/PollyServiceCollectionExtensionTests.cs b/test/Polly.Extensions.Tests/DependencyInjection/PollyServiceCollectionExtensionTests.cs index 9b8ee3eb652..316db8661e0 100644 --- a/test/Polly.Extensions.Tests/DependencyInjection/PollyServiceCollectionExtensionTests.cs +++ b/test/Polly.Extensions.Tests/DependencyInjection/PollyServiceCollectionExtensionTests.cs @@ -344,6 +344,13 @@ public void AddResiliencePipeline_EnsureTimeProvider(bool timeProviderRegistered asserted.ShouldBeTrue(); } + [Fact] + public void AddResiliencePipelineRegistry_Throws_If_Services_Null() + { + ServiceCollection serviceCollection = null!; + Assert.Throws("services", () => serviceCollection.AddResiliencePipelineRegistry()); + } + [Fact] public void AddResiliencePipelineRegistry_Ok() { diff --git a/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerAsyncSpecs.cs b/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerAsyncSpecs.cs index 3a0e07ebe75..e2ffbdda6a3 100644 --- a/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerAsyncSpecs.cs +++ b/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerAsyncSpecs.cs @@ -3094,6 +3094,36 @@ public void Should_throw_if_delegates_are_null() Should.Throw(action).ParamName.ShouldBe("onHalfOpen"); } + [Fact] + public void Should_not_throw_if_arguments_are_valid() + { + double failureThreshold = 1; + var samplingDuration = TimeSpan.FromMinutes(1); + int mimimumThroughput = 60; + var breakDuration = TimeSpan.FromSeconds(1); + + var builder = Policy.Handle(); + var builderOfT = Policy.HandleResult(ResultPrimitive.Fault); + + Action action = () => builderOfT.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _) => { }, () => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _) => { }, (_) => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _) => { }, () => { }, () => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _) => { }, (_) => { }, () => { }); + Should.NotThrow(action); + + action = () => builder.AdvancedCircuitBreakerAsync(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _, _) => { }, (_) => { }, () => { }); + Should.NotThrow(action); + } + [Theory] [InlineData("00:00:00.001", typeof(SingleHealthMetrics))] [InlineData("00:00:00.199", typeof(SingleHealthMetrics))] diff --git a/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerSpecs.cs b/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerSpecs.cs index 91dd643c0b0..f8d2da31e9c 100644 --- a/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerSpecs.cs +++ b/test/Polly.Specs/CircuitBreaker/AdvancedCircuitBreakerSpecs.cs @@ -2918,9 +2918,20 @@ public void Should_throw_if_delegates_are_null() var samplingDuration = TimeSpan.FromMinutes(1); int mimimumThroughput = 60; var breakDuration = TimeSpan.FromSeconds(1); - var builder = Policy.HandleResult(ResultPrimitive.Fault); - Action action = () => builder.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (null as Action, CircuitState, TimeSpan, Context>)!, (_) => { }, () => { }); + var builder = Policy.Handle(); + var builderOfT = Policy.HandleResult(ResultPrimitive.Fault); + + Action action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (null as Action, CircuitState, TimeSpan, Context>)!, (_) => { }, () => { }); + Should.Throw(action).ParamName.ShouldBe("onBreak"); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _, _) => { }, null!, () => { }); + Should.Throw(action).ParamName.ShouldBe("onReset"); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _, _) => { }, (_) => { }, null!); + Should.Throw(action).ParamName.ShouldBe("onHalfOpen"); + + action = () => builder.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (null as Action)!, (_) => { }, () => { }); Should.Throw(action).ParamName.ShouldBe("onBreak"); action = () => builder.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _, _) => { }, null!, () => { }); @@ -2930,6 +2941,36 @@ public void Should_throw_if_delegates_are_null() Should.Throw(action).ParamName.ShouldBe("onHalfOpen"); } + [Fact] + public void Should_not_throw_if_arguments_are_valid() + { + double failureThreshold = 1; + var samplingDuration = TimeSpan.FromMinutes(1); + int mimimumThroughput = 60; + var breakDuration = TimeSpan.FromSeconds(1); + + var builder = Policy.Handle(); + var builderOfT = Policy.HandleResult(ResultPrimitive.Fault); + + Action action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _) => { }, () => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _) => { }, (_) => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _) => { }, () => { }, () => { }); + Should.NotThrow(action); + + action = () => builderOfT.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _) => { }, (_) => { }, () => { }); + Should.NotThrow(action); + + action = () => builder.AdvancedCircuitBreaker(failureThreshold, samplingDuration, mimimumThroughput, breakDuration, (_, _, _, _) => { }, (_) => { }, () => { }); + Should.NotThrow(action); + } + #endregion public void Dispose() => diff --git a/test/Polly.Specs/CircuitBreaker/CircuitBreakerAsyncSpecs.cs b/test/Polly.Specs/CircuitBreaker/CircuitBreakerAsyncSpecs.cs index 070b844916b..c8fc9a9f56b 100644 --- a/test/Polly.Specs/CircuitBreaker/CircuitBreakerAsyncSpecs.cs +++ b/test/Polly.Specs/CircuitBreaker/CircuitBreakerAsyncSpecs.cs @@ -1634,6 +1634,21 @@ public async Task Should_honour_and_report_cancellation_during_func_execution() attemptsInvoked.ShouldBe(1); } + [Fact] + public void Should_set_throw_if_callbacks_are_null() + { + var builder = Policy.Handle(); + + Action nullOnBreak = null!; + Action onBreak = (_, _, _, _) => { }; + Action onReset = (_) => { }; + Action onHalfOpen = () => { }; + + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, nullOnBreak, onReset, onHalfOpen)).ParamName.ShouldBe("onBreak"); + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, onBreak, null!, onHalfOpen)).ParamName.ShouldBe("onReset"); + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, onBreak, onReset, null!)).ParamName.ShouldBe("onHalfOpen"); + } + #endregion public void Dispose() => diff --git a/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultAsyncSpecs.cs b/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultAsyncSpecs.cs index 847b90a6ea8..6c2c233146e 100644 --- a/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultAsyncSpecs.cs +++ b/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultAsyncSpecs.cs @@ -1658,6 +1658,21 @@ public async Task Should_honour_different_cancellationToken_captured_implicitly_ attemptsInvoked.ShouldBe(1); } + [Fact] + public void Should_set_throw_if_callbacks_are_null() + { + var builder = Policy.HandleResult(ResultPrimitive.Fault); + + Action, CircuitState, TimeSpan, Context> nullOnBreak = null!; + Action, CircuitState, TimeSpan, Context> onBreak = (_, _, _, _) => { }; + Action onReset = (_) => { }; + Action onHalfOpen = () => { }; + + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, nullOnBreak, onReset, onHalfOpen)).ParamName.ShouldBe("onBreak"); + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, onBreak, null!, onHalfOpen)).ParamName.ShouldBe("onReset"); + Should.Throw(() => builder.CircuitBreakerAsync(1, TimeSpan.Zero, onBreak, onReset, null!)).ParamName.ShouldBe("onHalfOpen"); + } + #endregion public void Dispose() => SystemClock.Reset(); diff --git a/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultMixedResultExceptionSpecs.cs b/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultMixedResultExceptionSpecs.cs index 4e238687c9d..0bc51e22467 100644 --- a/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultMixedResultExceptionSpecs.cs +++ b/test/Polly.Specs/CircuitBreaker/CircuitBreakerTResultMixedResultExceptionSpecs.cs @@ -113,6 +113,7 @@ public void Should_open_circuit_with_the_last_handled_result_after_specified_num var exception = Should.Throw>(() => breaker.RaiseResultSequence(ResultPrimitive.Good)); exception.Message.ShouldBe("The circuit is now open and is not allowing calls."); exception.Result.ShouldBe(ResultPrimitive.Fault); + exception.InnerException.ShouldBeNull(); breaker.CircuitState.ShouldBe(CircuitState.Open); } @@ -541,6 +542,21 @@ public void Should_set_LastHandledResult_and_LastException_to_default_on_circuit breaker.LastException.ShouldBeNull(); } + [Fact] + public void Should_set_throw_if_callbacks_are_null() + { + var builder = Policy.HandleResult(ResultPrimitive.Fault); + + Action, CircuitState, TimeSpan, Context> nullOnBreak = null!; + Action, CircuitState, TimeSpan, Context> onBreak = (_, _, _, _) => { }; + Action onReset = (_) => { }; + Action onHalfOpen = () => { }; + + Should.Throw(() => builder.CircuitBreaker(1, TimeSpan.Zero, nullOnBreak, onReset, onHalfOpen)).ParamName.ShouldBe("onBreak"); + Should.Throw(() => builder.CircuitBreaker(1, TimeSpan.Zero, onBreak, null!, onHalfOpen)).ParamName.ShouldBe("onReset"); + Should.Throw(() => builder.CircuitBreaker(1, TimeSpan.Zero, onBreak, onReset, null!)).ParamName.ShouldBe("onHalfOpen"); + } + #endregion public void Dispose() => diff --git a/test/Polly.Specs/Fallback/FallbackTResultSpecs.cs b/test/Polly.Specs/Fallback/FallbackTResultSpecs.cs index a6c6f0e0be2..0fa9ad4739c 100644 --- a/test/Polly.Specs/Fallback/FallbackTResultSpecs.cs +++ b/test/Polly.Specs/Fallback/FallbackTResultSpecs.cs @@ -911,5 +911,57 @@ public void Should_handle_handled_fault_and_execute_fallback_following_faulting_ fallbackActionExecuted.ShouldBeTrue(); } + [Fact] + public void Should_return_fallback_value_when_executed_delegate_throws_exception_handled_by_policy() + { + FallbackPolicy fallbackPolicy = Policy + .HandleResult(ResultPrimitive.Fault) + .Or() + .Fallback(ResultPrimitive.Substitute); + + fallbackPolicy.RaiseResultAndOrExceptionSequence([new InvalidTimeZoneException()]) + .ShouldBe(ResultPrimitive.Substitute); + } + + [Fact] + public void Should_return_fallback_value_when_executed_delegate_throws_exception_matching_predicate_by_policy() + { + var exception = new InvalidTimeZoneException(); + + FallbackPolicy fallbackPolicy = Policy + .HandleResult(ResultPrimitive.Fault) + .Or(ex => ex == exception) + .Fallback(ResultPrimitive.Substitute); + + fallbackPolicy.RaiseResultAndOrExceptionSequence([exception]) + .ShouldBe(ResultPrimitive.Substitute); + } + + [Fact] + public void Should_return_fallback_value_when_executed_delegate_throws_inner_exception_handled_by_policy() + { + FallbackPolicy fallbackPolicy = Policy + .HandleResult(ResultPrimitive.Fault) + .OrInner() + .Fallback(ResultPrimitive.Substitute); + + fallbackPolicy.RaiseResultAndOrExceptionSequence([new NotImplementedException("Timey wimey", new InvalidTimeZoneException())]) + .ShouldBe(ResultPrimitive.Substitute); + } + + [Fact] + public void Should_return_fallback_value_when_executed_delegate_throws_inner_exception_matching_predicate_by_policy() + { + var exception = new InvalidTimeZoneException(); + + FallbackPolicy fallbackPolicy = Policy + .HandleResult(ResultPrimitive.Fault) + .OrInner(ex => ex == exception) + .Fallback(ResultPrimitive.Substitute); + + fallbackPolicy.RaiseResultAndOrExceptionSequence([new NotImplementedException("Timey wimey", exception)]) + .ShouldBe(ResultPrimitive.Substitute); + } + #endregion } diff --git a/test/Polly.Specs/NoOp/NoOpSpecs.cs b/test/Polly.Specs/NoOp/NoOpSpecs.cs index f4436a85084..55f4833ef47 100644 --- a/test/Polly.Specs/NoOp/NoOpSpecs.cs +++ b/test/Polly.Specs/NoOp/NoOpSpecs.cs @@ -36,15 +36,41 @@ public void Should_execute_user_delegate() [Fact] public void Should_execute_user_delegate_without_adding_extra_cancellation_behaviour() { - NoOpPolicy policy = Policy.NoOp(); + var policy = Policy.NoOp(); + bool executed = false; + + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + Should.NotThrow( + () => policy.Execute((token) => + { + token.ShouldBe(cts.Token); + executed = true; + }, cts.Token)); + + executed.ShouldBeTrue(); + } + + [Fact] + public void Should_execute_user_delegate_with_specified_context_and_token() + { + var policy = Policy.NoOp(); + + using var cts = new CancellationTokenSource(); + cts.Cancel(); + + var context = new Context(); + bool executed = false; - using (var cts = new CancellationTokenSource()) + policy.Execute((ctx, token) => { - cts.Cancel(); + ctx.ShouldBeSameAs(context); + token.ShouldBe(cts.Token); - Should.NotThrow(() => policy.Execute(_ => executed = true, cts.Token)); - } + executed = true; + }, context, cts.Token); executed.ShouldBeTrue(); } diff --git a/test/Polly.Specs/Polly.Specs.csproj b/test/Polly.Specs/Polly.Specs.csproj index 0564c3aedef..149389846e3 100644 --- a/test/Polly.Specs/Polly.Specs.csproj +++ b/test/Polly.Specs/Polly.Specs.csproj @@ -5,7 +5,7 @@ $(TargetFrameworks);net481 enable Test - 91,90,89 + 94,94,91 [Polly]* true diff --git a/test/Polly.Specs/Retry/RetryAsyncSpecs.cs b/test/Polly.Specs/Retry/RetryAsyncSpecs.cs index d3802b3f50c..8d134f8cfed 100644 --- a/test/Polly.Specs/Retry/RetryAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/RetryAsyncSpecs.cs @@ -191,6 +191,12 @@ public void Should_throw_when_onRetryAsync_is_null() .RetryAsync(3, (Func)null!); Should.Throw(action).ParamName.ShouldBe("onRetryAsync"); + + action = () => Policy + .Handle() + .RetryAsync(3, (Func)null!); + + Should.Throw(action).ParamName.ShouldBe("onRetryAsync"); } [Fact] diff --git a/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs b/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs index 3f3a56a100d..40e57dd086d 100644 --- a/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/RetryForeverAsyncSpecs.cs @@ -153,89 +153,91 @@ public void Should_throw_when_onretryasync_is_null() Func, Task> onRetryAsync = null!; Action policy = () => Policy - .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetryAsync); + .HandleResult(ResultPrimitive.Fault) + .RetryForeverAsync(onRetryAsync); Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); - } - [Fact] - public void Should_throw_when_onretryasync_with_int_is_null() - { - Func, int, Task> onRetryAsync = null!; + Func, int, Task> onRetryAsyncAttempts = null!; - Action policy = () => Policy - .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetryAsync); + policy = () => Policy + .HandleResult(ResultPrimitive.Fault) + .RetryForeverAsync(onRetryAsyncAttempts); Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); - } - [Fact] - public void Should_throw_when_onretry_with_context_is_null() - { - Action, Context> onRetry = null!; + Func onRetryAsyncExceptionAttempts = null!; - Action policy = () => Policy - .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetry); + policy = () => Policy + .Handle() + .RetryForeverAsync(onRetryAsyncExceptionAttempts); Should.Throw(policy) - .ParamName.ShouldBe("onRetry"); - } + .ParamName.ShouldBe("onRetryAsync"); - [Fact] - public void Should_throw_when_onretry_with_int_and_context_is_null() - { - Action, int, Context> onRetry = null!; + Func onRetryAsyncExceptionContext = null!; - Action policy = () => Policy - .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetry); + policy = () => Policy + .Handle() + .RetryForeverAsync(onRetryAsyncExceptionContext); Should.Throw(policy) - .ParamName.ShouldBe("onRetry"); - } + .ParamName.ShouldBe("onRetryAsync"); - [Fact] - public void Should_throw_when_onretry_with_exception_and_int_is_null() - { - Func onRetryAsync = null!; + Func onRetryAsyncExceptionAttemptsContext = null!; - Action policy = () => Policy - .Handle() - .RetryForeverAsync(onRetryAsync); + policy = () => Policy + .Handle() + .RetryForeverAsync(onRetryAsyncExceptionAttemptsContext); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); + + Func, Context, Task> onRetryAsyncContext = null!; + + policy = () => Policy + .HandleResult(ResultPrimitive.Fault) + .RetryForeverAsync(onRetryAsyncContext); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); + + Func, int, Context, Task> onRetryAsyncAttemptsContext = null!; + + policy = () => Policy + .HandleResult(ResultPrimitive.Fault) + .RetryForeverAsync(onRetryAsyncAttemptsContext); Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); } [Fact] - public void Should_throw_when_onretryasync_with_context_is_null() + public void Should_throw_when_onretry_with_context_is_null() { - Func, Context, Task> onRetryAsync = null!; + Action, Context> onRetry = null!; Action policy = () => Policy .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetryAsync); + .RetryForeverAsync(onRetry); Should.Throw(policy) - .ParamName.ShouldBe("onRetryAsync"); + .ParamName.ShouldBe("onRetry"); } [Fact] - public void Should_throw_when_onretryasync_with_int_and_context_is_null() + public void Should_throw_when_onretry_with_int_and_context_is_null() { - Func, int, Context, Task> onRetryAsync = null!; + Action, int, Context> onRetry = null!; Action policy = () => Policy .HandleResult(ResultPrimitive.Fault) - .RetryForeverAsync(onRetryAsync); + .RetryForeverAsync(onRetry); Should.Throw(policy) - .ParamName.ShouldBe("onRetryAsync"); + .ParamName.ShouldBe("onRetry"); } [Fact] diff --git a/test/Polly.Specs/Retry/RetryForeverSpecs.cs b/test/Polly.Specs/Retry/RetryForeverSpecs.cs index 0fe51b2dbdf..36016a45d3e 100644 --- a/test/Polly.Specs/Retry/RetryForeverSpecs.cs +++ b/test/Polly.Specs/Retry/RetryForeverSpecs.cs @@ -74,6 +74,15 @@ public void Should_throw_when_onretry_action_is_null() Should.Throw(policy) .ParamName.ShouldBe("onRetry"); + + Action, int, Context> onRetryAttemptsResult = null!; + + policy = () => Policy + .HandleResult(ResultPrimitive.Fault) + .RetryForever(onRetryAttemptsResult); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetry"); } [Fact] diff --git a/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs index fd269c8ae5a..856d058ac52 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryAsyncSpecs.cs @@ -567,6 +567,24 @@ public void Should_throw_when_sleep_duration_provider_is_null_without_context() Should.Throw(policy) .ParamName.ShouldBe("sleepDurationProvider"); + + Func sleepDurationProvider = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryAsync(1, sleepDurationProvider, (_, _, _, _) => TaskHelper.EmptyTask); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); + + Func sleepDurationProviderException = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryAsync(1, sleepDurationProviderException, (_, _, _, _) => TaskHelper.EmptyTask); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); } [Fact] @@ -612,12 +630,37 @@ public void Should_throw_when_onretryasync_action_is_null() Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); + Func onRetryExceptionAsync = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryAsync(1, (_) => TimeSpan.Zero, onRetryExceptionAsync); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); + policy = () => Policy .Handle() .WaitAndRetryAsync(1, (_, _) => TimeSpan.Zero, onRetryWithContextAsync); Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); + + Func onRetryContextAsyncAttempts = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryAsync(1, (_, _, _) => TimeSpan.Zero, onRetryContextAsyncAttempts); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); + + policy = () => Policy + .Handle() + .WaitAndRetryAsync([], onRetryContextAsyncAttempts); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); } [Fact] diff --git a/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs index bb314af3755..de6fe040485 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryForeverAsyncSpecs.cs @@ -17,7 +17,7 @@ public void Should_throw_when_sleep_duration_provider_is_null_without_context() .WaitAndRetryForeverAsync(sleepDurationProviderContext); Should.Throw(policy) - .ParamName.ShouldBe("sleepDurationProvider"); + .ParamName.ShouldBe("sleepDurationProvider"); Func sleepDurationProvider = null!; Action onRetry = (_, _) => { }; @@ -27,7 +27,7 @@ public void Should_throw_when_sleep_duration_provider_is_null_without_context() .WaitAndRetryForeverAsync(sleepDurationProvider, onRetry); Should.Throw(policy) - .ParamName.ShouldBe("sleepDurationProvider"); + .ParamName.ShouldBe("sleepDurationProvider"); Func onRetryAsync = (_, _, _) => TaskHelper.EmptyTask; @@ -36,33 +36,53 @@ public void Should_throw_when_sleep_duration_provider_is_null_without_context() .WaitAndRetryForeverAsync(sleepDurationProvider, onRetryAsync); Should.Throw(policy) - .ParamName.ShouldBe("sleepDurationProvider"); - } + .ParamName.ShouldBe("sleepDurationProvider"); - [Fact] - public void Should_throw_when_sleep_duration_provider_is_null_with_exception_and_context() - { - Action onRetry = (_, _, _) => { }; + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(sleepDurationProviderContext, (_, _, _) => TaskHelper.EmptyTask); - Action policy = () => Policy - .Handle() - .WaitAndRetryForeverAsync(null, onRetry); + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); + + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(sleepDurationProviderContext, (_, _, _, _) => TaskHelper.EmptyTask); Should.Throw(policy) - .ParamName.ShouldBe("sleepDurationProvider"); - } + .ParamName.ShouldBe("sleepDurationProvider"); - [Fact] - public void Should_throw_when_sleep_duration_provider_is_null_with_attempts_and_context() - { - Func sleepDurationProvider = null!; + Action onRetryTimeSpanContext = (_, _, _) => { }; - Action policy = () => Policy - .Handle() - .WaitAndRetryForeverAsync(sleepDurationProvider); + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(null, onRetryTimeSpanContext); Should.Throw(policy) - .ParamName.ShouldBe("sleepDurationProvider"); + .ParamName.ShouldBe("sleepDurationProvider"); + + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(sleepDurationProvider); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); + + Func sleepDurationProviderKitchenSink = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(sleepDurationProviderKitchenSink, (_, _, _) => TaskHelper.EmptyTask); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); + + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync(sleepDurationProviderKitchenSink, (_, _, _, _) => TaskHelper.EmptyTask); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); } [Fact] @@ -124,6 +144,15 @@ public void Should_throw_when_onretryasync_exception_int_timespan_is_null_with_s Should.Throw(policy) .ParamName.ShouldBe("onRetryAsync"); + + Func onRetryAsync = null!; + + policy = () => Policy + .Handle() + .WaitAndRetryForeverAsync((_, _, _) => TimeSpan.Zero, onRetryAsync); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetryAsync"); } [Fact] diff --git a/test/Polly.Specs/Retry/WaitAndRetryForeverTResultSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryForeverTResultSpecs.cs index 4ac4551f280..147d4878513 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryForeverTResultSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryForeverTResultSpecs.cs @@ -85,6 +85,13 @@ public void Should_throw_when_sleepDurationProvider_is_null() Func, Context, TimeSpan> sleepDurationProviderResult = null!; + policy = () => + Policy.HandleResult(ResultPrimitive.Fault) + .WaitAndRetryForever(sleepDurationProviderResult, (_, _, _) => { }); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); + policy = () => Policy.HandleResult(ResultPrimitive.Fault) .WaitAndRetryForever(sleepDurationProviderResult, (_, _, _, _) => { }); diff --git a/test/Polly.Specs/Retry/WaitAndRetryTResultSpecs.cs b/test/Polly.Specs/Retry/WaitAndRetryTResultSpecs.cs index 372b5da7405..0fa1112670b 100644 --- a/test/Polly.Specs/Retry/WaitAndRetryTResultSpecs.cs +++ b/test/Polly.Specs/Retry/WaitAndRetryTResultSpecs.cs @@ -62,6 +62,15 @@ public void Should_throw_when_sleepDurationProvider_is_null() Should.Throw(policy) .ParamName.ShouldBe("sleepDurationProvider"); + + Func, Context, TimeSpan> sleepDurationProviderKitchenSink = null!; + + policy = () => + Policy.HandleResult(ResultPrimitive.Fault) + .WaitAndRetry(1, sleepDurationProviderKitchenSink, (_, _, _, _) => { }); + + Should.Throw(policy) + .ParamName.ShouldBe("sleepDurationProvider"); } [Fact] @@ -154,6 +163,13 @@ public void Should_throw_when_onRetry_is_null() Should.Throw(policy) .ParamName.ShouldBe("onRetry"); + + policy = () => + Policy.HandleResult(ResultPrimitive.Fault) + .WaitAndRetry(1, (_, _, _) => TimeSpan.Zero, onRetryAttempts); + + Should.Throw(policy) + .ParamName.ShouldBe("onRetry"); } [Fact] diff --git a/test/Polly.Specs/Timeout/TimeoutAsyncSpecs.cs b/test/Polly.Specs/Timeout/TimeoutAsyncSpecs.cs index e183dd96e71..936ad46ef7c 100644 --- a/test/Polly.Specs/Timeout/TimeoutAsyncSpecs.cs +++ b/test/Polly.Specs/Timeout/TimeoutAsyncSpecs.cs @@ -337,6 +337,43 @@ public void Should_be_able_to_configure_with_timeout_func() Should.NotThrow(policy); } + [Fact] + public void Should_not_throw_if_arguments_valid() + { + Action policy = () => Policy.TimeoutAsync(1, TimeoutStrategy.Optimistic, (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(1, TimeoutStrategy.Optimistic, (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.FromSeconds(1), TimeoutStrategy.Optimistic); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.FromSeconds(1), (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.FromSeconds(1), (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.FromSeconds(1), TimeoutStrategy.Optimistic, (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.FromSeconds(1), TimeoutStrategy.Optimistic, (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.FromSeconds(1)); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.FromSeconds(1), TimeoutStrategy.Optimistic); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.FromSeconds(1), (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.FromSeconds(1), (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + } + #endregion #region Timeout operation - pessimistic @@ -707,6 +744,21 @@ public void Should_throw_when_timeoutProvider_is_null_with_strategy_and_ontimeou exception.ParamName.ShouldBe("timeoutProvider"); } + [Fact] + public void Should_throw_when_timeoutProvider_is_null_with_everything() + { + // Arrange + Func timeoutProvider = null!; + Func onTimeoutAsync = (_, _, _, _) => TaskHelper.EmptyTask; + Action policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, onTimeoutAsync); + + // Act + var exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + } + [Theory] [InlineData(1)] [InlineData(2)] diff --git a/test/Polly.Specs/Timeout/TimeoutTResultAsyncSpecs.cs b/test/Polly.Specs/Timeout/TimeoutTResultAsyncSpecs.cs index 834a76e0e58..ae744a14529 100644 --- a/test/Polly.Specs/Timeout/TimeoutTResultAsyncSpecs.cs +++ b/test/Polly.Specs/Timeout/TimeoutTResultAsyncSpecs.cs @@ -276,15 +276,6 @@ public void Should_throw_when_onTimeout_is_null_with_seconds_with_full_argument_ .ParamName.ShouldBe("onTimeoutAsync"); } - [Fact] - public void Should_throw_when_timeoutProvider_is_null() - { - Action policy = () => Policy.TimeoutAsync((Func)null!); - - Should.Throw(policy) - .ParamName.ShouldBe("timeoutProvider"); - } - [Fact] public void Should_throw_when_onTimeout_is_null_with_timeoutprovider() { @@ -313,6 +304,31 @@ public void Should_be_able_to_configure_with_timeout_func() Should.NotThrow(policy); } + [Fact] + public void Should_not_throw_if_arguments_valid() + { + Action policy = () => Policy.TimeoutAsync(1, TimeoutStrategy.Pessimistic, (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(1, TimeoutStrategy.Pessimistic, (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.Zero, TimeoutStrategy.Pessimistic); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync(() => TimeSpan.Zero, TimeoutStrategy.Pessimistic, (_, _, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.Zero); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.Zero, TimeoutStrategy.Pessimistic); + Should.NotThrow(policy); + + policy = () => Policy.TimeoutAsync((_) => TimeSpan.Zero, (_, _, _) => TaskHelper.EmptyTask); + Should.NotThrow(policy); + } + #endregion #region Timeout operation - pessimistic @@ -570,44 +586,83 @@ await Should.ThrowAsync(() => policy.ExecuteAsync(asyn } [Fact] - public void Should_throw_when_timeoutProvider_is_null_with_strategy() + public void Should_throw_when_timeoutProvider_is_null() { + Action policy = () => Policy.TimeoutAsync((Func)null!); + + Should.Throw(policy) + .ParamName.ShouldBe("timeoutProvider"); + // Arrange Func timeoutProvider = null!; - Action policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic); + policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic); // Act var exception = Should.Throw(policy); // Assert exception.ParamName.ShouldBe("timeoutProvider"); - } - [Fact] - public void Should_throw_when_timeoutProvider_is_null_with_strategy_and_ontimeout() - { // Arrange - Func timeoutProvider = null!; - Func onTimeoutAsync = (_, _, _) => TaskHelper.EmptyTask; - Action policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, onTimeoutAsync); + policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, (_, _, _) => TaskHelper.EmptyTask); // Act - var exception = Should.Throw(policy); + exception = Should.Throw(policy); // Assert exception.ParamName.ShouldBe("timeoutProvider"); - } - [Fact] - public void Should_throw_when_timeoutProvider_is_null_with_strategy_and_ontimeout_with_exception() - { // Arrange - Func timeoutProvider = null!; - Func onTimeoutAsync = (_, _, _, _) => TaskHelper.EmptyTask; - Action policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, onTimeoutAsync); + policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, (_, _, _, _) => TaskHelper.EmptyTask); // Act - var exception = Should.Throw(policy); + exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + + // Arrange + policy = () => Policy.TimeoutAsync(timeoutProvider, (_, _, _) => TaskHelper.EmptyTask); + + // Act + exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + + // Arrange + policy = () => Policy.TimeoutAsync(timeoutProvider, (_, _, _, _) => TaskHelper.EmptyTask); + + // Act + exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + + // Arrange + Func timeoutProviderContext = null!; + policy = () => Policy.TimeoutAsync(timeoutProviderContext, (_, _, _, _) => TaskHelper.EmptyTask); + + // Act + exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + + // Arrange + policy = () => Policy.TimeoutAsync(timeoutProvider, TimeoutStrategy.Pessimistic, (_, _, _, _) => TaskHelper.EmptyTask); + + // Act + exception = Should.Throw(policy); + + // Assert + exception.ParamName.ShouldBe("timeoutProvider"); + + // Arrange + policy = () => Policy.TimeoutAsync(timeoutProviderContext, TimeoutStrategy.Pessimistic, (_, _, _, _) => TaskHelper.EmptyTask); + + // Act + exception = Should.Throw(policy); // Assert exception.ParamName.ShouldBe("timeoutProvider");