diff --git a/Directory.Packages.props b/Directory.Packages.props
index 727816ff46f..c5a69391593 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,5 +1,6 @@
+ 7.0.0
true
8.0.0-alpha.4
@@ -8,13 +9,15 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -27,23 +30,19 @@
-
-
+
+
-
-
-
-
-
-
+
+
-
-
+
+
diff --git a/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj b/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj
index 85926fa8f13..d7742e9db96 100644
--- a/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj
+++ b/bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj
@@ -1,6 +1,7 @@
net7.0
+ Polly
true
Benchmark
enable
diff --git a/build.cake b/build.cake
index a74e4a01b85..48abc0bf9a9 100644
--- a/build.cake
+++ b/build.cake
@@ -10,14 +10,14 @@ var configuration = Argument("configuration", "Release");
//////////////////////////////////////////////////////////////////////
#Tool "xunit.runner.console&version=2.4.2"
-#Tool "dotnet-stryker&version=3.7.1"
+#Tool "dotnet-stryker&version=3.9.2"
//////////////////////////////////////////////////////////////////////
// EXTERNAL NUGET LIBRARIES
//////////////////////////////////////////////////////////////////////
-#addin nuget:?package=Cake.FileHelpers&version=6.0.0
-#addin nuget:?package=Newtonsoft.Json&version=13.0.2
+#addin nuget:?package=Cake.FileHelpers&version=6.1.3
+#addin nuget:?package=Newtonsoft.Json&version=13.0.3
///////////////////////////////////////////////////////////////////////////////
// GLOBAL VARIABLES
@@ -170,7 +170,6 @@ Task("__RunMutationTests")
TestProject(File("../src/Polly.Core/Polly.Core.csproj"), File("./Polly.Core.Tests/Polly.Core.Tests.csproj"), "Polly.Core.csproj");
TestProject(File("../src/Polly.RateLimiting/Polly.RateLimiting.csproj"), File("./Polly.RateLimiting.Tests/Polly.RateLimiting.Tests.csproj"), "Polly.RateLimiting.csproj");
TestProject(File("../src/Polly.Extensions/Polly.Extensions.csproj"), File("./Polly.Extensions.Tests/Polly.Extensions.Tests.csproj"), "Polly.Extensions.csproj");
-
TestProject(File("../src/Polly/Polly.csproj"), File("./Polly.Specs/Polly.Specs.csproj"), "Polly.csproj");
context.Environment.WorkingDirectory = oldDirectory;
diff --git a/eng/Analyzers.targets b/eng/Analyzers.targets
index 071b4825ccc..798450220ca 100644
--- a/eng/Analyzers.targets
+++ b/eng/Analyzers.targets
@@ -12,5 +12,6 @@
true
true
latest
+ true
diff --git a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs
index 19365a1cab1..af3fb43a627 100644
--- a/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs
+++ b/src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs
@@ -1,4 +1,3 @@
-using System.Diagnostics.CodeAnalysis;
using Polly.Telemetry;
namespace Polly.Timeout;
@@ -23,7 +22,6 @@ public TimeoutResilienceStrategy(TimeoutStrategyOptions options, TimeProvider ti
public Func? OnTimeout { get; }
- [ExcludeFromCodeCoverage]
protected internal override async ValueTask> ExecuteCoreAsync(
Func>> callback,
ResilienceContext context,
@@ -50,7 +48,7 @@ protected internal override async ValueTask> ExecuteCoreAsync
+
-
+
diff --git a/src/Polly.RateLimiting/Polly.RateLimiting.csproj b/src/Polly.RateLimiting/Polly.RateLimiting.csproj
index c4165fe48eb..9ebb23c6b01 100644
--- a/src/Polly.RateLimiting/Polly.RateLimiting.csproj
+++ b/src/Polly.RateLimiting/Polly.RateLimiting.csproj
@@ -9,7 +9,7 @@
100
true
-
+
diff --git a/test/Polly.Core.Tests/Helpers/MockTimeProvider.cs b/test/Polly.Core.Tests/Helpers/MockTimeProvider.cs
deleted file mode 100644
index e602dce6628..00000000000
--- a/test/Polly.Core.Tests/Helpers/MockTimeProvider.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using Moq;
-
-namespace Polly.Core.Tests.Helpers;
-
-internal class MockTimeProvider : Mock
-{
- public MockTimeProvider()
- : base(MockBehavior.Strict)
- {
- }
-
- public MockTimeProvider SetupAnyCreateTimer()
- {
- Setup(t => t.CreateTimer(It.IsAny(), It.IsAny
-
+
diff --git a/test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs b/test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs
index d61b46fcb0b..3e45f210564 100644
--- a/test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs
+++ b/test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs
@@ -1,3 +1,4 @@
+using FluentAssertions.Execution;
using Microsoft.Extensions.Time.Testing;
using Moq;
using Polly.Retry;
@@ -158,40 +159,76 @@ public void Retry_Infinite_Respected()
[Fact]
public async Task RetryDelayGenerator_Respected()
{
- int calls = 0;
- _options.OnRetry = _ => { calls++; return default; };
+ int retries = 0;
+ int generatedValues = 0;
+
+ var delay = TimeSpan.FromMilliseconds(120);
+ var provider = TimeProvider.System;
+
_options.ShouldHandle = _ => PredicateResult.True;
_options.RetryCount = 3;
_options.BackoffType = RetryBackoffType.Constant;
- _options.RetryDelayGenerator = _ => new ValueTask(TimeSpan.FromMilliseconds(123));
- var provider = new MockTimeProvider();
- provider.SetupCreateTimer(TimeSpan.FromMilliseconds(123));
- provider.Setup(p => p.GetTimestamp()).Returns(0);
- provider.Setup(p => p.TimestampFrequency).Returns(10000);
- var sut = CreateSut(provider.Object);
+ _options.OnRetry = _ =>
+ {
+ retries++;
+ return default;
+ };
+ _options.RetryDelayGenerator = _ =>
+ {
+ generatedValues++;
+ return new ValueTask(delay);
+ };
+
+ var before = provider.GetUtcNow();
+
+ var sut = CreateSut(provider);
await sut.ExecuteAsync(_ => default);
- provider.VerifyAll();
+ retries.Should().Be(3);
+ generatedValues.Should().Be(3);
+
+ var after = provider.GetUtcNow();
+ (after - before).Should().BeGreaterThanOrEqualTo(delay.Add(delay).Add(delay));
}
[Fact]
public async Task RetryDelayGenerator_ZeroDelay_NoTimeProviderCalls()
{
- int calls = 0;
- _options.OnRetry = _ => { calls++; return default; };
+ int retries = 0;
+ int generatedValues = 0;
+
+ var delay = TimeSpan.Zero;
+ var provider = new ThrowingFakeTimeProvider();
+
_options.ShouldHandle = _ => PredicateResult.True;
- _options.RetryCount = 1;
- _options.RetryDelayGenerator = _ => new ValueTask(TimeSpan.FromMilliseconds(0));
- var provider = new MockTimeProvider();
- provider.Setup(p => p.GetTimestamp()).Returns(0);
- provider.Setup(p => p.TimestampFrequency).Returns(10000);
+ _options.RetryCount = 3;
+ _options.BackoffType = RetryBackoffType.Constant;
- var sut = CreateSut(provider.Object);
+ _options.OnRetry = _ =>
+ {
+ retries++;
+ return default;
+ };
+ _options.RetryDelayGenerator = _ =>
+ {
+ generatedValues++;
+ return new ValueTask(delay);
+ };
+
+ var sut = CreateSut(provider);
await sut.ExecuteAsync(_ => default);
- provider.VerifyAll();
- provider.VerifyNoOtherCalls();
+ retries.Should().Be(3);
+ generatedValues.Should().Be(3);
+ }
+
+ private sealed class ThrowingFakeTimeProvider : FakeTimeProvider
+ {
+ public override DateTimeOffset GetUtcNow() => throw new AssertionFailedException("TimeProvider should not be used.");
+
+ public override ITimer CreateTimer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period)
+ => throw new AssertionFailedException("TimeProvider should not be used.");
}
[Fact]
diff --git a/test/Polly.Core.Tests/Utils/CancellationTokenSourcePoolTests.cs b/test/Polly.Core.Tests/Utils/CancellationTokenSourcePoolTests.cs
index 648e29cc198..75fe6db8077 100644
--- a/test/Polly.Core.Tests/Utils/CancellationTokenSourcePoolTests.cs
+++ b/test/Polly.Core.Tests/Utils/CancellationTokenSourcePoolTests.cs
@@ -34,6 +34,7 @@ public void RentReturn_Reusable_EnsureProperBehavior(object timeProvider)
pool.Return(cts);
var cts2 = pool.Get(System.Threading.Timeout.InfiniteTimeSpan);
+
#if NET6_0_OR_GREATER
if (timeProvider == TimeProvider.System)
{
diff --git a/test/Polly.Core.Tests/Utils/TimeProviderExtensionsTests.cs b/test/Polly.Core.Tests/Utils/TimeProviderExtensionsTests.cs
index 2cbdc93f562..0768eff9b77 100644
--- a/test/Polly.Core.Tests/Utils/TimeProviderExtensionsTests.cs
+++ b/test/Polly.Core.Tests/Utils/TimeProviderExtensionsTests.cs
@@ -4,38 +4,27 @@ namespace Polly.Core.Tests.Utils;
public class TimeProviderExtensionsTests
{
- [InlineData(false, false, false)]
- [InlineData(false, false, true)]
- [InlineData(false, true, true)]
- [InlineData(false, true, false)]
- [InlineData(true, false, false)]
- [InlineData(true, false, true)]
- [InlineData(true, true, true)]
- [InlineData(true, true, false)]
+ [InlineData(false, false)]
+ [InlineData(false, true)]
+ [InlineData(true, false)]
+ [InlineData(true, true)]
[Theory]
- public async Task DelayAsync_System_Ok(bool synchronous, bool mocked, bool hasCancellation)
+ public async Task DelayAsync_System_Ok(bool synchronous, bool hasCancellation)
{
using var tcs = new CancellationTokenSource();
var token = hasCancellation ? tcs.Token : default;
var delay = TimeSpan.FromMilliseconds(10);
- var mock = new MockTimeProvider();
- var timeProvider = mocked ? mock.Object : TimeProvider.System;
+ var timeProvider = TimeProvider.System;
var context = ResilienceContext.Get();
context.Initialize(isSynchronous: synchronous);
context.CancellationToken = token;
- mock.SetupCreateTimer(delay);
await TestUtilities.AssertWithTimeoutAsync(async () =>
{
var task = timeProvider.DelayAsync(delay, context);
- task.IsCompleted.Should().Be(synchronous || mocked);
+ task.IsCompleted.Should().Be(synchronous);
await task;
});
-
- if (mocked)
- {
- mock.VerifyAll();
- }
}
[Fact]
@@ -72,46 +61,38 @@ await TimeProvider.System
});
}
- [InlineData(false, false)]
- [InlineData(false, true)]
- [InlineData(true, false)]
- [InlineData(true, true)]
+ [InlineData(false)]
+ [InlineData(true)]
[Theory]
- public async Task DelayAsync_CancellationRequestedBefore_Throws(bool synchronous, bool mocked)
+ public async Task DelayAsync_CancellationRequestedBefore_Throws(bool synchronous)
{
using var tcs = new CancellationTokenSource();
tcs.Cancel();
var token = tcs.Token;
var delay = TimeSpan.FromMilliseconds(10);
- var mock = new MockTimeProvider();
- var timeProvider = mocked ? mock.Object : TimeProvider.System;
+ var timeProvider = TimeProvider.System;
var context = ResilienceContext.Get();
context.Initialize(isSynchronous: synchronous);
context.CancellationToken = token;
- mock.SetupCreateTimer(delay);
await Assert.ThrowsAsync(() => timeProvider.DelayAsync(delay, context));
}
- [InlineData(false, false)]
- [InlineData(false, true)]
- [InlineData(true, false)]
- [InlineData(true, true)]
+ [InlineData(false)]
+ [InlineData(true)]
[Theory]
- public async Task DelayAsync_CancellationAfter_Throws(bool synchronous, bool mocked)
+ public async Task DelayAsync_CancellationAfter_Throws(bool synchronous)
{
var delay = TimeSpan.FromMilliseconds(20);
await TestUtilities.AssertWithTimeoutAsync(async () =>
{
- var mock = new MockTimeProvider();
using var tcs = new CancellationTokenSource();
var token = tcs.Token;
- var timeProvider = mocked ? mock.Object : TimeProvider.System;
+ var timeProvider = TimeProvider.System;
var context = ResilienceContext.Get();
context.Initialize(isSynchronous: synchronous);
context.CancellationToken = token;
- mock.SetupCreateTimerException(delay, new OperationCanceledException());
tcs.CancelAfter(TimeSpan.FromMilliseconds(5));
diff --git a/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj b/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj
index cd8c555ac17..fd0d43615c3 100644
--- a/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj
+++ b/test/Polly.Extensions.Tests/Polly.Extensions.Tests.csproj
@@ -10,7 +10,6 @@
-
diff --git a/test/Polly.TestUtils/Polly.TestUtils.csproj b/test/Polly.TestUtils/Polly.TestUtils.csproj
index 8f53558bf61..e7587e9e770 100644
--- a/test/Polly.TestUtils/Polly.TestUtils.csproj
+++ b/test/Polly.TestUtils/Polly.TestUtils.csproj
@@ -11,7 +11,7 @@
-
+