Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions test/.editorconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
[*.cs]

dotnet_diagnostic.CA1062.severity = none
dotnet_diagnostic.SA1204.severity = none
dotnet_diagnostic.SA1600.severity = none
dotnet_diagnostic.xUnit1031.severity = suggestion
2 changes: 1 addition & 1 deletion test/Polly.Core.Tests/Polly.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<ProjectType>Test</ProjectType>
<Nullable>enable</Nullable>
<Threshold>100</Threshold>
<NoWarn>$(NoWarn);S6966;SA1600;SA1204</NoWarn>
<NoWarn>$(NoWarn);S6966</NoWarn>
<Include>[Polly.Core]*</Include>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
</PropertyGroup>
Expand Down
1 change: 0 additions & 1 deletion test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<ProjectType>Test</ProjectType>
<Nullable>enable</Nullable>
<Threshold>100</Threshold>
<NoWarn>$(NoWarn);SA1600;SA1204</NoWarn>
<Include>[Polly.Extensions]*</Include>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<ProjectType>Test</ProjectType>
<Nullable>enable</Nullable>
<Threshold>100</Threshold>
<NoWarn>$(NoWarn);SA1600;SA1204</NoWarn>
<Include>[Polly.RateLimiting]*</Include>
</PropertyGroup>
<ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions test/Polly.Specs/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[*.cs]

dotnet_diagnostic.CA1030.severity = none
dotnet_diagnostic.CA2008.severity = none
dotnet_diagnostic.CA2201.severity = none
dotnet_diagnostic.S104.severity = none
dotnet_diagnostic.S6966.severity = none
7 changes: 1 addition & 6 deletions test/Polly.Specs/Bulkhead/BulkheadSpecs.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
namespace Polly.Specs.Bulkhead;

[Collection(Constants.ParallelThreadDependentTestCollection)]
public class BulkheadSpecs : BulkheadSpecsBase
public class BulkheadSpecs(ITestOutputHelper testOutputHelper) : BulkheadSpecsBase(testOutputHelper)
{
public BulkheadSpecs(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
}

#region Configuration

[Fact]
Expand Down
14 changes: 6 additions & 8 deletions test/Polly.Specs/Bulkhead/BulkheadSpecsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public abstract class BulkheadSpecsBase : IDisposable
#region Time constraints

protected readonly TimeSpan ShimTimeSpan = TimeSpan.FromMilliseconds(50); // How frequently to retry the assertions.
protected readonly TimeSpan CohesionTimeLimit = TimeSpan.FromMilliseconds(1000); // Consider increasing CohesionTimeLimit if bulkhead specs fail transiently in slower build environments.
protected readonly TimeSpan CohesionTimeLimit = TimeSpan.FromSeconds(1);

#endregion

Expand All @@ -33,9 +33,9 @@ protected BulkheadSpecsBase(ITestOutputHelper testOutputHelper)

protected IBulkheadPolicy BulkheadForStats { get; set; } = null!;

internal TraceableAction[] Actions { get; set; } = { };
internal TraceableAction[] Actions { get; set; } = [];

protected Task[] Tasks { get; set; } = { };
protected Task[] Tasks { get; set; } = [];

protected readonly AutoResetEvent StatusChangedEvent = new(false);

Expand Down Expand Up @@ -84,10 +84,7 @@ protected BulkheadSpecsBase(ITestOutputHelper testOutputHelper)
[ClassData(typeof(BulkheadScenarios))]
public void Should_control_executions_per_specification(int maxParallelization, int maxQueuingActions, int totalActions, bool cancelQueuing, bool cancelExecuting, string scenario)
{
if (totalActions < 0)
{
throw new ArgumentOutOfRangeException(nameof(totalActions));
}
totalActions.ShouldBeGreaterThanOrEqualTo(0);

MaxParallelization = maxParallelization;
MaxQueuingActions = maxQueuingActions;
Expand Down Expand Up @@ -312,7 +309,7 @@ protected void EnsureNoUnbservedTaskExceptions()
}
catch (Exception e)
{
throw new Exception("Task " + i + " raised the following unobserved task exception: ", e);
throw new Exception($"Task {i} raised the following unobserved task exception: ", e);
}
}
}
Expand Down Expand Up @@ -373,6 +370,7 @@ protected void OutputStatus(string statusHeading)
private void ShowTestOutput() =>
((AnnotatedOutputHelper)TestOutputHelper).Flush();
#endif

