예제 #1
0
        public async Task HttpRetryHandler_ThrowsTimeoutExceptionForTimeout()
        {
            // Arrange
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > handler = async(requestMessage, token) =>
            {
                await Task.Delay(LargeTimeout);

                return(new HttpResponseMessage(HttpStatusCode.OK));
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = 1,
                RequestTimeout = TimeSpan.Zero,
                RetryDelay     = TimeSpan.Zero
            };

            // Act
            Func <Task> actionAsync = () => retryHandler.SendAsync(
                request,
                new TestLogger(),
                CancellationToken.None);

            // Assert
            await Assert.ThrowsAsync <TimeoutException>(actionAsync);
        }
예제 #2
0
        public async Task HttpRetryHandler_DifferentRequestInstanceEachTime()
        {
            // Arrange
            var requests = new HashSet <HttpRequestMessage>();
            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                requests.Add(requestMessage);
                return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = TimeSpan.Zero
            };
            var log = new TestLogger();

            // Act
            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            // Assert
            Assert.Equal(MaxTries, requests.Count);
        }
예제 #3
0
        public async Task HttpRetryHandler_404VerifySingleHit()
        {
            // Arrange
            var hits = 0;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                hits++;
                return(new HttpResponseMessage(HttpStatusCode.OK));
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = TimeSpan.Zero
            };
            var log = new TestLogger();

            // Act
            using (var response = await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
                // Assert
                Assert.Equal(1, hits);
                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            }
        }
예제 #4
0
        public async Task HttpRetryHandler_MultipleTriesNoSuccess()
        {
            // Arrange
            var hits = 0;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                hits++;

                return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = TimeSpan.Zero
            };
            var log = new TestLogger();

            // Act
            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            // Assert
            Assert.Equal(MaxTries, hits);
        }
예제 #5
0
        private static async Task <T> ThrowsException <T>(ITestServer server) where T : Exception
        {
            return(await server.ExecuteAsync(async address =>
            {
                // Arrange
                var retryHandler = new HttpRetryHandler();
                var countingHandler = new CountingHandler {
                    InnerHandler = new HttpClientHandler()
                };
                var httpClient = new HttpClient(countingHandler);
                var request = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, address))
                {
                    MaxTries = 2,
                    RetryDelay = TimeSpan.Zero
                };

                // Act
                Func <Task> actionAsync = () => retryHandler.SendAsync(
                    request,
                    new TestLogger(),
                    CancellationToken.None);

                // Act & Assert
                var exception = await Assert.ThrowsAsync <T>(actionAsync);
                Assert.Equal(2, countingHandler.Hits);
                return exception;
            }));
        }
        public async Task HttpRetryHandler_AddHeaders()
        {
            // Arrange
            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler();

            using (var httpClient = new HttpClient(testHandler))
            {
                var request = new HttpRetryHandlerRequest(
                    httpClient,
                    () => new HttpRequestMessage(HttpMethod.Get, TestUrl));

                var id = Guid.NewGuid().ToString();
                request.AddHeaders.Add(new KeyValuePair <string, IEnumerable <string> >(ProtocolConstants.SessionId, new[] { id }));
                var log = new TestLogger();

                // Act
                using (var actualResponse = await retryHandler.SendAsync(request, log, CancellationToken.None))
                {
                    // Assert
                    testHandler.LastRequest.Headers.GetValues(ProtocolConstants.SessionId)
                    .FirstOrDefault()
                    .Should()
                    .Be(id);
                }
            }
        }
        public async Task HttpRetryHandler_EnhancedRetryAllowsSettingMoreRetries()
        {
            // Arrange
            var tries   = 0;
            var sent503 = false;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                tries++;

                // Return 503 for the first 2 tries
                if (tries > 10)
                {
                    return(new HttpResponseMessage(HttpStatusCode.OK));
                }
                else
                {
                    sent503 = true;
                    return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
                }
            };

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.IsEnabledEnvironmentVariableName]           = bool.TrueString,
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = "11",
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = "3"
            });

            EnhancedHttpRetryHelper helper = new EnhancedHttpRetryHelper(testEnvironmentVariableReader);

            Assert.Equal(helper.IsEnabled, true);
            // Enhanced retry mode causes a random 0-199 ms jitter so we can't time it in this test
            // but we can make sure the setting got through
            Assert.Equal(helper.DelayInMilliseconds, 3);
            Assert.Equal(helper.RetryCount, 11);

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = helper.RetryCount,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                // HttpRetryHandler will override with values from NUGET_ENHANCED_NETWORK_RETRY_DELAY_MILLISECONDS
                // so set this to a value that will cause test timeout if the correct value is not honored.
                RetryDelay = TimeSpan.FromMilliseconds(int.MaxValue) // = about 24 days
            };
            var log = new TestLogger();

            // Act
            using (var response = await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
                // Assert
                Assert.True(sent503);
                Assert.Equal(11, tries);
                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            }
        }
