Files
CBDDC/tests/ZB.MOM.WW.CBDDC.Core.Tests/RetryPolicyTests.cs
Joseph Doherty bd10914828
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m17s
Harden Surreal migration with retry/coverage fixes and XML docs cleanup
2026-02-22 05:39:00 -05:00

79 lines
2.5 KiB
C#

using ZB.MOM.WW.CBDDC.Core.Exceptions;
using ZB.MOM.WW.CBDDC.Core.Network;
using ZB.MOM.WW.CBDDC.Core.Resilience;
namespace ZB.MOM.WW.CBDDC.Core.Tests;
public class RetryPolicyTests
{
/// <summary>
/// Verifies transient failures are retried until a successful result is returned.
/// </summary>
[Fact]
public async Task ExecuteAsync_WhenTransientFailureEventuallySucceeds_RetriesAndReturnsResult()
{
var policy = new RetryPolicy(CreateConfigProvider(retryAttempts: 3, retryDelayMs: 1));
var attempts = 0;
int result = await policy.ExecuteAsync(async () =>
{
attempts++;
if (attempts < 3) throw new NetworkException("transient");
await Task.CompletedTask;
return 42;
}, "test-op");
result.ShouldBe(42);
attempts.ShouldBe(3);
}
/// <summary>
/// Verifies transient failures throw retry exhausted when all retries are consumed.
/// </summary>
[Fact]
public async Task ExecuteAsync_WhenTransientFailureExhausted_ThrowsRetryExhaustedException()
{
var policy = new RetryPolicy(CreateConfigProvider(retryAttempts: 2, retryDelayMs: 1));
var attempts = 0;
var ex = await Should.ThrowAsync<CBDDCException>(() => policy.ExecuteAsync<int>(() =>
{
attempts++;
throw new NetworkException("still transient");
}, "test-op"));
ex.ErrorCode.ShouldBe("RETRY_EXHAUSTED");
ex.InnerException.ShouldBeOfType<NetworkException>();
attempts.ShouldBe(2);
}
/// <summary>
/// Verifies non-transient failures are not retried.
/// </summary>
[Fact]
public async Task ExecuteAsync_WhenFailureIsNonTransient_DoesNotRetry()
{
var policy = new RetryPolicy(CreateConfigProvider(retryAttempts: 3, retryDelayMs: 1));
var attempts = 0;
await Should.ThrowAsync<InvalidOperationException>(() => policy.ExecuteAsync<int>(() =>
{
attempts++;
throw new InvalidOperationException("non-transient");
}, "test-op"));
attempts.ShouldBe(1);
}
private static IPeerNodeConfigurationProvider CreateConfigProvider(int retryAttempts, int retryDelayMs)
{
var configProvider = Substitute.For<IPeerNodeConfigurationProvider>();
configProvider.GetConfiguration().Returns(new PeerNodeConfiguration
{
RetryAttempts = retryAttempts,
RetryDelayMs = retryDelayMs
});
return configProvider;
}
}