Skip to content

Commit

Permalink
Enhance callback API with handling of void-based results (#1155)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk committed Apr 24, 2023
1 parent c7c8dbd commit c5f0f0e
Show file tree
Hide file tree
Showing 22 changed files with 919 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public async Task IsolateAsync_Ok()
{
// arrange
bool called = false;
_options.OnOpened.Register<VoidResult>((outcome, args) =>
_options.OnOpened.RegisterVoid((outcome, args) =>
{
args.BreakDuration.Should().Be(TimeSpan.MaxValue);
args.Context.IsSynchronous.Should().BeFalse();
Expand Down Expand Up @@ -65,7 +65,7 @@ public async Task BreakAsync_Ok()
{
// arrange
bool called = false;
_options.OnClosed.Register<VoidResult>((outcome, args) =>
_options.OnClosed.RegisterVoid((outcome, args) =>
{
args.Context.IsSynchronous.Should().BeFalse();
args.Context.IsVoid.Should().BeTrue();
Expand Down
12 changes: 7 additions & 5 deletions src/Polly.Core.Tests/Retry/RetryStrategyOptionsTResultTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,13 @@ public async Task AsNonGenericOptions_Ok()
nonGenericOptions.StrategyName.Should().Be("my-name");
nonGenericOptions.StrategyType.Should().Be("my-type");

(await nonGenericOptions.ShouldRetry.CreateHandler()!.ShouldHandleAsync(new Outcome<int>(999), default)).Should().BeTrue();
await nonGenericOptions.OnRetry.CreateHandler()!.HandleAsync(new Outcome<int>(999), default);
called.Should().BeTrue();
var args = new RetryDelayArguments(ResilienceContext.Get(), 2, TimeSpan.FromMinutes(1));
(await nonGenericOptions.RetryDelayGenerator.CreateHandler(default, _ => true)!.GenerateAsync(new Outcome<int>(999), args)).Should().Be(TimeSpan.FromSeconds(123));
var args = new ShouldRetryArguments(ResilienceContext.Get(), 0);
var delayArgs = new RetryDelayArguments(ResilienceContext.Get(), 2, TimeSpan.FromMinutes(1));
var retryArgs = new OnRetryArguments(ResilienceContext.Get(), 0, TimeSpan.Zero);

(await nonGenericOptions.ShouldRetry.CreateHandler()!.ShouldHandleAsync(new Outcome<int>(999), args)).Should().BeTrue();
await nonGenericOptions.OnRetry.CreateHandler()!.HandleAsync(new Outcome<int>(999), retryArgs);
called.Should().BeTrue();
(await nonGenericOptions.RetryDelayGenerator.CreateHandler(default, _ => true)!.GenerateAsync(new Outcome<int>(999), delayArgs)).Should().Be(TimeSpan.FromSeconds(123));
}
}
99 changes: 94 additions & 5 deletions src/Polly.Core.Tests/Strategy/OutcomeEventTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,107 @@ public void CreateHandler_Empty_ReturnsNull()
called.Should().BeFalse();
},
sut =>
{
sut.ConfigureCallbacks<double>(callbacks => callbacks.IsEmpty.Should().BeTrue());
InvokeHandler(sut, new Outcome<double>(1.0));
},
sut =>
{
bool called = false;
sut.Register<double>((_, _) => { called = true; return default; });
sut.SetCallbacks(new OutcomeEvent<TestArguments, double>());
InvokeHandler(sut, new Outcome<double>(1.0));
called.Should().BeFalse();
},
sut =>
{
int called = 0;
sut.Register<double>((_, _) => { called ++; return default; });
sut.RegisterVoid((_, _) => { called ++; return default; });
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.RegisterVoid((_) => called ++);
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.RegisterVoid(() => called ++);
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.RegisterVoid((_, _) => called ++);
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.RegisterVoid((_, _) => called ++);
sut.RegisterVoid((_, _) => called ++);
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
called.Should().Be(2);
},
sut =>
{
sut.SetVoidCallbacks(new VoidOutcomeEvent<TestArguments>());
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance));
},
sut =>
{
int called = 0;
sut.Register(() => called ++);
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.Register(() => called ++);
sut.Register(() => called ++);
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(2);
},
sut =>
{
int called = 0;
sut.Register(() => called ++);
sut.Register(() => called ++);
sut.Register<int>(() => called ++);
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(3);
},
sut =>
{
int called = 0;
sut.Register(o => { o.Result.Should().Be(10); called ++; });
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.Register(o => { o.Exception.Should().BeOfType<InvalidOperationException>(); called ++; });
InvokeHandler(sut, new Outcome<int>(new InvalidOperationException()));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.Register((_, _) => called ++);
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(1);
},
sut =>
{
int called = 0;
sut.Register((_, _) => { called ++; return default; });
InvokeHandler(sut, new Outcome<int>(10));
called.Should().Be(1);
},
};

[MemberData(nameof(Data))]
Expand Down
21 changes: 15 additions & 6 deletions src/Polly.Core.Tests/Strategy/OutcomeGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,28 @@ public void CreateHandler_Empty_ReturnsNull()
},
sut =>
{
sut.ConfigureGenerator<int>(generator => generator.IsEmpty.Should().BeTrue());
InvokeHandler(sut, new Outcome<int>(10), GeneratedValue.Default);
sut.SetGenerator((_, _) => new ValueTask<GeneratedValue>(GeneratedValue.Valid1));
InvokeHandler(sut, new Outcome<int>(10), GeneratedValue.Valid1);
},
sut =>
{
sut.SetVoidGenerator((_, _) => new ValueTask<GeneratedValue>(GeneratedValue.Valid1));
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance), GeneratedValue.Valid1);
},
sut =>
{
sut.ConfigureGenerator<int>(generator => generator.SetGenerator((_, _) => GeneratedValue.Valid1));
sut.SetGenerator(new OutcomeGenerator<TestArguments, GeneratedValue, int>());
sut.SetVoidGenerator((_, _) => GeneratedValue.Valid1);
InvokeHandler(sut, new Outcome<VoidResult>(VoidResult.Instance), GeneratedValue.Valid1);
},
sut =>
{
sut.SetVoidGenerator((_, _) => new ValueTask<GeneratedValue>(GeneratedValue.Valid1));
InvokeHandler(sut, new Outcome<int>(10), GeneratedValue.Default);
},
sut =>
{
sut.SetGenerator((_, _) => new ValueTask<GeneratedValue>(GeneratedValue.Valid1));
InvokeHandler(sut, new Outcome<int>(10), GeneratedValue.Valid1);
sut.SetVoidGenerator((_, _) => GeneratedValue.Valid1);
InvokeHandler(sut, new Outcome<int>(10), GeneratedValue.Default);
},
};