예제 #8
0
 /// <summary>
 /// 默认配置信息
 /// 使用<see cref="DefaultLogger"/>和<see cref="DefaultHttpLogger"/>
 /// 处理顺序:<see cref="ConnectionHandler"/>=><see cref="RetryHandler"/>=><see cref="LoggingHandler"/>
 /// </summary>
 /// <param name="path">日志目录</param>
 public HttpClientConfigs(string path)
 {
     Logger            = new DefaultLogger(path);
     ConnectionHandler = new HttpConnectionHandler(Logger);
     HttpLogger        = new DefaultHttpLogger(path);
     LoggingHandler    = new HttpLoggingHandler(ConnectionHandler, HttpLogger);
     RetryHandler      = new HttpRetryHandler(LoggingHandler, Logger);
 }
예제 #9
0
        /// <summary>
        /// 处理顺序:<see cref="ConnectionHandler"/>=><see cref="RetryHandler"/>=><see cref="LoggingHandler"/>
        /// </summary>
        /// <param name="logger">通常日志记录者。记录一些类似“开始任务”或“进入特殊处理”之类的日志</param>
        /// <param name="httpLogger">HTTP日志记录者。每个Request与Response的头和内容都被记录在单独的文件中</param>
        public HttpClientConfigs(ILogger logger, IHttpLogger httpLogger)
        {
            Logger     = logger;
            HttpLogger = httpLogger;

            ConnectionHandler = new HttpConnectionHandler(Logger);
            LoggingHandler    = new HttpLoggingHandler(ConnectionHandler, HttpLogger);
            RetryHandler      = new HttpRetryHandler(LoggingHandler, Logger);
        }
예제 #10
0
        /// <summary>
        /// 创建<see cref="HttpClient"/>对象
        /// 推荐在不需要控制HTTP细节时使用
        /// </summary>
        /// <param name="path">日志保存目录</param>
        public static HttpClient CreateHttpClient(string path)
        {
            var logger            = new DefaultLogger(path);
            var connectionHandler = new HttpConnectionHandler(logger);
            var httpLogger        = new DefaultHttpLogger(path);
            var loggingHandler    = new HttpLoggingHandler(connectionHandler, httpLogger);
            var retryHandler      = new HttpRetryHandler(loggingHandler, logger);

            return(new HttpClient(retryHandler));
        }
예제 #11
0
        /// <summary>
        /// 默认配置信息
        /// 使用<see cref="DefaultLogger"/>和<see cref="DefaultHttpLogger"/>
        /// 处理顺序:<see cref="ConnectionHandler"/>=><see cref="RetryHandler"/>=><see cref="LoggingHandler"/>
        /// </summary>
        public HttpClientConfigs()
        {
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "GlobalLogs", DateTime.Now.ToString("yyyy-MM-dd"), Guid.NewGuid().ToString("N"));

            Logger            = new DefaultLogger(path);
            ConnectionHandler = new HttpConnectionHandler(Logger);
            HttpLogger        = new DefaultHttpLogger(path);
            LoggingHandler    = new HttpLoggingHandler(ConnectionHandler, HttpLogger);
            RetryHandler      = new HttpRetryHandler(LoggingHandler, Logger);
        }
        public async Task HttpRetryHandler_MultipleTriesUntilSuccess()
        {
            // Arrange
            TimeSpan retryDelay = TimeSpan.Zero;

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = MaxTries.ToString(),
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
            });
            var tries   = 0;
            var sent503 = false;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                tries++;

                // Return 503 for the first 2 tries
                if (tries > 2)
                {
                    return(new HttpResponseMessage(HttpStatusCode.OK));
                }
                else
                {
                    sent503 = true;
                    return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
                }
            };

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = retryDelay
            };
            var log = new TestLogger();

            // Act
            using (var response = await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
                // Assert
                Assert.True(sent503);
                Assert.Equal(3, tries);
                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            }
        }
        public async Task HttpRetryHandler_AppliesTimeoutToRequestsIndividually()
        {
            // Arrange

            // 20 requests that take 250ms each for a total of 5 seconds (plus noise).
            var requestDuration = TimeSpan.FromMilliseconds(250);
            var maxTries        = 20;
            var retryDelay      = TimeSpan.Zero;

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = maxTries.ToString(),
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
            });

            // Make the request timeout longer than each request duration but less than the total
            // duration of all attempts.
            var requestTimeout = TimeSpan.FromMilliseconds(4000);

            var hits = 0;
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > handler = async(requestMessage, token) =>
            {
                hits++;
                await Task.Delay(requestDuration);

                return(new HttpResponseMessage(HttpStatusCode.InternalServerError));
            };

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = maxTries,
                RequestTimeout = requestTimeout,
                RetryDelay     = retryDelay
            };
            var log = new TestLogger();

            // Act
            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            // Assert
            Assert.Equal(maxTries, hits);
        }
        public async Task HttpRetryHandler_MultipleTriesTimed()
        {
            // Arrange
            TimeSpan retryDelay = SmallTimeout;

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = MaxTries.ToString(),
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
            });
            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
            };

            var minTime = GetRetryMinTime(MaxTries, SmallTimeout);

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = retryDelay
            };
            var log = new TestLogger();

            // Act
            var timer = new Stopwatch();

            timer.Start();

            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            timer.Stop();

            // Assert
            Assert.True(
                timer.Elapsed >= minTime,
                $"Expected this to take at least: {minTime} But it finished in: {timer.Elapsed}");
        }
