Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id D10D1200C77 for ; Mon, 1 May 2017 15:06:51 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id CF8D1160BB9; Mon, 1 May 2017 13:06:51 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 2900A160BAB for ; Mon, 1 May 2017 15:06:50 +0200 (CEST) Received: (qmail 66010 invoked by uid 500); 1 May 2017 13:06:49 -0000 Mailing-List: contact commits-help@hc.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "HttpComponents Project" Delivered-To: mailing list commits@hc.apache.org Received: (qmail 65995 invoked by uid 99); 1 May 2017 13:06:49 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 May 2017 13:06:49 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id B4A6E3A3B85 for ; Mon, 1 May 2017 13:06:48 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1793325 [2/2] - in /httpcomponents/httpclient/trunk/httpclient5/src: main/java/org/apache/hc/client5/http/impl/sync/ test/java/org/apache/hc/client5/http/impl/sync/ Date: Mon, 01 May 2017 13:06:48 -0000 To: commits@hc.apache.org From: olegk@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20170501130648.B4A6E3A3B85@svn01-us-west.apache.org> archived-at: Mon, 01 May 2017 13:06:52 -0000 Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestMainClientExec.java URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestMainClientExec.java?rev=1793325&r1=1793324&r2=1793325&view=diff ============================================================================== --- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestMainClientExec.java (original) +++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestMainClientExec.java Mon May 1 13:06:48 2017 @@ -27,52 +27,28 @@ package org.apache.hc.client5.http.impl.sync; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.InterruptedIOException; -import java.util.Collections; -import java.util.Map; import org.apache.hc.client5.http.ConnectionKeepAliveStrategy; import org.apache.hc.client5.http.HttpRoute; -import org.apache.hc.client5.http.RouteInfo; -import org.apache.hc.client5.http.auth.AuthChallenge; -import org.apache.hc.client5.http.auth.AuthExchange; -import org.apache.hc.client5.http.auth.AuthScheme; -import org.apache.hc.client5.http.auth.AuthScope; -import org.apache.hc.client5.http.auth.ChallengeType; -import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; import org.apache.hc.client5.http.entity.EntityBuilder; import org.apache.hc.client5.http.impl.ConnectionShutdownException; -import org.apache.hc.client5.http.impl.auth.BasicScheme; -import org.apache.hc.client5.http.impl.auth.NTLMScheme; -import org.apache.hc.client5.http.protocol.AuthenticationStrategy; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.protocol.NonRepeatableRequestException; import org.apache.hc.client5.http.protocol.UserTokenHandler; import org.apache.hc.client5.http.sync.ExecChain; import org.apache.hc.client5.http.sync.ExecRuntime; import org.apache.hc.client5.http.sync.methods.HttpGet; -import org.apache.hc.client5.http.sync.methods.HttpPost; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.ConnectionReuseStrategy; import org.apache.hc.core5.http.HttpException; -import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpRequest; -import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.HttpVersion; -import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; -import org.apache.hc.core5.http.protocol.HttpProcessor; import org.apache.hc.core5.util.TimeValue; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @@ -87,27 +63,18 @@ public class TestMainClientExec { @Mock private ConnectionKeepAliveStrategy keepAliveStrategy; @Mock - private HttpProcessor proxyHttpProcessor; - @Mock - private AuthenticationStrategy targetAuthStrategy; - @Mock - private AuthenticationStrategy proxyAuthStrategy; - @Mock private UserTokenHandler userTokenHandler; @Mock private ExecRuntime endpoint; private MainClientExec mainClientExec; private HttpHost target; - private HttpHost proxy; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - mainClientExec = new MainClientExec(reuseStrategy, keepAliveStrategy, proxyHttpProcessor, targetAuthStrategy, - proxyAuthStrategy, userTokenHandler); + mainClientExec = new MainClientExec(reuseStrategy, keepAliveStrategy, userTokenHandler); target = new HttpHost("foo", 80); - proxy = new HttpHost("bar", 8888); } @Test @@ -131,8 +98,6 @@ public class TestMainClientExec { final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint).acquireConnection(route, null, context); - Mockito.verify(endpoint).connect(context); Mockito.verify(endpoint).execute(request, context); Mockito.verify(endpoint, Mockito.times(1)).markConnectionNonReusable(); Mockito.verify(endpoint, Mockito.never()).releaseConnection(); @@ -162,8 +127,6 @@ public class TestMainClientExec { final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint).acquireConnection(route, null, context); - Mockito.verify(endpoint).connect(context); Mockito.verify(endpoint).execute(request, context); Mockito.verify(endpoint).markConnectionNonReusable(); Mockito.verify(endpoint).releaseConnection(); @@ -200,8 +163,6 @@ public class TestMainClientExec { final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint).acquireConnection(route, null, context); - Mockito.verify(endpoint).connect(context); Mockito.verify(endpoint).execute(request, context); Mockito.verify(endpoint).markConnectionReusable(); Mockito.verify(endpoint, Mockito.never()).releaseConnection(); @@ -234,8 +195,6 @@ public class TestMainClientExec { final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint).acquireConnection(route, null, context); - Mockito.verify(endpoint).connect(context); Mockito.verify(endpoint).execute(request, context); Mockito.verify(endpoint).releaseConnection(); @@ -355,355 +314,6 @@ public class TestMainClientExec { } } - @Test - public void testExecRequestRetryOnAuthChallenge() throws Exception { - final HttpRoute route = new HttpRoute(target); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://foo/test"); - final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); - response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); - response1.setEntity(EntityBuilder.create() - .setStream(instream1) - .build()); - final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); - final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); - response2.setEntity(EntityBuilder.create() - .setStream(instream2) - .build()); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); - context.setCredentialsProvider(credentialsProvider); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.same(request), - Mockito.any())).thenReturn(response1, response2); - Mockito.when(reuseStrategy.keepAlive( - Mockito.same(request), - Mockito.any(), - Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(targetAuthStrategy.select( - Mockito.eq(ChallengeType.TARGET), - Mockito.>any(), - Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); - Mockito.when(endpoint.isConnectionReusable()).thenReturn(true); - - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); - final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint, Mockito.times(2)).execute(request, context); - Mockito.verify(instream1).close(); - Mockito.verify(instream2, Mockito.never()).close(); - - Assert.assertNotNull(finalResponse); - Assert.assertEquals(200, finalResponse.getCode()); - } - - @Test - public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exception { - final HttpRoute route = new HttpRoute(target, proxy); - final ClassicHttpRequest request = new HttpGet("http://foo/test"); - final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); - response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); - response1.setEntity(EntityBuilder.create() - .setStream(instream1) - .build()); - final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); - final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); - response2.setEntity(EntityBuilder.create() - .setStream(instream2) - .build()); - - final HttpClientContext context = new HttpClientContext(); - - final AuthExchange proxyAuthExchange = new AuthExchange(); - proxyAuthExchange.setState(AuthExchange.State.SUCCESS); - proxyAuthExchange.select(new NTLMScheme()); - context.setAuthExchange(proxy, proxyAuthExchange); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); - context.setCredentialsProvider(credentialsProvider); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.same(request), - Mockito.any())).thenReturn(response1, response2); - Mockito.when(reuseStrategy.keepAlive( - Mockito.same(request), - Mockito.any(), - Mockito.any())).thenReturn(Boolean.FALSE); - - Mockito.when(targetAuthStrategy.select( - Mockito.eq(ChallengeType.TARGET), - Mockito.>any(), - Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); - - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); - final ClassicHttpResponse finalResponse = mainClientExec.execute(request, scope, null); - Mockito.verify(endpoint, Mockito.times(2)).execute(request, context); - Mockito.verify(endpoint).disconnect(); - Mockito.verify(instream2, Mockito.never()).close(); - - Assert.assertNotNull(finalResponse); - Assert.assertEquals(200, finalResponse.getCode()); - Assert.assertNull(proxyAuthExchange.getAuthScheme()); - } - - @Test(expected = NonRepeatableRequestException.class) - public void testExecEntityEnclosingRequest() throws Exception { - final HttpRoute route = new HttpRoute(target); - final HttpClientContext context = new HttpClientContext(); - final HttpPost request = new HttpPost("http://foo/test"); - final InputStream instream0 = new ByteArrayInputStream(new byte[] {1, 2, 3}); - request.setEntity(EntityBuilder.create() - .setStream(instream0) - .build()); - final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); - response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); - final InputStream instream1 = new ByteArrayInputStream(new byte[] {1, 2, 3}); - response1.setEntity(EntityBuilder.create() - .setStream(instream1) - .build()); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); - context.setCredentialsProvider(credentialsProvider); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.same(request), - Mockito.any())).thenAnswer(new Answer() { - - @Override - public HttpResponse answer(final InvocationOnMock invocationOnMock) throws Throwable { - final Object[] args = invocationOnMock.getArguments(); - final ClassicHttpRequest requestEE = (ClassicHttpRequest) args[0]; - requestEE.getEntity().writeTo(new ByteArrayOutputStream()); - return response1; - } - - }); - Mockito.when(reuseStrategy.keepAlive( - Mockito.same(request), - Mockito.any(), - Mockito.any())).thenReturn(Boolean.TRUE); - - Mockito.when(targetAuthStrategy.select( - Mockito.eq(ChallengeType.TARGET), - Mockito.>any(), - Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); - - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); - mainClientExec.execute(request, scope, null); - } - - @Test - public void testEstablishDirectRoute() throws Exception { - final HttpRoute route = new HttpRoute(target); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - - mainClientExec.establishRoute(route, request, endpoint, context); - - Mockito.verify(endpoint).connect(context); - Mockito.verify(endpoint, Mockito.never()).execute(Mockito.any(), Mockito.any()); - } - - @Test - public void testEstablishRouteDirectProxy() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, false); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - - mainClientExec.establishRoute(route, request, endpoint, context); - - Mockito.verify(endpoint).connect(context); - Mockito.verify(endpoint, Mockito.never()).execute(Mockito.any(), Mockito.any()); - } - - @Test - public void testEstablishRouteViaProxyTunnel() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, true); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK"); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.any(), - Mockito.any())).thenReturn(response); - - mainClientExec.establishRoute(route, request, endpoint, context); - - Mockito.verify(endpoint).connect(context); - final ArgumentCaptor reqCaptor = ArgumentCaptor.forClass(ClassicHttpRequest.class); - Mockito.verify(endpoint).execute( - reqCaptor.capture(), - Mockito.same(context)); - final HttpRequest connect = reqCaptor.getValue(); - Assert.assertNotNull(connect); - Assert.assertEquals("CONNECT", connect.getMethod()); - Assert.assertEquals(HttpVersion.HTTP_1_1, connect.getVersion()); - Assert.assertEquals("foo:80", connect.getRequestUri()); - } - - @Test(expected = HttpException.class) - public void testEstablishRouteViaProxyTunnelUnexpectedResponse() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, true); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - final ClassicHttpResponse response = new BasicClassicHttpResponse(101, "Lost"); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.any(), - Mockito.any())).thenReturn(response); - - mainClientExec.establishRoute(route, request, endpoint, context); - } - - @Test(expected = HttpException.class) - public void testEstablishRouteViaProxyTunnelFailure() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, true); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - final ClassicHttpResponse response = new BasicClassicHttpResponse(500, "Boom"); - response.setEntity(new StringEntity("Ka-boom")); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(endpoint.execute( - Mockito.any(), - Mockito.any())).thenReturn(response); - - try { - mainClientExec.establishRoute(route, request, endpoint, context); - } catch (final TunnelRefusedException ex) { - final ClassicHttpResponse r = ex.getResponse(); - Assert.assertEquals("Ka-boom", EntityUtils.toString(r.getEntity())); - Mockito.verify(endpoint).disconnect(); - Mockito.verify(endpoint).discardConnection(); - throw ex; - } - } - - @Test - public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengePersistentConnection() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, true); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - final ClassicHttpResponse response1 = new BasicClassicHttpResponse(407, "Huh?"); - response1.setHeader(HttpHeaders.PROXY_AUTHENTICATE, "Basic realm=test"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); - response1.setEntity(EntityBuilder.create() - .setStream(instream1) - .build()); - final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("user", "pass".toCharArray())); - context.setCredentialsProvider(credentialsProvider); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(reuseStrategy.keepAlive( - Mockito.same(request), - Mockito.any(), - Mockito.any())).thenReturn(Boolean.TRUE); - Mockito.when(endpoint.execute( - Mockito.any(), - Mockito.any())).thenReturn(response1, response2); - - Mockito.when(proxyAuthStrategy.select( - Mockito.eq(ChallengeType.PROXY), - Mockito.>any(), - Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); - - mainClientExec.establishRoute(route, request, endpoint, context); - - Mockito.verify(endpoint).connect(context); - Mockito.verify(instream1).close(); - } - - @Test - public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengeNonPersistentConnection() throws Exception { - final HttpRoute route = new HttpRoute(target, null, proxy, true); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - final ClassicHttpResponse response1 = new BasicClassicHttpResponse(407, "Huh?"); - response1.setHeader(HttpHeaders.PROXY_AUTHENTICATE, "Basic realm=test"); - final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); - response1.setEntity(EntityBuilder.create() - .setStream(instream1) - .build()); - final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); - - final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("user", "pass".toCharArray())); - context.setCredentialsProvider(credentialsProvider); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - Mockito.when(reuseStrategy.keepAlive( - Mockito.same(request), - Mockito.any(), - Mockito.any())).thenReturn(Boolean.FALSE); - Mockito.when(endpoint.execute( - Mockito.any(), - Mockito.any())).thenReturn(response1, response2); - - Mockito.when(proxyAuthStrategy.select( - Mockito.eq(ChallengeType.PROXY), - Mockito.>any(), - Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); - - mainClientExec.establishRoute(route, request, endpoint, context); - - Mockito.verify(endpoint).connect(context); - Mockito.verify(instream1, Mockito.never()).close(); - Mockito.verify(endpoint).disconnect(); - } - - @Test(expected = HttpException.class) - public void testEstablishRouteViaProxyTunnelMultipleHops() throws Exception { - final HttpHost proxy1 = new HttpHost("this", 8888); - final HttpHost proxy2 = new HttpHost("that", 8888); - final HttpRoute route = new HttpRoute(target, null, new HttpHost[] {proxy1, proxy2}, - true, RouteInfo.TunnelType.TUNNELLED, RouteInfo.LayerType.LAYERED); - final HttpClientContext context = new HttpClientContext(); - final ClassicHttpRequest request = new HttpGet("http://bar/test"); - - final ConnectionState connectionState = new ConnectionState(); - Mockito.doAnswer(connectionState.connectAnswer()).when(endpoint).connect(Mockito.any()); - Mockito.when(endpoint.isConnected()).thenAnswer(connectionState.isConnectedAnswer()); - - mainClientExec.establishRoute(route, request, endpoint, context); - } - static class ConnectionState { private boolean connected; Modified: httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestProtocolExec.java URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestProtocolExec.java?rev=1793325&r1=1793324&r2=1793325&view=diff ============================================================================== --- httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestProtocolExec.java (original) +++ httpcomponents/httpclient/trunk/httpclient5/src/test/java/org/apache/hc/client5/http/impl/sync/TestProtocolExec.java Mon May 1 13:06:48 2017 @@ -26,22 +26,41 @@ */ package org.apache.hc.client5.http.impl.sync; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URI; +import java.util.Collections; +import java.util.Map; import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.auth.AuthChallenge; +import org.apache.hc.client5.http.auth.AuthExchange; +import org.apache.hc.client5.http.auth.AuthScheme; import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.ChallengeType; import org.apache.hc.client5.http.auth.Credentials; import org.apache.hc.client5.http.auth.CredentialsProvider; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.entity.EntityBuilder; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.client5.http.impl.auth.NTLMScheme; +import org.apache.hc.client5.http.protocol.AuthenticationStrategy; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.http.protocol.NonRepeatableRequestException; import org.apache.hc.client5.http.sync.ExecChain; import org.apache.hc.client5.http.sync.ExecRuntime; import org.apache.hc.client5.http.sync.methods.HttpGet; +import org.apache.hc.client5.http.sync.methods.HttpPost; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.EntityDetails; import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.message.BasicClassicHttpResponse; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpProcessor; import org.junit.Assert; @@ -50,6 +69,8 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; @SuppressWarnings({"static-access"}) // test code public class TestProtocolExec { @@ -57,18 +78,24 @@ public class TestProtocolExec { @Mock private HttpProcessor httpProcessor; @Mock + private AuthenticationStrategy targetAuthStrategy; + @Mock + private AuthenticationStrategy proxyAuthStrategy; + @Mock private ExecChain chain; @Mock - private ExecRuntime endpoint; + private ExecRuntime execRuntime; private ProtocolExec protocolExec; private HttpHost target; + private HttpHost proxy; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - protocolExec = new ProtocolExec(httpProcessor); + protocolExec = new ProtocolExec(httpProcessor, targetAuthStrategy, proxyAuthStrategy); target = new HttpHost("foo", 80); + proxy = new HttpHost("bar", 8888); } @Test @@ -83,7 +110,7 @@ public class TestProtocolExec { Mockito.any(), Mockito.any())).thenReturn(response); - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); protocolExec.execute(request, scope, chain); Mockito.verify(httpProcessor).process(request, null, context); @@ -107,7 +134,7 @@ public class TestProtocolExec { Mockito.any(), Mockito.any())).thenReturn(response); - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); protocolExec.execute(request, scope, chain); Assert.assertEquals(new URI("http://bar/test"), request.getUri()); final CredentialsProvider credentialsProvider = context.getCredentialsProvider(); @@ -129,11 +156,11 @@ public class TestProtocolExec { Mockito.any())).thenReturn(response); Mockito.doThrow(new HttpException("Ooopsie")).when(httpProcessor).process( Mockito.same(response), Mockito.isNull(EntityDetails.class), Mockito.any()); - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); try { protocolExec.execute(request, scope, chain); } catch (final Exception ex) { - Mockito.verify(response).close(); + Mockito.verify(execRuntime).discardConnection(); throw ex; } } @@ -150,11 +177,11 @@ public class TestProtocolExec { Mockito.any())).thenReturn(response); Mockito.doThrow(new IOException("Ooopsie")).when(httpProcessor).process( Mockito.same(response), Mockito.isNull(EntityDetails.class), Mockito.any()); - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); try { protocolExec.execute(request, scope, chain); } catch (final Exception ex) { - Mockito.verify(response).close(); + Mockito.verify(execRuntime).discardConnection(); throw ex; } } @@ -171,13 +198,143 @@ public class TestProtocolExec { Mockito.any())).thenReturn(response); Mockito.doThrow(new RuntimeException("Ooopsie")).when(httpProcessor).process( Mockito.same(response), Mockito.isNull(EntityDetails.class), Mockito.any()); - final ExecChain.Scope scope = new ExecChain.Scope(route, request, endpoint, context); + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); try { protocolExec.execute(request, scope, chain); } catch (final Exception ex) { - Mockito.verify(response).close(); + Mockito.verify(execRuntime).discardConnection(); throw ex; } } + @Test + public void testExecRequestRetryOnAuthChallenge() throws Exception { + final HttpRoute route = new HttpRoute(target); + final HttpClientContext context = new HttpClientContext(); + final ClassicHttpRequest request = new HttpGet("http://foo/test"); + final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); + response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); + final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + response1.setEntity(EntityBuilder.create() + .setStream(instream1) + .build()); + final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); + final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); + response2.setEntity(EntityBuilder.create() + .setStream(instream2) + .build()); + + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); + context.setCredentialsProvider(credentialsProvider); + + Mockito.when(chain.proceed( + Mockito.same(request), + Mockito.any())).thenReturn(response1, response2); + Mockito.when(targetAuthStrategy.select( + Mockito.eq(ChallengeType.TARGET), + Mockito.>any(), + Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); + Mockito.when(execRuntime.isConnectionReusable()).thenReturn(true); + + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); + final ClassicHttpResponse finalResponse = protocolExec.execute(request, scope, chain); + Mockito.verify(chain, Mockito.times(2)).proceed(request, scope); + Mockito.verify(instream1).close(); + Mockito.verify(instream2, Mockito.never()).close(); + + Assert.assertNotNull(finalResponse); + Assert.assertEquals(200, finalResponse.getCode()); + } + + @Test + public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exception { + final HttpRoute route = new HttpRoute(target, proxy); + final ClassicHttpRequest request = new HttpGet("http://foo/test"); + final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); + response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); + final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3})); + response1.setEntity(EntityBuilder.create() + .setStream(instream1) + .build()); + final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); + final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4})); + response2.setEntity(EntityBuilder.create() + .setStream(instream2) + .build()); + + final HttpClientContext context = new HttpClientContext(); + + final AuthExchange proxyAuthExchange = new AuthExchange(); + proxyAuthExchange.setState(AuthExchange.State.SUCCESS); + proxyAuthExchange.select(new NTLMScheme()); + context.setAuthExchange(proxy, proxyAuthExchange); + + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); + context.setCredentialsProvider(credentialsProvider); + + Mockito.when(chain.proceed( + Mockito.same(request), + Mockito.any())).thenReturn(response1, response2); + + Mockito.when(targetAuthStrategy.select( + Mockito.eq(ChallengeType.TARGET), + Mockito.>any(), + Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); + + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); + final ClassicHttpResponse finalResponse = protocolExec.execute(request, scope, chain); + Mockito.verify(chain, Mockito.times(2)).proceed(request, scope); + Mockito.verify(execRuntime).disconnect(); + Mockito.verify(instream2, Mockito.never()).close(); + + Assert.assertNotNull(finalResponse); + Assert.assertEquals(200, finalResponse.getCode()); + Assert.assertNull(proxyAuthExchange.getAuthScheme()); + } + + @Test(expected = NonRepeatableRequestException.class) + public void testExecEntityEnclosingRequest() throws Exception { + final HttpRoute route = new HttpRoute(target); + final HttpClientContext context = new HttpClientContext(); + final HttpPost request = new HttpPost("http://foo/test"); + final InputStream instream0 = new ByteArrayInputStream(new byte[] {1, 2, 3}); + request.setEntity(EntityBuilder.create() + .setStream(instream0) + .build()); + final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); + response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=test"); + final InputStream instream1 = new ByteArrayInputStream(new byte[] {1, 2, 3}); + response1.setEntity(EntityBuilder.create() + .setStream(instream1) + .build()); + + final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray())); + context.setCredentialsProvider(credentialsProvider); + + Mockito.when(chain.proceed( + Mockito.same(request), + Mockito.any())).thenAnswer(new Answer() { + + @Override + public HttpResponse answer(final InvocationOnMock invocationOnMock) throws Throwable { + final Object[] args = invocationOnMock.getArguments(); + final ClassicHttpRequest requestEE = (ClassicHttpRequest) args[0]; + requestEE.getEntity().writeTo(new ByteArrayOutputStream()); + return response1; + } + + }); + + Mockito.when(targetAuthStrategy.select( + Mockito.eq(ChallengeType.TARGET), + Mockito.>any(), + Mockito.any())).thenReturn(Collections.singletonList(new BasicScheme())); + + final ExecChain.Scope scope = new ExecChain.Scope(route, request, execRuntime, context); + protocolExec.execute(request, scope, chain); + } + }