Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,14 @@ public void CanRetry_Respects_RetryOnError_From_Configuration()
};
var policy = new DefaultRetryPolicy(config);
var context = CreateExecutionContext();
var exception = new ArgumentException("Test");

var result = policy.CanRetry(context);
// Test through Retry method which calls CanRetry internally
var result = policy.Retry(context, exception);

Assert.IsTrue(result);
// Should return false because ArgumentException is not retryable, but CanRetry should be true
// We can verify by checking that RetryLimitExceeded is false
Assert.IsFalse(result);
}

[TestMethod]
Expand All @@ -56,14 +60,17 @@ public void CanRetry_Fallback_To_RetryOnError_Property()
var policy = new DefaultRetryPolicy(5, TimeSpan.FromMilliseconds(300));
policy.RetryOnError = false;
var context = CreateExecutionContext();
var exception = new ArgumentException("Test");

var result = policy.CanRetry(context);
// Test through Retry method
var result = policy.Retry(context, exception);

// Should return false because RetryOnError is false
Assert.IsFalse(result);
}

[TestMethod]
public void RetryForException_NetworkError_Respects_MaxNetworkRetries()
public void Retry_NetworkError_Respects_MaxNetworkRetries()
{
var config = new RetryConfiguration
{
Expand All @@ -76,16 +83,16 @@ public void RetryForException_NetworkError_Respects_MaxNetworkRetries()
var exception = MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset);

context.RequestContext.NetworkRetryCount = 1;
var result1 = policy.RetryForException(context, exception);
var result1 = policy.Retry(context, exception);
Assert.IsTrue(result1);

context.RequestContext.NetworkRetryCount = 2;
var result2 = policy.RetryForException(context, exception);
var result2 = policy.Retry(context, exception);
Assert.IsFalse(result2);
}

[TestMethod]
public void RetryForException_NetworkError_Increments_NetworkRetryCount()
public void Retry_NetworkError_Allows_Retry()
{
var config = new RetryConfiguration
{
Expand All @@ -97,12 +104,12 @@ public void RetryForException_NetworkError_Increments_NetworkRetryCount()
var context = CreateExecutionContext();
var exception = MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset);

var result = policy.RetryForException(context, exception);
var result = policy.Retry(context, exception);
Assert.IsTrue(result);
}