Expand Down
82 changes: 79 additions & 3 deletions src/Polly.Core.Tests/Strategy/OutcomePredicateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ public void Empty_Ok()
public void Empty_ConfigurePredicates_Ok()
{
_sut.IsEmpty.Should().BeTrue();
_sut.ConfigurePredicates<int>(p => p.IsEmpty.Should().BeTrue());
_sut.ConfigurePredicates<int>(p => p.IsEmpty.Should().BeTrue());
_sut.IsEmpty.Should().BeFalse();
_sut.CreateHandler().Should().BeNull();
}

Expand Down Expand Up @@ -89,6 +86,66 @@ public void CreateHandler_Empty_ReturnsNull()
sut.HandleException<InvalidOperationException>((e, _) => new ValueTask<bool>(e.Message.Contains("dummy")));
InvokeHandler(sut, new InvalidOperationException("dummy"), true);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>();
InvokeVoidHandler(sut, new InvalidOperationException("dummy"), true);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>(_=> true);
InvokeVoidHandler(sut, new ArgumentNullException("dummy"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((_, _)=> true);
InvokeVoidHandler(sut, new ArgumentNullException("dummy"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((_, _)=> new ValueTask<bool>(true));
InvokeVoidHandler(sut, new ArgumentNullException("dummy"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>();
InvokeVoidHandler(sut, new ArgumentNullException("dummy"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>();
InvokeVoidHandler(sut, new InvalidOperationException("dummy"), true);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>(e => e.Message.Contains("dummy"));
InvokeVoidHandler(sut, new InvalidOperationException("other message"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((e, _) => e.Message.Contains("dummy"));
InvokeVoidHandler(sut, new InvalidOperationException("other message"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((e, _) => e.Message.Contains("dummy"));
InvokeVoidHandler(sut, new InvalidOperationException("dummy"), true);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((e, _) => new ValueTask<bool>(e.Message.Contains("dummy")));
InvokeVoidHandler(sut, new InvalidOperationException("other message"), false);
},
sut =>
{
sut.HandleVoidException<InvalidOperationException>((e, _) => new ValueTask<bool>(e.Message.Contains("dummy")));
InvokeVoidHandler(sut, new InvalidOperationException("dummy"), true);
},
sut =>
{
sut.SetVoidPredicates(new VoidOutcomePredicate<TestArguments>());
InvokeVoidHandler(sut, new InvalidOperationException("dummy"), false);
},
};

[MemberData(nameof(ExceptionPredicates))]
Expand Down Expand Up @@ -333,6 +390,25 @@ private static void InvokeHandler(OutcomePredicate<TestArguments> sut, Exception
sut.CreateHandler()!.ShouldHandleAsync(new Outcome<int>(10), args).AsTask().Result.Should().Be(false);
}

private static void InvokeVoidHandler(OutcomePredicate<TestArguments> sut, Exception exception, bool expectedResult)
{
var args = new TestArguments();
var handler = sut.CreateHandler();

if (handler == null)
{
expectedResult.Should().BeFalse();
return;
}

#pragma warning disable S5034 // "ValueTask" should be consumed correctly
handler.ShouldHandleAsync(new Outcome<int>(exception), args).AsTask().Result.Should().Be(false);

// again with void result
handler.ShouldHandleAsync(new Outcome<VoidResult>(exception), args).AsTask().Result.Should().Be(expectedResult);
#pragma warning restore S5034 // "ValueTask" should be consumed correctly
}

private static void InvokeResultHandler<T>(OutcomePredicate<TestArguments> sut, T result, bool expectedResult)
{
sut.CreateHandler()!.ShouldHandleAsync<T>(new Outcome<T>(result), new TestArguments()).AsTask().Result.Should().Be(expectedResult);
Expand Down
18 changes: 18 additions & 0 deletions src/Polly.Core.Tests/Strategy/VoidOutcomeEventTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;

public class VoidOutcomeEventTests
{
[Fact]
public void IsEmpty_Ok()
{
var ev = new VoidOutcomeEvent<TestArguments>();

ev.IsEmpty.Should().BeTrue();

ev.Register(() => { });

ev.IsEmpty.Should().BeFalse();
}
}
18 changes: 18 additions & 0 deletions src/Polly.Core.Tests/Strategy/VoidOutcomeGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;

public class VoidOutcomeGeneratorTests
{
[Fact]
public void IsEmpty_Ok()
{
var ev = new VoidOutcomeGenerator<TestArguments, int>();

ev.IsEmpty.Should().BeTrue();

ev.SetGenerator((_, _) => 10);

ev.IsEmpty.Should().BeFalse();
}
}
18 changes: 18 additions & 0 deletions src/Polly.Core.Tests/Strategy/VoidOutcomePredicateTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;

public class VoidOutcomePredicateTests
{
[Fact]
public void IsEmpty_Ok()
{
var ev = new VoidOutcomePredicate<TestArguments>();

ev.IsEmpty.Should().BeTrue();

ev.HandleException<InvalidOperationException>();

ev.IsEmpty.Should().BeFalse();
}
}

0 comments on commit c5f0f0e

Please sign in to comment.