Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for .NET 8 #1360

Merged
merged 4 commits into from
Jun 27, 2023
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
33 changes: 16 additions & 17 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<Project>
<PropertyGroup>
<MicrosoftExtensionsVersion>7.0.0</MicrosoftExtensionsVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<PollyVersion>8.0.0-alpha.4</PollyVersion>
</PropertyGroup>
Expand All @@ -8,13 +9,15 @@
<PackageVersion Include="BenchmarkDotNet" Version="0.13.5" />
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.2" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.1.1" />
<PackageVersion Include="MinVer" Version="4.3.0" />
Expand All @@ -27,23 +30,19 @@
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.4.0.72892" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.507" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="4.5.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" />
<PackageVersion Include="System.Threading.RateLimiting" Version="7.0.0" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="System.Threading.RateLimiting" Version="$(MicrosoftExtensionsVersion)" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="System.ValueTuple" Version="4.5.0" />
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework) == 'net7.0'">
<PackageVersion Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework) == 'net6.0'">
<PackageVersion Include="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Options" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'netcoreapp3.1'))">
<PackageVersion Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
<PackageVersion Update="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageVersion Update="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions bench/Polly.Core.Benchmarks/Polly.Core.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net7.0</TargetFrameworks>
<RootNamespace>Polly</RootNamespace>
<ImplicitUsings>true</ImplicitUsings>
<ProjectType>Benchmark</ProjectType>
<Nullable>enable</Nullable>
Expand Down
7 changes: 3 additions & 4 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ var configuration = Argument<string>("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
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions eng/Analyzers.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest</AnalysisLevel>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
</Project>
4 changes: 1 addition & 3 deletions src/Polly.Core/Timeout/TimeoutResilienceStrategy.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using Polly.Telemetry;

namespace Polly.Timeout;
Expand All @@ -23,7 +22,6 @@ public TimeoutResilienceStrategy(TimeoutStrategyOptions options, TimeProvider ti

public Func<OnTimeoutArguments, ValueTask>? OnTimeout { get; }

[ExcludeFromCodeCoverage]
protected internal override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<TResult, TState>(
Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback,
ResilienceContext context,
Expand All @@ -50,7 +48,7 @@ protected internal override async ValueTask<Outcome<TResult>> ExecuteCoreAsync<T
var outcome = await ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);
var isCancellationRequested = cancellationSource.IsCancellationRequested;

// execution is finished, cleanup
// execution is finished, clean up
context.CancellationToken = previousToken;
#pragma warning disable CA1849 // Call async methods when in an async method, OK here as the callback is synchronous
registration.Dispose();
Expand Down
32 changes: 9 additions & 23 deletions src/Polly.Core/Utils/TimeProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,19 @@ public static Task DelayAsync(this TimeProvider timeProvider, TimeSpan delay, Re

context.CancellationToken.ThrowIfCancellationRequested();

if (context.IsSynchronous && timeProvider == TimeProvider.System)
if (context.IsSynchronous)
{
// Stryker disable once boolean : no means to test this
if (context.CancellationToken.CanBeCanceled)
{
context.CancellationToken.WaitHandle.WaitOne(delay);
context.CancellationToken.ThrowIfCancellationRequested();
}
else
{
Thread.Sleep(delay);
}
#pragma warning disable CA1849
// For synchronous scenarios we want to return a completed task. We avoid
// the use of Thread.Sleep() here because it is not cancellable and to
// simplify the code. Sync-over-async is not a concern here because it
// only applies in the case of a reilience event and not on the hot path.
timeProvider.Delay(delay, context.CancellationToken).GetAwaiter().GetResult();
#pragma warning restore CA1849

return Task.CompletedTask;
}
else
{
if (context.IsSynchronous)
{
#pragma warning disable CA1849 // For synchronous scenarios we want to return completed task
timeProvider.Delay(delay, context.CancellationToken).GetAwaiter().GetResult();
#pragma warning restore CA1849

return Task.CompletedTask;
}

return timeProvider.Delay(delay, context.CancellationToken);
}
return timeProvider.Delay(delay, context.CancellationToken);
}
}
3 changes: 2 additions & 1 deletion src/Polly.Extensions/Polly.Extensions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
</ItemGroup>

<ItemGroup>
<Using Remove="System.Net.Http" />
<InternalsVisibleToTest Include="Polly.Extensions.Tests" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Polly.Core\Polly.Core.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
Expand Down
2 changes: 1 addition & 1 deletion src/Polly.RateLimiting/Polly.RateLimiting.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<MutationScore>100</MutationScore>
<LegacySupport>true</LegacySupport>
</PropertyGroup>

<ItemGroup>
<Using Include="Polly.Utils" />
<Compile Include="..\Polly.Core\Utils\ExceptionUtilities.cs" Link="utils\ExceptionUtilities.cs" />
Expand Down
52 changes: 0 additions & 52 deletions test/Polly.Core.Tests/Helpers/MockTimeProvider.cs

This file was deleted.

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 @@ -19,7 +19,7 @@
</ItemGroup>

<ItemGroup>
<Using Include="Polly.TestUtils" />
<Using Include="Polly.Core.Tests.Helpers" />
<Using Include="Polly.TestUtils" />
</ItemGroup>
</Project>
75 changes: 56 additions & 19 deletions test/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using FluentAssertions.Execution;
using Microsoft.Extensions.Time.Testing;
using Moq;
using Polly.Retry;
Expand Down Expand Up @@ -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>(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<TimeSpan>(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>(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<TimeSpan>(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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Loading