/// <summary>Test helper for testing unsuccessful response handlers.</summary> private void SubtestSendAsyncUnsuccessfulReponseHanlder(HttpStatusCode code) { var handler = new UnsuccessfulResponseMessageHandler { ResponseStatusCode = code }; var configurableHanlder = new ConfigurableMessageHandler(handler); var unsuccessfulHandler = new UnsuccessfulResponseMessageHandler.ServiceUnavailableResponseHandler(); configurableHanlder.AddUnsuccessfulResponseHandler(unsuccessfulHandler); using (var client = new HttpClient(configurableHanlder)) { var request = new HttpRequestMessage(HttpMethod.Get, "https://test-unsuccessful-handler"); HttpResponseMessage response = client.SendAsync(request).Result; Assert.That(response.StatusCode, Is.EqualTo(code)); // if service unavailable, retry will occur because we plugged unsuccessful response handler which // handles service unavailable responses if (code == HttpStatusCode.ServiceUnavailable) { Assert.That(unsuccessfulHandler.Calls, Is.EqualTo(configurableHanlder.NumTries)); Assert.That(handler.Calls, Is.EqualTo(configurableHanlder.NumTries)); } else { // if status is OK, there isn't any call to unsuccessful response handler Assert.That(unsuccessfulHandler.Calls, Is.EqualTo(code != HttpStatusCode.OK ? 1 : 0)); Assert.That(handler.Calls, Is.EqualTo(1)); } } }
/// <summary> /// Tests the retry mechanism. In case the abnormal response is handled, there should be retries, but otherwise /// there should not be any retry. /// </summary> /// <param name="numTries"></param> /// <param name="handle"></param> private void SubtestSendAsyncNumTries(int numTries, bool handle = true) { var handler = new UnsuccessfulResponseMessageHandler { ResponseStatusCode = HttpStatusCode.ServiceUnavailable }; var configurableHanlder = new ConfigurableMessageHandler(handler) { NumTries = numTries }; if (handle) { var unsuccessfulHandler = new UnsuccessfulResponseMessageHandler.ServiceUnavailableResponseHandler(); configurableHanlder.AddUnsuccessfulResponseHandler(unsuccessfulHandler); } using (var client = new HttpClient(configurableHanlder)) { client.GetAsync("http://num-retres"); Assert.That(handler.Calls, Is.EqualTo(handle ? numTries : 1)); } }
public void SendAsync_ExecuteInterceptor_AbnormalResponse_UnsuccessfulResponseHandler() { var handler = new InterceptorMessageHandler(); handler.InjectedResponseMessage = new HttpResponseMessage() { StatusCode = HttpStatusCode.ServiceUnavailable }; var configurableHanlder = new ConfigurableMessageHandler(handler); var interceptor = new InterceptorMessageHandler.Interceptor(); configurableHanlder.AddExecuteInterceptor(interceptor); configurableHanlder.AddUnsuccessfulResponseHandler(new TrueUnsuccessfulResponseHandler()); using (var client = new HttpClient(configurableHanlder)) { var request = new HttpRequestMessage(HttpMethod.Get, "https://test-execute-interceptor"); HttpResponseMessage response = client.SendAsync(request).Result; Assert.That(interceptor.Calls, Is.EqualTo(configurableHanlder.NumTries)); Assert.That(handler.Calls, Is.EqualTo(configurableHanlder.NumTries)); } }
/// <summary> /// Subtest that back-off handler works as expected when a successful or abnormal response is returned. /// For testing the back-off handler in case of a canceled request, set the <code>cancelRequestNum</code> /// parameter to the index of the request you want to cancel. /// </summary> private void SubtestSendAsync_BackOffUnsuccessfulResponseHandler(HttpStatusCode statusCode, BackOffHandler.Initializer initializer, int cancelRequestNum = 0, int numTries = 10) { var handler = new UnsuccessfulResponseMessageHandler { ResponseStatusCode = statusCode }; CancellationToken cancellationToken = CancellationToken.None; bool cancel = cancelRequestNum > 0; if (cancel) { CancellationTokenSource tcs = new CancellationTokenSource(); handler.CancellationTokenSource = tcs; handler.CancelRequestNum = cancelRequestNum; cancellationToken = tcs.Token; } var configurableHanlder = new ConfigurableMessageHandler(handler) { NumTries = numTries }; var boHandler = new MockBackOffHandler(initializer); configurableHanlder.AddUnsuccessfulResponseHandler(boHandler); int boHandleCount = 0; if (initializer.HandleUnsuccessfulResponseFunc != null && initializer.HandleUnsuccessfulResponseFunc(new HttpResponseMessage { StatusCode = statusCode })) { boHandleCount = Math.Min((int)Math.Floor(Math.Log(boHandler.MaxTimeSpan.TotalSeconds, 2)) + 1, configurableHanlder.NumTries - 1); boHandleCount = boHandleCount >= 0 ? boHandleCount : 0; if (cancel) { boHandleCount = Math.Min(boHandleCount, cancelRequestNum); } } using (var client = new HttpClient(configurableHanlder)) { var request = new HttpRequestMessage(HttpMethod.Get, "https://test-exception-handler"); try { HttpResponseMessage response = client.SendAsync(request, cancellationToken).Result; Assert.False(cancel); } catch (AggregateException ae) { // a canceled request should throw an exception Assert.IsInstanceOf <TaskCanceledException>(ae.InnerException); Assert.True(cancel); } Assert.That(boHandler.Waits.Count, Is.EqualTo(boHandleCount)); // check the exponential behavior - wait 1, 2, 4, 8, ... seconds. for (int i = 0; i < boHandler.Waits.Count; ++i) { Assert.That(boHandler.Waits[i].TotalSeconds, Is.EqualTo((int)Math.Pow(2, i))); } // if the request was canceled the number of calls to the message handler is equal to the number of // calls to back-off handler Assert.That(handler.Calls, Is.EqualTo(boHandleCount + (cancel ? 0 : 1))); } }