public async Task ExecuteAsync_ResponseOk_DoesNotRetry()
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff = TimeSpan.FromSeconds(5)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender().Returns(HttpStatusCode.OK);

            var response = await retryPolicy.ExecuteAsync(client.SendRequest);

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal(1, client.TimesCalled);
        }
        public async Task ExecuteAsync_ThrottledRequest_NoHeader_GetsNextWaitTime(HttpStatusCode statusCode)
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff          = TimeSpan.FromSeconds(10),
                MaxCumulativeWaitTime = TimeSpan.FromSeconds(5)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender().Returns(statusCode);

            var response = await retryPolicy.ExecuteAsync(client.SendRequest);

            Assert.Equal(statusCode, response.StatusCode);
            Assert.Equal(1, client.TimesCalled);
        }
        public async Task ExecuteAsync_RecoversAfterNotSuccessStatusCode()
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff = TimeSpan.FromMilliseconds(100)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender().Returns(HttpStatusCode.InternalServerError, HttpStatusCode.OK);

            var stopwatch = Stopwatch.StartNew();
            var response  = await retryPolicy.ExecuteAsync(client.SendRequest);

            stopwatch.Stop();

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal(2, client.TimesCalled);
            Assert.True(stopwatch.Elapsed > 0.8 * options.DeltaBackoff);
        }
        public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithDate_ReadsWaitTimeFromHeader(HttpStatusCode statusCode)
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff          = TimeSpan.FromMilliseconds(100),
                MaxCumulativeWaitTime = TimeSpan.FromSeconds(5)
            };
            var retryPolicy  = new DefaultRetryPolicy(options);
            var mockResponse = new HttpResponseMessage(statusCode);

            mockResponse.Headers.RetryAfter = new RetryConditionHeaderValue(DateTime.UtcNow.AddSeconds(6));
            var client = new FakeSender().Returns(mockResponse);

            var response = await retryPolicy.ExecuteAsync(client.SendRequest);

            Assert.Equal(statusCode, response.StatusCode);
            Assert.Equal(1, client.TimesCalled);
        }
        public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithNotPositiveDelta_GetsNextWaitTime(HttpStatusCode statusCode, int waitTimeInSeconds)
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff          = TimeSpan.FromSeconds(10),
                MaxCumulativeWaitTime = TimeSpan.FromSeconds(5)
            };
            var retryPolicy  = new DefaultRetryPolicy(options);
            var mockResponse = new HttpResponseMessage(statusCode);

            mockResponse.Headers.RetryAfter = new RetryConditionHeaderValue(TimeSpan.FromSeconds(waitTimeInSeconds));
            var client = new FakeSender().Returns(mockResponse);

            var response = await retryPolicy.ExecuteAsync(client.SendRequest);

            Assert.Equal(statusCode, response.StatusCode);
            Assert.Equal(1, client.TimesCalled);
        }
        public async Task ExecuteAsync_Exception_RetriesUntilCumulativeWaitTimeReached()
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff          = TimeSpan.FromMilliseconds(100),
                MaxCumulativeWaitTime = TimeSpan.FromSeconds(2)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender().Throws(GetExceptionFromStatus(WebExceptionStatus.ConnectionClosed));

            var stopwatch = Stopwatch.StartNew();
            await Assert.ThrowsAsync <HttpRequestException>(() => retryPolicy.ExecuteAsync(client.SendRequest));

            stopwatch.Stop();

            Assert.True(client.TimesCalled > 1);
            var maximumPossibleNextWaitTime = 1.2 * options.DeltaBackoff * Math.Pow(2, client.TimesCalled - 1);

            Assert.True(stopwatch.Elapsed > options.MaxCumulativeWaitTime - maximumPossibleNextWaitTime);
        }
        public async Task ExecuteAsync_RecoversAfterException()
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff = TimeSpan.FromMilliseconds(100)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender()
                              .Throws(GetExceptionFromStatus(WebExceptionStatus.ConnectionClosed))
                              .Returns(HttpStatusCode.OK);

            var stopwatch = Stopwatch.StartNew();
            var response  = await retryPolicy.ExecuteAsync(client.SendRequest);

            stopwatch.Stop();

            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            Assert.Equal(2, client.TimesCalled);
            Assert.True(stopwatch.Elapsed > 0.8 * options.DeltaBackoff);
        }
        public async Task ExecuteAsync_UnsuccessfulStatusCode_RetriesUntilCumulativeWaitTimeReached()
        {
            var options = new DefaultRetryPolicyOptions
            {
                DeltaBackoff          = TimeSpan.FromMilliseconds(100),
                MaxCumulativeWaitTime = TimeSpan.FromSeconds(2)
            };
            var retryPolicy = new DefaultRetryPolicy(options);
            var client      = new FakeSender().Returns(HttpStatusCode.InternalServerError);

            var stopwatch = Stopwatch.StartNew();
            var response  = await retryPolicy.ExecuteAsync(client.SendRequest);

            stopwatch.Stop();

            Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
            Assert.True(client.TimesCalled > 1);
            var maximumPossibleNextWaitTime = 1.2 * options.DeltaBackoff * Math.Pow(2, client.TimesCalled - 1);

            Assert.True(stopwatch.Elapsed > options.MaxCumulativeWaitTime - maximumPossibleNextWaitTime);
        }