#endregion

public void Dispose()
Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Bulkhead/BulkheadTResultAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected override IBulkheadPolicy GetBulkhead(int maxParallelization, int maxQu
Policy.BulkheadAsync<ResultPrimitive>(maxParallelization, maxQueuingActions);

protected override Task ExecuteOnBulkhead(IBulkheadPolicy bulkhead, TraceableAction action) =>
action.ExecuteOnBulkheadAsync<ResultPrimitive>((AsyncBulkheadPolicy<ResultPrimitive>)bulkhead);
action.ExecuteOnBulkheadAsync((AsyncBulkheadPolicy<ResultPrimitive>)bulkhead);

#endregion
}
2 changes: 1 addition & 1 deletion test/Polly.Specs/Bulkhead/BulkheadTResultSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected override IBulkheadPolicy GetBulkhead(int maxParallelization, int maxQu
Policy.Bulkhead<ResultPrimitive>(maxParallelization, maxQueuingActions);

protected override Task ExecuteOnBulkhead(IBulkheadPolicy bulkhead, TraceableAction action) =>
action.ExecuteOnBulkhead<ResultPrimitive>((BulkheadPolicy<ResultPrimitive>)bulkhead);
action.ExecuteOnBulkhead((BulkheadPolicy<ResultPrimitive>)bulkhead);

#endregion
}
4 changes: 2 additions & 2 deletions test/Polly.Specs/Bulkhead/IBulkheadPolicySpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ public class IBulkheadPolicySpecs
[Fact]
public void Should_be_able_to_use_BulkheadAvailableCount_via_interface()
{
IBulkheadPolicy bulkhead = Policy.Bulkhead(20, 10);
var bulkhead = Policy.Bulkhead(20, 10);

bulkhead.BulkheadAvailableCount.ShouldBe(20);
}

[Fact]
public void Should_be_able_to_use_QueueAvailableCount_via_interface()
{
IBulkheadPolicy bulkhead = Policy.Bulkhead(20, 10);
var bulkhead = Policy.Bulkhead(20, 10);

bulkhead.QueueAvailableCount.ShouldBe(10);
}
Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Caching/CacheAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ public void Should_throw_when_policies_is_null()
Action action = () => Policy.WrapAsync(policies);
Should.Throw<ArgumentNullException>(action).ParamName.ShouldBe("policies");

action = () => Policy.WrapAsync<int>(policiesGeneric);
action = () => Policy.WrapAsync(policiesGeneric);
Should.Throw<ArgumentNullException>(action).ParamName.ShouldBe("policies");
}
#endregion
Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Caching/CacheSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public void Should_throw_when_policies_is_null()
Action action = () => Policy.Wrap(policies);
Should.Throw<ArgumentNullException>(action).ParamName.ShouldBe("policies");

action = () => Policy.Wrap<int>(policiesGeneric);
action = () => Policy.Wrap(policiesGeneric);
Should.Throw<ArgumentNullException>(action).ParamName.ShouldBe("policies");
}

Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Caching/CacheTResultAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public async Task Should_allow_custom_ICacheKeyStrategy()
var stubCacheProvider = new StubCacheProvider();
var cacheKeyStrategy = new StubCacheKeyStrategy(context => context.OperationKey + context["id"]);