예제 #15
0
        public async Task HttpRetryHandler_TimesOutDownload()
        {
            // Arrange
            var hits                 = 0;
            var memoryStream         = new MemoryStream(Encoding.ASCII.GetBytes("foobar"));
            var expectedMilliseconds = 50;
            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                hits++;
                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StreamContent(new SlowStream(memoryStream)
                    {
                        DelayPerByte = TimeSpan.FromSeconds(1)
                    })
                });
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                DownloadTimeout = TimeSpan.FromMilliseconds(expectedMilliseconds)
            };
            var destinationStream = new MemoryStream();
            var log = new TestLogger();

            // Act
            using (var response = await retryHandler.SendAsync(request, log, CancellationToken.None))
                using (var stream = await response.Content.ReadAsStreamAsync())
                {
                    var actual = await Assert.ThrowsAsync <IOException>(() => stream.CopyToAsync(destinationStream));

                    // Assert
                    Assert.Equal(1, hits);
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                    Assert.IsType <TimeoutException>(actual.InnerException);
                    Assert.EndsWith(
                        $"timed out because no data was received for {expectedMilliseconds}ms.",
                        actual.Message);
                }
        }
예제 #16
0
        public async Task HttpRetryHandler_MultipleTriesUntilSuccess()
        {
            // Arrange
            var tries   = 0;
            var sent503 = false;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                tries++;

                // Return 503 for the first 2 tries
                if (tries > 2)
                {
                    return(new HttpResponseMessage(HttpStatusCode.OK));
                }
                else
                {
                    sent503 = true;
                    return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
                }
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = TimeSpan.Zero
            };
            var log = new TestLogger();

            // Act
            using (var response = await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
                // Assert
                Assert.True(sent503);
                Assert.Equal(3, tries);
                Assert.Equal(HttpStatusCode.OK, response.StatusCode);
            }
        }
        public async Task HttpRetryHandler_CancelsRequestAfterTimeout()
        {
            // Arrange
            TimeSpan retryDelay = TimeSpan.Zero;

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = MaxTries.ToString(),
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
            });
            var requestToken = CancellationToken.None;
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > handler = async(requestMessage, token) =>
            {
                requestToken = token;
                await Task.Delay(LargeTimeout, token);

                return(new HttpResponseMessage(HttpStatusCode.OK));
            };

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = 1,
                RequestTimeout = SmallTimeout,
                RetryDelay     = retryDelay
            };

            // Act
            Func <Task> actionAsync = () => retryHandler.SendAsync(
                request,
                new TestLogger(),
                CancellationToken.None);

            // Assert
            await Assert.ThrowsAsync <TimeoutException>(actionAsync);

            Assert.True(requestToken.CanBeCanceled);
            Assert.True(requestToken.IsCancellationRequested);
        }
예제 #18
0
        public async Task HttpRetryHandler_ReturnsContentHeaders()
        {
            // Arrange
            var retryHandler = new HttpRetryHandler();

            using (var httpClient = new HttpClient())
            {
                var request = new HttpRetryHandlerRequest(
                    httpClient,
                    () => new HttpRequestMessage(HttpMethod.Get, "https://api.nuget.org/v3/index.json"));
                var log = new TestLogger();

                // Act
                using (var actualResponse = await retryHandler.SendAsync(request, log, CancellationToken.None))
                {
                    // Assert
                    Assert.NotEmpty(actualResponse.Content.Headers);
                }
            }
        }
        public async Task HttpRetryHandler_ReturnsContentHeaders()
        {
            // Arrange
            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                var stringContent = new StringContent("Plain text document.", Encoding.UTF8, "text/plain");
                stringContent.Headers.TryAddWithoutValidation("X-Content-ID", "49f47c14-c21f-4c1d-9e13-4f5fcf5f8013");
                var response = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = stringContent,
                };
                response.Headers.TryAddWithoutValidation("X-Message-Header", "This isn't on the content.");
                return(response);
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(
                httpClient,
                () => new HttpRequestMessage(HttpMethod.Get, TestUrl));
            var log = new TestLogger();

            // Act
            var actualResponse = await retryHandler.SendAsync(request, log, CancellationToken.None);

            // Assert
            var actualHeaders = actualResponse
                                .Content
                                .Headers
                                .OrderBy(x => x.Key)
                                .ToDictionary(x => x.Key, x => x.Value);

            Assert.Equal(
                new List <string> {
                "Content-Type", "X-Content-ID"
            },
                actualHeaders.Keys.OrderBy(x => x).ToList());
            Assert.Equal(actualHeaders["Content-Type"], new[] { "text/plain; charset=utf-8" });
            Assert.Equal(actualHeaders["X-Content-ID"], new[] { "49f47c14-c21f-4c1d-9e13-4f5fcf5f8013" });
        }