[TestMethod]
public void RetryForException_HttpError_5xx_Respects_RetryLimit()
public void Retry_HttpError_5xx_Respects_RetryLimit()
{
var config = new RetryConfiguration
{
Expand All @@ -114,16 +121,16 @@ public void RetryForException_HttpError_5xx_Respects_RetryLimit()
var exception = MockNetworkErrorGenerator.CreateContentstackErrorException(HttpStatusCode.InternalServerError);

context.RequestContext.HttpRetryCount = 1;
var result1 = policy.RetryForException(context, exception);
var result1 = policy.Retry(context, exception);
Assert.IsTrue(result1);

context.RequestContext.HttpRetryCount = 2;
var result2 = policy.RetryForException(context, exception);
var result2 = policy.Retry(context, exception);
Assert.IsFalse(result2);
}

[TestMethod]
public void RetryForException_HttpError_5xx_Increments_HttpRetryCount()
public void Retry_HttpError_5xx_Allows_Retry()
{
var config = new RetryConfiguration
{
Expand All @@ -134,32 +141,32 @@ public void RetryForException_HttpError_5xx_Increments_HttpRetryCount()
var context = CreateExecutionContext();
var exception = MockNetworkErrorGenerator.CreateContentstackErrorException(HttpStatusCode.InternalServerError);

var result = policy.RetryForException(context, exception);
var result = policy.Retry(context, exception);
Assert.IsTrue(result);
}

[TestMethod]
public void RetryForException_HttpError_429_Respects_RetryLimit()
public void Retry_HttpError_429_Respects_RetryLimit()
{
var config = new RetryConfiguration
{
RetryLimit = 2
};
var policy = new DefaultRetryPolicy(config);
var context = CreateExecutionContext();
var exception = MockNetworkErrorGenerator.CreateContentstackErrorException(HttpStatusCode.TooManyRequests);
var exception = MockNetworkErrorGenerator.CreateContentstackErrorException((HttpStatusCode)429);

context.RequestContext.HttpRetryCount = 1;
var result1 = policy.RetryForException(context, exception);
var result1 = policy.Retry(context, exception);
Assert.IsTrue(result1);

context.RequestContext.HttpRetryCount = 2;
var result2 = policy.RetryForException(context, exception);
var result2 = policy.Retry(context, exception);
Assert.IsFalse(result2);
}

[TestMethod]
public void RetryForException_NetworkError_Exceeds_MaxNetworkRetries_Returns_False()
public void Retry_NetworkError_Exceeds_MaxNetworkRetries_Returns_False()
{
var config = new RetryConfiguration
{
Expand All @@ -172,12 +179,12 @@ public void RetryForException_NetworkError_Exceeds_MaxNetworkRetries_Returns_Fal
context.RequestContext.NetworkRetryCount = 1;
var exception = MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset);

var result = policy.RetryForException(context, exception);
var result = policy.Retry(context, exception);
Assert.IsFalse(result);
}

[TestMethod]
public void RetryForException_HttpError_Exceeds_RetryLimit_Returns_False()
public void Retry_HttpError_Exceeds_RetryLimit_Returns_False()
{
var config = new RetryConfiguration
{
Expand All @@ -189,42 +196,45 @@ public void RetryForException_HttpError_Exceeds_RetryLimit_Returns_False()
context.RequestContext.HttpRetryCount = 1;
var exception = MockNetworkErrorGenerator.CreateContentstackErrorException(HttpStatusCode.InternalServerError);

var result = policy.RetryForException(context, exception);
var result = policy.Retry(context, exception);
Assert.IsFalse(result);
}

[TestMethod]
public void RetryForException_NonRetryableException_Returns_False()
public void Retry_NonRetryableException_Returns_False()
{
var config = new RetryConfiguration();
var policy = new DefaultRetryPolicy(config);
var context = CreateExecutionContext();
var exception = new ArgumentException("Invalid argument");

var result = policy.RetryForException(context, exception);
var result = policy.Retry(context, exception);
Assert.IsFalse(result);
}

[TestMethod]
public void RetryLimitExceeded_Checks_Both_Network_And_Http_Counts()
public void Retry_Respects_Both_Network_And_Http_Limits()
{
var config = new RetryConfiguration
{
MaxNetworkRetries = 2,
RetryLimit = 3
RetryLimit = 3,
RetryOnNetworkFailure = true,
RetryOnSocketFailure = true
};
var policy = new DefaultRetryPolicy(config);
var context = CreateExecutionContext();
var networkException = MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset);

context.RequestContext.NetworkRetryCount = 1;
context.RequestContext.HttpRetryCount = 2;
var result1 = policy.RetryLimitExceeded(context);
Assert.IsFalse(result1);
var result1 = policy.Retry(context, networkException);
Assert.IsTrue(result1); // Should allow retry

context.RequestContext.NetworkRetryCount = 2;
context.RequestContext.HttpRetryCount = 3;
var result2 = policy.RetryLimitExceeded(context);
Assert.IsTrue(result2);
var result2 = policy.Retry(context, networkException);
Assert.IsFalse(result2); // Should not allow retry when both limits exceeded
}

[TestMethod]
Expand Down Expand Up @@ -316,7 +326,7 @@ public void ShouldRetryHttpStatusCode_Respects_RetryLimit()
var context = CreateExecutionContext();
context.RequestContext.HttpRetryCount = 2;

var result = policy.ShouldRetryHttpStatusCode(HttpStatusCode.TooManyRequests, context.RequestContext);
var result = policy.ShouldRetryHttpStatusCode((HttpStatusCode)429, context.RequestContext);
Assert.IsFalse(result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void FromOptions_Creates_Configuration_With_All_Properties()
MaxNetworkRetries = 3,
NetworkRetryDelay = TimeSpan.FromMilliseconds(100),
NetworkBackoffStrategy = BackoffStrategy.Exponential,
RetryCondition = (statusCode) => statusCode == HttpStatusCode.TooManyRequests,
RetryCondition = (statusCode) => statusCode == (HttpStatusCode)429,
RetryDelayOptions = new RetryDelayOptions
{
Base = TimeSpan.FromMilliseconds(300),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,8 @@ public void CalculateNetworkRetryDelay_Includes_Jitter()
};

// Run multiple times to verify jitter is added
bool foundVariation = false;
var firstDelay = calculator.CalculateNetworkRetryDelay(1, config);

for (int i = 0; i < 10; i++)
{
var delay = calculator.CalculateNetworkRetryDelay(1, config);
if (delay != firstDelay)
{
foundVariation = true;
break;
}
}

// Jitter should cause some variation (though it's random, so not guaranteed)
// At minimum, verify the delay is within expected range
Assert.IsTrue(firstDelay >= TimeSpan.FromMilliseconds(100));
Expand Down Expand Up @@ -169,7 +158,7 @@ public void CalculateHttpRetryDelay_Respects_RetryAfter_Header_Delta()
RetryDelay = TimeSpan.FromMilliseconds(300)
};

var response = new HttpResponseMessage(HttpStatusCode.TooManyRequests);
var response = new HttpResponseMessage((HttpStatusCode)429);
response.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(5));

var delay = calculator.CalculateHttpRetryDelay(0, config, null, response.Headers);
Expand All @@ -185,7 +174,7 @@ public void CalculateHttpRetryDelay_Respects_RetryAfter_Header_Date()
RetryDelay = TimeSpan.FromMilliseconds(300)
};