var cache = Policy.CacheAsync<ResultClass>(stubCacheProvider.AsyncFor<ResultClass>(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling);
var cache = Policy.CacheAsync(stubCacheProvider.AsyncFor<ResultClass>(), new RelativeTtl(TimeSpan.MaxValue), cacheKeyStrategy, emptyDelegate, emptyDelegate, emptyDelegate, noErrorHandling, noErrorHandling);

object person1 = new ResultClass(ResultPrimitive.Good, "person1");
await stubCacheProvider.PutAsync("person1", person1, new Ttl(TimeSpan.MaxValue), CancellationToken, false);
Expand Down
6 changes: 3 additions & 3 deletions test/Polly.Specs/Caching/GenericCacheProviderAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public async Task Should_not_error_for_executions_on_non_nullable_types_if_cache
const string OperationKey = "SomeOperationKey";

bool onErrorCalled = false;
Action<Context, string, Exception> onError = (_, _, _) => { onErrorCalled = true; };
Action<Context, string, Exception> onError = (_, _, _) => onErrorCalled = true;

IAsyncCacheProvider stubCacheProvider = new StubCacheProvider();
var stubCacheProvider = new StubCacheProvider();
var cache = Policy.CacheAsync(stubCacheProvider, TimeSpan.MaxValue, onError);

(bool cacheHit, object? fromCache) = await stubCacheProvider.TryGetAsync(OperationKey, CancellationToken.None, false);
Expand All @@ -34,7 +34,7 @@ public async Task Should_execute_delegate_and_put_value_in_cache_for_non_nullabl
const string OperationKey = "SomeOperationKey";

var cancellationToken = CancellationToken.None;
IAsyncCacheProvider stubCacheProvider = new StubCacheProvider();
var stubCacheProvider = new StubCacheProvider();
var cache = Policy.CacheAsync(stubCacheProvider, TimeSpan.MaxValue);

(bool cacheHit1, object? fromCache1) = await stubCacheProvider.TryGetAsync(OperationKey, cancellationToken, false);
Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Caching/GenericCacheProviderSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void Should_execute_delegate_and_put_value_in_cache_for_non_nullable_type
const ResultPrimitive ValueToReturn = ResultPrimitive.Substitute;
const string OperationKey = "SomeOperationKey";

ISyncCacheProvider stubCacheProvider = new StubCacheProvider();
var stubCacheProvider = new StubCacheProvider();
CachePolicy cache = Policy.Cache(stubCacheProvider, TimeSpan.MaxValue);

(bool cacheHit1, object? fromCache1) = stubCacheProvider.TryGet(OperationKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public class ICircuitBreakerTResultPolicySpecs
[Fact]
public void Should_be_able_to_use_LastHandledResult_via_interface()
{
ICircuitBreakerPolicy<ResultPrimitive> breaker = Policy
var breaker = Policy
.HandleResult(ResultPrimitive.Fault)
.CircuitBreaker(2, TimeSpan.FromMinutes(1));

Expand Down
6 changes: 3 additions & 3 deletions test/Polly.Specs/Custom/CustomTResultAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void Should_be_able_to_construct_reactive_policy()
{
Action construct = () =>
{
AsyncAddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult<ResultPrimitive>(ResultPrimitive.Fault).WithBehaviourAsync(async outcome =>
AsyncAddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult(ResultPrimitive.Fault).WithBehaviourAsync(async outcome =>
{
// Placeholder for more substantive async work.
Console.WriteLine("Handling " + outcome.Result);
Expand All @@ -52,7 +52,7 @@ public async Task Reactive_policy_should_handle_result()
{
ResultPrimitive handled = ResultPrimitive.Undefined;
AsyncAddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy
.HandleResult<ResultPrimitive>(ResultPrimitive.Fault)
.HandleResult(ResultPrimitive.Fault)
.WithBehaviourAsync(async outcome => { handled = outcome.Result; await Task.CompletedTask; });

ResultPrimitive toReturn = ResultPrimitive.Fault;
Expand All @@ -75,7 +75,7 @@ public async Task Reactive_policy_should_be_able_to_ignore_unhandled_result()
{
ResultPrimitive? handled = null;
AsyncAddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy
.HandleResult<ResultPrimitive>(ResultPrimitive.Fault)
.HandleResult(ResultPrimitive.Fault)
.WithBehaviourAsync(async outcome => { handled = outcome.Result; await Task.CompletedTask; });

ResultPrimitive toReturn = ResultPrimitive.FaultYetAgain;
Expand Down
6 changes: 3 additions & 3 deletions test/Polly.Specs/Custom/CustomTResultSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void Should_be_able_to_construct_reactive_policy()
{
Action construct = () =>
{
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult<ResultPrimitive>(ResultPrimitive.Fault).WithBehaviour(outcome => Console.WriteLine("Handling " + outcome.Result));
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult(ResultPrimitive.Fault).WithBehaviour(outcome => Console.WriteLine("Handling " + outcome.Result));
};

Should.NotThrow(construct);
Expand All @@ -46,7 +46,7 @@ public void Should_be_able_to_construct_reactive_policy()
public void Reactive_policy_should_handle_result()
{
ResultPrimitive handled = ResultPrimitive.Undefined;
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult<ResultPrimitive>(ResultPrimitive.Fault).WithBehaviour(outcome => handled = outcome.Result);
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult(ResultPrimitive.Fault).WithBehaviour(outcome => handled = outcome.Result);

ResultPrimitive toReturn = ResultPrimitive.Fault;
bool executed = false;
Expand All @@ -66,7 +66,7 @@ public void Reactive_policy_should_handle_result()
public void Reactive_policy_should_be_able_to_ignore_unhandled_result()
{
ResultPrimitive? handled = null;
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult<ResultPrimitive>(ResultPrimitive.Fault).WithBehaviour(outcome => handled = outcome.Result);
AddBehaviourIfHandlePolicy<ResultPrimitive> policy = Policy.HandleResult(ResultPrimitive.Fault).WithBehaviour(outcome => handled = outcome.Result);

ResultPrimitive toReturn = ResultPrimitive.FaultYetAgain;
bool executed = false;
Expand Down
2 changes: 1 addition & 1 deletion test/Polly.Specs/Fallback/FallbackAsyncSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public async Task Should_throw_for_generic_method_execution_on_non_generic_polic
.Handle<DivideByZeroException>()
.FallbackAsync(_ => TaskHelper.EmptyTask);

await Should.ThrowAsync<InvalidOperationException>(() => fallbackPolicy.ExecuteAsync<int>(() => Task.FromResult(0)));
await Should.ThrowAsync<InvalidOperationException>(() => fallbackPolicy.ExecuteAsync(() => Task.FromResult(0)));
}

#endregion
Expand Down
24 changes: 12 additions & 12 deletions test/Polly.Specs/Helpers/Bulkhead/TraceableAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
/// A traceable action that can be executed on a <see cref="BulkheadPolicy"/>, to support specs.
/// <remarks>We can execute multiple instances of <see cref="TraceableAction"/> in parallel on a bulkhead, and manually control the cancellation and completion of each, to provide determinate tests on the bulkhead operation. The status of this <see cref="TraceableAction"/> as it executes is fully traceable through the <see cref="TraceableActionStatus"/> property.</remarks>
/// </summary>
public class TraceableAction : IDisposable
public class TraceableAction(int id, AutoResetEvent statusChanged, ITestOutputHelper testOutputHelper) : IDisposable
{
private readonly string _id;
private readonly ITestOutputHelper _testOutputHelper;
private readonly string _id = $"{id:00}: ";
private readonly ITestOutputHelper _testOutputHelper = testOutputHelper;

private readonly TaskCompletionSource<object?> _tcsProxyForRealWork = new();
private readonly CancellationTokenSource _cancellationSource = new();
private readonly AutoResetEvent _statusChanged;
private readonly AutoResetEvent _statusChanged = statusChanged;

private TraceableActionStatus _status;

Expand All @@ -26,13 +26,6 @@ public TraceableActionStatus Status
}
}

public TraceableAction(int id, AutoResetEvent statusChanged, ITestOutputHelper testOutputHelper)
{
_id = $"{id:00}: ";
_statusChanged = statusChanged;
_testOutputHelper = testOutputHelper;
}

public void SignalStateChange()
{
_testOutputHelper.WriteLine("--signalled--");
Expand Down Expand Up @@ -99,7 +92,9 @@ private Task ExecuteThroughSyncBulkheadOuter(Action executeThroughBulkheadInner)
throw;
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
{
_testOutputHelper.WriteLine(_id + "Caught unexpected exception during execution: " + e);

Expand Down Expand Up @@ -165,7 +160,9 @@ public Task ExecuteThroughAsyncBulkheadOuter(Func<Task> executeThroughBulkheadIn
Status = TraceableActionStatus.Canceled;
} // else: was execution cancellation rethrown: ignore
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
{
_testOutputHelper.WriteLine(_id + "Caught unexpected exception during execution: " + e);

Expand Down Expand Up @@ -233,6 +230,9 @@ public void Cancel()
_tcsProxyForRealWork.SetCanceled();
}

public void Dispose() =>
public void Dispose()
{
_statusChanged?.Dispose();
_cancellationSource.Dispose();
}
}
6 changes: 4 additions & 2 deletions test/Polly.Specs/Helpers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
public static class Constants
{
/// <summary>
/// Denotes a test collection dependent on manipulating the abstracted <see cref="Polly.Utilities.SystemClock"/>. <remarks>These tests are not parallelized.</remarks>
/// Denotes a test collection dependent on manipulating the abstracted <see cref="SystemClock"/>.
/// </summary>
/// <remarks>These tests are not parallelized.</remarks>
public const string SystemClockDependentTestCollection = "SystemClockDependentTestCollection";

/// <summary>
/// Denotes a test collection making heavy use of parallel threads. <remarks>These tests are not run in parallel with each other, to reduce heavy use of threads in the build/CI environment.</remarks>
/// Denotes a test collection making heavy use of parallel threads.
/// </summary>
/// <remarks>These tests are not run in parallel with each other, to reduce heavy use of threads in the build/CI environment.</remarks>
public const string ParallelThreadDependentTestCollection = "ParallelThreadDependentTestCollection";
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

public static class ContextualPolicyTResultExtensionsAsync
{
public static Task<TResult> RaiseResultSequenceAsync<TResult>(this AsyncPolicy<TResult> policy,
IDictionary<string, object> contextData,
params TResult[] resultsToRaise) =>
policy.RaiseResultSequenceAsync(contextData, CancellationToken.None, resultsToRaise.ToList());
public static Task<TResult> RaiseResultSequenceAsync<TResult>(
this AsyncPolicy<TResult> policy,
IDictionary<string, object> contextData,
params TResult[] resultsToRaise) =>
policy.RaiseResultSequenceAsync(contextData, CancellationToken.None, [.. resultsToRaise]);

public static Task<TResult> RaiseResultSequenceAsync<TResult>(this AsyncPolicy<TResult> policy, IDictionary<string, object> contextData, CancellationToken cancellationToken, IEnumerable<TResult> resultsToRaise)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,13 @@ internal static class AddBehaviourIfHandleSyntax
{
internal static AddBehaviourIfHandlePolicy WithBehaviour(this PolicyBuilder policyBuilder, Action<Exception> behaviourIfHandle)
{
if (behaviourIfHandle == null)
{
throw new ArgumentNullException(nameof(behaviourIfHandle));
}

behaviourIfHandle.ShouldNotBeNull();
return new AddBehaviourIfHandlePolicy(behaviourIfHandle, policyBuilder);
}

internal static AddBehaviourIfHandlePolicy<TResult> WithBehaviour<TResult>(this PolicyBuilder<TResult> policyBuilder, Action<DelegateResult<TResult>> behaviourIfHandle)
{
if (behaviourIfHandle == null)
{
throw new ArgumentNullException(nameof(behaviourIfHandle));
}

behaviourIfHandle.ShouldNotBeNull();
return new AddBehaviourIfHandlePolicy<TResult>(behaviourIfHandle, policyBuilder);
}
}
Loading
Loading