public async Task SendAsync_NoContextSet_RequestThrows_CleansUpContext() { // Arrange var policy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10)); var handler = new TestPolicyHttpMessageHandler(policy); Context context = null; handler.OnSendAsync = (req, c, ct) => { context = c; throw new OperationCanceledException(); }; var request = new HttpRequestMessage(); // Act var exception = await Assert.ThrowsAsync <OperationCanceledException>(async() => { await handler.SendAsync(request, CancellationToken.None); }); // Assert Assert.NotNull(context); // The handler did generate a context for the execution. Assert.Null(request.GetPolicyExecutionContext()); // We do clean up a context we generated, when the execution throws. }
public void SendAsync_WorksInSingleThreadedSyncContext() { // Arrange var policy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10)); var handler = new TestPolicyHttpMessageHandler(policy); handler.OnSendAsync = async(req, c, ct) => { await Task.Delay(1).ConfigureAwait(false); return(null); }; var hangs = true; // Act using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3))) { var token = cts.Token; token.Register(() => throw new OperationCanceledException(token)); SingleThreadedSynchronizationContext.Run(() => { // Act var request = new HttpRequestMessage(); handler.SendAsync(request, CancellationToken.None).GetAwaiter().GetResult(); hangs = false; }); } // Assert Assert.False(hangs); }
public async Task SendAsync_ExistingContext_ReusesContext() { // Arrange var policy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10)); var handler = new TestPolicyHttpMessageHandler(policy); var expected = new HttpResponseMessage(); var expectedContext = new Context(Guid.NewGuid().ToString()); Context context = null; handler.OnSendAsync = (req, c, ct) => { context = c; Assert.NotNull(c); Assert.Same(c, req.GetPolicyExecutionContext()); return(Task.FromResult(expected)); }; var request = new HttpRequestMessage(); request.SetPolicyExecutionContext(expectedContext); // Act var response = await handler.SendAsync(request, CancellationToken.None); // Assert Assert.Same(expectedContext, context); Assert.Same(expectedContext, request.GetPolicyExecutionContext()); // We don't clean up the context if the caller or earlier delegating handlers had supplied it. Assert.Same(expected, response); }
public async Task SendAsync_NoContextSet_CreatesNewContext() { // Arrange var policy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10)); var handler = new TestPolicyHttpMessageHandler(policy); Context context = null; var expected = new HttpResponseMessage(); handler.OnSendAsync = (req, c, ct) => { context = c; Assert.NotNull(context); Assert.Same(context, req.GetPolicyExecutionContext()); return(Task.FromResult(expected)); }; var request = new HttpRequestMessage(); // Act var response = await handler.SendAsync(request, CancellationToken.None); // Assert Assert.NotNull(context); Assert.Null(request.GetPolicyExecutionContext()); // We clean up the context if it was generated by the handler rather than caller supplied. Assert.Same(expected, response); }
public async Task SendAsync_DynamicPolicy_PolicyTriggers_CanReexecuteSendAsync() { // Arrange var policy = Policy <HttpResponseMessage> .Handle <HttpRequestException>() .RetryAsync(retryCount: 5); var expectedRequest = new HttpRequestMessage(); HttpRequestMessage policySelectorRequest = null; var handler = new TestPolicyHttpMessageHandler((req) => { policySelectorRequest = req; return(policy); }); var callCount = 0; var expected = new HttpResponseMessage(); handler.OnSendAsync = (req, c, ct) => { if (callCount == 0) { callCount++; throw new HttpRequestException(); } else if (callCount == 1) { callCount++; return(Task.FromResult(expected)); } else { throw new InvalidOperationException(); } }; // Act var response = await handler.SendAsync(expectedRequest, CancellationToken.None); // Assert Assert.Equal(2, callCount); Assert.Same(expected, response); Assert.Same(expectedRequest, policySelectorRequest); }
public async Task SendAsync_PolicyCancellation_CanTriggerRequestCancellation() { // Arrange var policy = Policy <HttpResponseMessage> .Handle <TimeoutRejectedException>() // Handle timeouts by retrying .RetryAsync(retryCount: 5) .WrapAsync(Policy .TimeoutAsync <HttpResponseMessage>(TimeSpan.FromMilliseconds(50)) // Apply a 50ms timeout .WrapAsync(Policy.NoOpAsync <HttpResponseMessage>())); var handler = new TestPolicyHttpMessageHandler(policy); var @event = new ManualResetEventSlim(initialState: false); var callCount = 0; var expected = new HttpResponseMessage(); handler.OnSendAsync = (req, c, ct) => { // The inner cancellation token is created by Polly, it will trigger the timeout. Assert.True(ct.CanBeCanceled); if (callCount == 0) { callCount++; @event.Wait(ct); throw null; // unreachable, previous line should throw } else if (callCount == 1) { callCount++; return(Task.FromResult(expected)); } else { throw new InvalidOperationException(); } }; // Act var response = await handler.SendAsync(new HttpRequestMessage(), CancellationToken.None); // Assert Assert.Equal(2, callCount); Assert.Same(expected, response); }
public async Task SendAsync_NoContextSet_DynamicPolicySelectorThrows_CleansUpContext() { // Arrange var handler = new TestPolicyHttpMessageHandler((req) => { throw new InvalidOperationException(); }); var request = new HttpRequestMessage(); // Act var exception = await Assert.ThrowsAsync <InvalidOperationException>(async() => { await handler.SendAsync(request, CancellationToken.None); }); // Assert Assert.Null(request.GetPolicyExecutionContext()); // We do clean up a context we generated, when the policy selector throws. }
public async Task SendAsync_DynamicPolicy_PolicySelectorReturnsNull_ThrowsException() { // Arrange var handler = new TestPolicyHttpMessageHandler((req) => { return(null); }); var expected = new HttpResponseMessage(); // Act var exception = await Assert.ThrowsAsync <InvalidOperationException>(async() => { await handler.SendAsync(new HttpRequestMessage(), CancellationToken.None); }); // Assert Assert.Equal( "The 'policySelector' function must return a non-null policy instance. To create a policy that takes no action, use 'Policy.NoOpAsync<HttpResponseMessage>()'.", exception.Message); }