예제 #20
0
        public async Task HttpRetryHandler_AppliesTimeoutToRequestsIndividually()
        {
            // Arrange

            // 20 requests that take 50ms each for a total of 1 second (plus noise).
            var requestDuration = TimeSpan.FromMilliseconds(50);
            var maxTries        = 20;

            // Make the request timeout longer than each request duration but less than the total
            // duration of all attempts.
            var requestTimeout = TimeSpan.FromMilliseconds(500);

            int hits = 0;
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > handler = async(requestMessage, token) =>
            {
                hits++;
                await Task.Delay(requestDuration);

                return(new HttpResponseMessage(HttpStatusCode.InternalServerError));
            };

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = maxTries,
                RequestTimeout = requestTimeout,
                RetryDelay     = TimeSpan.Zero
            };
            var log = new TestLogger();

            // Act
            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            // Assert
            Assert.Equal(maxTries, hits);
        }
        public async Task HttpRetryHandler_MultipleTriesNoSuccess()
        {
            // Arrange
            TimeSpan retryDelay = TimeSpan.Zero;

            TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                new Dictionary <string, string>()
            {
                [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName]          = MaxTries.ToString(),
                [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
            });
            var hits = 0;

            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                hits++;

                return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
            };

            var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
            var testHandler  = new HttpRetryTestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = retryDelay
            };
            var log = new TestLogger();

            // Act
            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            // Assert
            Assert.Equal(MaxTries, hits);
        }
        private static async Task <T> ThrowsException <T>(ITestServer server) where T : Exception
        {
            return(await server.ExecuteAsync(async address =>
            {
                int maxTries = 2;
                TimeSpan retryDelay = TimeSpan.Zero;

                TestEnvironmentVariableReader testEnvironmentVariableReader = new TestEnvironmentVariableReader(
                    new Dictionary <string, string>()
                {
                    [EnhancedHttpRetryHelper.RetryCountEnvironmentVariableName] = maxTries.ToString(),
                    [EnhancedHttpRetryHelper.DelayInMillisecondsEnvironmentVariableName] = retryDelay.TotalMilliseconds.ToString()
                });

                // Arrange
                var retryHandler = new HttpRetryHandler(testEnvironmentVariableReader);
                var countingHandler = new CountingHandler {
                    InnerHandler = new HttpClientHandler()
                };
                var httpClient = new HttpClient(countingHandler);
                var request = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, address))
                {
                    MaxTries = maxTries,
                    RetryDelay = retryDelay
                };

                // Act
                Func <Task> actionAsync = () => retryHandler.SendAsync(
                    request,
                    new TestLogger(),
                    CancellationToken.None);

                // Act & Assert
                var exception = await Assert.ThrowsAsync <T>(actionAsync);
                Assert.Equal(2, countingHandler.Hits);
                return exception;
            }));
        }
예제 #23
0
        public async Task HttpRetryHandler_MultipleTriesTimed()
        {
            // Arrange
            Func <HttpRequestMessage, HttpResponseMessage> handler = requestMessage =>
            {
                return(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
            };

            var minTime = GetRetryMinTime(MaxTries, SmallTimeout);

            var retryHandler = new HttpRetryHandler();
            var testHandler  = new TestHandler(handler);
            var httpClient   = new HttpClient(testHandler);
            var request      = new HttpRetryHandlerRequest(httpClient, () => new HttpRequestMessage(HttpMethod.Get, TestUrl))
            {
                MaxTries       = MaxTries,
                RequestTimeout = Timeout.InfiniteTimeSpan,
                RetryDelay     = SmallTimeout
            };
            var log = new TestLogger();

            // Act
            var timer = new Stopwatch();

            timer.Start();

            using (await retryHandler.SendAsync(request, log, CancellationToken.None))
            {
            }

            timer.Stop();

            // Assert
            Assert.True(
                timer.Elapsed >= minTime,
                $"Expected this to take at least: {minTime} But it finished in: {timer.Elapsed}");
        }