var response = new HttpResponseMessage(HttpStatusCode.TooManyRequests);
var response = new HttpResponseMessage((HttpStatusCode)429);
var retryAfterDate = DateTimeOffset.UtcNow.AddSeconds(3);
response.Headers.RetryAfter = new RetryConditionHeaderValue(retryAfterDate);

Expand Down Expand Up @@ -299,7 +288,7 @@ public void CalculateHttpRetryDelay_Uses_RetryDelay_When_Base_Is_Zero()
public void ShouldRetryHttpStatusCode_Default_429()
{
var config = new RetryConfiguration();
var result = calculator.ShouldRetryHttpStatusCode(HttpStatusCode.TooManyRequests, config);
var result = calculator.ShouldRetryHttpStatusCode((HttpStatusCode)429, config);
Assert.IsTrue(result);
}

Expand Down Expand Up @@ -351,11 +340,11 @@ public void ShouldRetryHttpStatusCode_Custom_Condition()
{
var config = new RetryConfiguration
{
RetryCondition = (statusCode) => statusCode == HttpStatusCode.NotFound || statusCode == HttpStatusCode.TooManyRequests
RetryCondition = (statusCode) => statusCode == HttpStatusCode.NotFound || statusCode == (HttpStatusCode)429
};

Assert.IsTrue(calculator.ShouldRetryHttpStatusCode(HttpStatusCode.NotFound, config));
Assert.IsTrue(calculator.ShouldRetryHttpStatusCode(HttpStatusCode.TooManyRequests, config));
Assert.IsTrue(calculator.ShouldRetryHttpStatusCode((HttpStatusCode)429, config));
Assert.IsFalse(calculator.ShouldRetryHttpStatusCode(HttpStatusCode.InternalServerError, config));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
using System.Net;
using System.Net.Sockets;
using Contentstack.Management.Core;
using Contentstack.Management.Core.Exceptions;
using Contentstack.Management.Core.Internal;
using Contentstack.Management.Core.Runtime.Contexts;
using Contentstack.Management.Core.Runtime.Pipeline.RetryHandler;
using ContentstackRetryHandler = Contentstack.Management.Core.Runtime.Pipeline.RetryHandler.RetryHandler;
using Contentstack.Management.Core.Unit.Tests.Mokes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;
Expand Down Expand Up @@ -36,7 +39,7 @@ public async Task EndToEnd_NetworkError_Retries_And_Succeeds()
NetworkBackoffStrategy = BackoffStrategy.Exponential
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddFailuresThenSuccess(2, MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset));
handler.InnerHandler = mockInnerHandler;
Expand Down Expand Up @@ -64,7 +67,7 @@ public async Task EndToEnd_HttpError_Retries_And_Succeeds()
}
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddHttpErrorsThenSuccess(2, HttpStatusCode.InternalServerError);
handler.InnerHandler = mockInnerHandler;
Expand Down Expand Up @@ -93,11 +96,11 @@ public async Task EndToEnd_Mixed_Network_And_Http_Errors()
RetryDelay = TimeSpan.FromMilliseconds(10)
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddException(MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset));
mockInnerHandler.AddResponse(HttpStatusCode.InternalServerError);
mockInnerHandler.AddResponse(HttpStatusCode.TooManyRequests);
mockInnerHandler.AddResponse((HttpStatusCode)429);
mockInnerHandler.AddSuccessResponse();
handler.InnerHandler = mockInnerHandler;
handler.LogManager = LogManager.EmptyLogger;
Expand All @@ -120,7 +123,7 @@ public async Task EndToEnd_Respects_RetryConfiguration()
RetryOnError = false
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddException(MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset));
handler.InnerHandler = mockInnerHandler;
Expand Down Expand Up @@ -154,7 +157,7 @@ public async Task EndToEnd_ExponentialBackoff_Delays_Increase()
NetworkBackoffStrategy = BackoffStrategy.Exponential
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddFailuresThenSuccess(2, MockNetworkErrorGenerator.CreateSocketException(SocketError.ConnectionReset));
handler.InnerHandler = mockInnerHandler;
Expand All @@ -179,11 +182,11 @@ public async Task EndToEnd_RetryLimit_Stops_Retries()
RetryDelay = TimeSpan.FromMilliseconds(10)
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddResponse(HttpStatusCode.TooManyRequests);
mockInnerHandler.AddResponse(HttpStatusCode.TooManyRequests);
mockInnerHandler.AddResponse(HttpStatusCode.TooManyRequests);
mockInnerHandler.AddResponse((HttpStatusCode)429);
mockInnerHandler.AddResponse((HttpStatusCode)429);
mockInnerHandler.AddResponse((HttpStatusCode)429);
handler.InnerHandler = mockInnerHandler;
handler.LogManager = LogManager.EmptyLogger;

Expand Down Expand Up @@ -214,7 +217,7 @@ public async Task EndToEnd_With_CustomRetryCondition()
RetryCondition = (statusCode) => statusCode == HttpStatusCode.NotFound
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddHttpErrorsThenSuccess(2, HttpStatusCode.NotFound);
handler.InnerHandler = mockInnerHandler;
Expand Down Expand Up @@ -242,9 +245,9 @@ public async Task EndToEnd_With_CustomBackoff()
}
};
var policy = new DefaultRetryPolicy(config);
var handler = new RetryHandler(policy);
var handler = new ContentstackRetryHandler(policy);
var mockInnerHandler = new MockHttpHandlerWithRetries();
mockInnerHandler.AddHttpErrorsThenSuccess(2, HttpStatusCode.TooManyRequests);
mockInnerHandler.AddHttpErrorsThenSuccess(2, (HttpStatusCode)429);
handler.InnerHandler = mockInnerHandler;
handler.LogManager = LogManager.EmptyLogger;

Expand Down
Loading
Loading