From 7626230ffd711f55b00d9a5a0998c501f97045d9 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 29 Oct 2022 19:31:14 +0200 Subject: [PATCH] Fixed integration tests broken by JUnit 5 upgrade --- httpclient5-testing/pom.xml | 2 +- .../AbstractHttp1IntegrationTestBase.java | 136 ---------- ...actHttpAsyncClientAuthenticationTest.java} | 199 +++++++------- .../AbstractHttpAsyncFundamentalsTest.java | 61 +++-- .../async/AbstractHttpAsyncRedirectsTest.java | 200 +++++++++----- .../AbstractHttpReactiveFundamentalsTest.java | 65 +++-- .../async/AbstractIntegrationTestBase.java | 124 +++++---- .../testing/async/AbstractServerTestBase.java | 98 ------- .../testing/async/HttpIntegrationTests.java | 216 +++++++++++++++ .../async/HttpMinimalIntegrationTests.java | 75 ++++++ .../async/ReactiveIntegrationTests.java | 75 ++++++ .../ReactiveMinimalIntegrationTests.java | 75 ++++++ .../async/TestAsyncRequestContext.java | 161 ----------- .../hc/client5/testing/async/TestH2Async.java | 55 +--- .../testing/async/TestH2AsyncMinimal.java | 36 +-- .../testing/async/TestH2AsyncRedirect.java | 58 +--- .../async/TestH2ClientAuthentication.java | 124 ++++----- .../client5/testing/async/TestH2Reactive.java | 53 +--- ...active.java => TestH2ReactiveMinimal.java} | 37 +-- .../client5/testing/async/TestHttp1Async.java | 136 +++------- ...inimal.java => TestHttp1AsyncMinimal.java} | 75 ++---- .../async/TestHttp1AsyncRedirects.java | 117 +++----- .../TestHttp1AsyncStatefulConnManagement.java | 94 ++----- .../async/TestHttp1ClientAuthentication.java | 144 ++++------ .../testing/async/TestHttp1Reactive.java | 126 +++------ ...ive.java => TestHttp1ReactiveMinimal.java} | 78 ++---- .../async/TestHttp1RequestReExecution.java | 114 ++------ .../async/TestHttpAsyncMinimalTls.java | 142 ---------- .../TestHttpAsyncMinimalTlsHandshake.java | 98 +++++++ .../async/TestHttpAsyncProtocolPolicy.java | 94 +++++++ .../async/extension/TestAsyncResources.java | 235 +++++++++++++++++ .../hc/client5/testing/fluent/TestFluent.java | 43 ++- .../testing/sync/LocalServerTestBase.java | 156 ----------- .../sync/TestBasicConnectionManager.java | 40 ++- .../sync/TestClientAuthentication.java | 249 ++++++++++++------ .../TestClientAuthenticationFakeNTLM.java | 85 ++++-- .../sync/TestClientRequestExecution.java | 107 +++++--- .../sync/TestConnectionManagement.java | 194 ++++++++------ .../testing/sync/TestConnectionReuse.java | 141 +++++++--- .../testing/sync/TestContentCodings.java | 121 ++++++--- .../testing/sync/TestCookieVirtualHost.java | 28 +- .../sync/TestIdleConnectionEviction.java | 32 ++- .../TestMinimalClientRequestExecution.java | 36 ++- .../client5/testing/sync/TestRedirects.java | 182 +++++++++---- .../testing/sync/TestSPNegoScheme.java | 48 ++-- .../sync/TestStatefulConnManagement.java | 58 ++-- .../sync/TestWindowsNegotiateScheme.java | 35 ++- .../sync/extension/TestClientResources.java | 167 ++++++++++++ ...ngAsyncClientConnectionManagerBuilder.java | 2 - 49 files changed, 2743 insertions(+), 2284 deletions(-) delete mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java rename httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/{AbstractHttpAsyncClientAuthentication.java => AbstractHttpAsyncClientAuthenticationTest.java} (77%) delete mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractServerTestBase.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpIntegrationTests.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpMinimalIntegrationTests.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveIntegrationTests.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveMinimalIntegrationTests.java delete mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRequestContext.java rename httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/{TestH2MinimalReactive.java => TestH2ReactiveMinimal.java} (52%) rename httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/{TestHttpAsyncMinimal.java => TestHttp1AsyncMinimal.java} (61%) rename httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/{TestHttpMinimalReactive.java => TestHttp1ReactiveMinimal.java} (61%) delete mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTls.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTlsHandshake.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncProtocolPolicy.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/extension/TestAsyncResources.java delete mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/extension/TestClientResources.java diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index 87096e00a..e97ae10cf 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -84,7 +84,7 @@ org.junit.jupiter - junit-jupiter-migrationsupport + junit-jupiter-params test diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java deleted file mode 100644 index 964e1d329..000000000 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.hc.client5.testing.async; - -import java.net.InetSocketAddress; -import java.util.concurrent.Future; - -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.function.Decorator; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.config.Http1Config; -import org.apache.hc.core5.http.impl.HttpProcessors; -import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; -import org.apache.hc.core5.http.protocol.HttpProcessor; -import org.apache.hc.core5.io.CloseMode; -import org.apache.hc.core5.reactor.ListenerEndpoint; -import org.junit.Rule; -import org.junit.rules.ExternalResource; - -public abstract class AbstractHttp1IntegrationTestBase extends AbstractServerTestBase { - - public AbstractHttp1IntegrationTestBase(final URIScheme scheme) { - super(scheme); - } - - public AbstractHttp1IntegrationTestBase() { - super(URIScheme.HTTP); - } - - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - protected CloseableHttpAsyncClient httpclient; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - @Override - protected void after() { - if (httpclient != null) { - httpclient.close(CloseMode.GRACEFUL); - httpclient = null; - } - } - - }; - - public HttpHost start( - final HttpProcessor httpProcessor, - final Decorator exchangeHandlerDecorator, - final Http1Config h1Config) throws Exception { - server.start(httpProcessor, exchangeHandlerDecorator, h1Config); - final Future endpointFuture = server.listen(new InetSocketAddress(0)); - httpclient = clientBuilder.build(); - httpclient.start(); - final ListenerEndpoint endpoint = endpointFuture.get(); - final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress(); - return new HttpHost(scheme.name(), "localhost", address.getPort()); - } - - public HttpHost start( - final HttpProcessor httpProcessor, - final Http1Config h1Config) throws Exception { - return start(httpProcessor, null, h1Config); - } - - public HttpHost start() throws Exception { - return start(HttpProcessors.server(), Http1Config.DEFAULT); - } - -} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthenticationTest.java similarity index 77% rename from httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java rename to httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthenticationTest.java index 7747b3bc1..3dba15041 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthenticationTest.java @@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.hc.client5.http.AuthenticationStrategy; @@ -64,71 +65,63 @@ import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponseInterceptor; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.config.Lookup; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; -import org.apache.hc.core5.http.impl.HttpProcessors; import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; import org.apache.hc.core5.http.support.BasicResponseBuilder; -import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.http2.impl.H2Processors; import org.apache.hc.core5.net.URIAuthority; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.hamcrest.CoreMatchers; -import org.junit.Test; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; -public abstract class AbstractHttpAsyncClientAuthentication extends AbstractIntegrationTestBase { +public abstract class AbstractHttpAsyncClientAuthenticationTest extends AbstractIntegrationTestBase { - protected final HttpVersion protocolVersion; - - public AbstractHttpAsyncClientAuthentication(final URIScheme scheme, final HttpVersion protocolVersion) { + public AbstractHttpAsyncClientAuthenticationTest(final URIScheme scheme) { super(scheme); - this.protocolVersion = protocolVersion; } - @Override - public final HttpHost start() throws Exception { - return start(requestHandler -> new AuthenticatingAsyncDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm"))); + abstract protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception; + + protected H2TestServer startServer() throws Exception { + return startServer(requestHandler -> new AuthenticatingAsyncDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm"))); } - public final HttpHost start( - final Decorator exchangeHandlerDecorator) throws Exception { - if (protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) { - return super.start( - H2Processors.server(), - exchangeHandlerDecorator, - H2Config.DEFAULT); - } else { - return super.start( - HttpProcessors.server(), - exchangeHandlerDecorator, - Http1Config.DEFAULT); - } + interface TestClientBuilder { + + TestClientBuilder setDefaultAuthSchemeRegistry(Lookup authSchemeRegistry); + + TestClientBuilder setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy); + + TestClientBuilder addResponseInterceptor(HttpResponseInterceptor responseInterceptor); + + TestClientBuilder addRequestInterceptor(HttpRequestInterceptor requestInterceptor); + } - abstract void setDefaultAuthSchemeRegistry(Lookup authSchemeRegistry); + abstract protected T startClientCustom(final Consumer clientCustomizer) throws Exception; - abstract void setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy); - - abstract void addResponseInterceptor(HttpResponseInterceptor responseInterceptor); - - abstract void addRequestInterceptor(final HttpRequestInterceptor requestInterceptor); + T startClient() throws Exception { + return startClientCustom(c -> {}); + } @Test public void testBasicAuthenticationNoCreds() throws Exception { + final H2TestServer server = startServer(); server.register("*", AsyncEchoHandler::new); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final T client = startClient(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(credsProvider); - final Future future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(), context, null); @@ -142,8 +135,11 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(), context, null); @@ -165,8 +161,11 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/") @@ -189,15 +188,18 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.put() .setHttpHost(target) .setPath("/") @@ -213,8 +215,11 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.put() .setHttpHost(target) .setPath("/") @@ -236,8 +241,11 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.put() .setHttpHost(target) .setPath("/") @@ -261,11 +269,12 @@ public abstract class AbstractHttpAsyncClientAuthentication builder.setTargetAuthenticationStrategy(authStrategy)); final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(CredentialsProviderBuilder.create() @@ -273,7 +282,7 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(), context, null); @@ -287,15 +296,17 @@ public abstract class AbstractHttpAsyncClientAuthentication responseQueue = new ConcurrentLinkedQueue<>(); - addResponseInterceptor((response, entity, context) - -> responseQueue.add(BasicResponseBuilder.copy(response).build())); - final HttpHost target = start(); + final T client = startClientCustom(builder -> builder + .setTargetAuthenticationStrategy(authStrategy) + .addResponseInterceptor((response, entity, context) + -> responseQueue.add(BasicResponseBuilder.copy(response).build()))); final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() .add(target, "test", "test".toCharArray()) @@ -307,7 +318,7 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath(requestPath) .build(), context, null); @@ -331,7 +342,7 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath(requestPath) .build(), context, null); @@ -350,11 +361,14 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setScheme(target.getSchemeName()) .setAuthority(new URIAuthority("test:test", target.getHostName(), target.getPort())) .setPath("/") @@ -365,7 +379,32 @@ public abstract class AbstractHttpAsyncClientAuthentication new AuthenticatingAsyncDecorator(exchangeHandler, authenticator) { + + @Override + protected void customizeUnauthorizedResponse(final HttpResponse unauthorized) { + unauthorized.removeHeaders(HttpHeaders.WWW_AUTHENTICATE); + unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, "MyBasic realm=\"test realm\""); + } + + }); server.register("*", AsyncEchoHandler::new); + final HttpHost target = targetHost(); + final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any())) .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray())); @@ -382,32 +421,8 @@ public abstract class AbstractHttpAsyncClientAuthentication new AuthenticatingAsyncDecorator(exchangeHandler, authenticator) { - - @Override - protected void customizeUnauthorizedResponse(final HttpResponse unauthorized) { - unauthorized.removeHeaders(HttpHeaders.WWW_AUTHENTICATE); - unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, "MyBasic realm=\"test realm\""); - } - - }); + final T client = startClientCustom(builder -> builder.setDefaultAuthSchemeRegistry(authSchemeRegistry)); final RequestConfig config = RequestConfig.custom() .setTargetPreferredAuthSchemes(Collections.singletonList("MyBasic")) @@ -421,7 +436,7 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(request, context, null); + final Future future = client.execute(request, context, null); final SimpleHttpResponse response = future.get(); Assertions.assertNotNull(response); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); @@ -430,16 +445,18 @@ public abstract class AbstractHttpAsyncClientAuthentication new AuthenticatingAsyncDecorator(exchangeHandler, new BasicTestAuthenticator("test:test", "test realm")) { + + @Override + protected void customizeUnauthorizedResponse(final HttpResponse unauthorized) { + unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"test realm\" invalid"); + } + + }); server.register("*", AsyncEchoHandler::new); - final HttpHost target = start( - exchangeHandler -> new AuthenticatingAsyncDecorator(exchangeHandler, new BasicTestAuthenticator("test:test", "test realm")) { + final HttpHost target = targetHost(); - @Override - protected void customizeUnauthorizedResponse(final HttpResponse unauthorized) { - unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"test realm\" invalid"); - } - - }); + final T client = startClient(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any())) @@ -447,7 +464,7 @@ public abstract class AbstractHttpAsyncClientAuthentication future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/") .build(), context, null); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncFundamentalsTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncFundamentalsTest.java index fd6ceff92..05f818b3e 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncFundamentalsTest.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncFundamentalsTest.java @@ -53,20 +53,28 @@ import org.apache.hc.core5.http.nio.entity.AsyncEntityProducers; import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityConsumer; import org.apache.hc.core5.http.nio.support.BasicRequestProducer; import org.apache.hc.core5.http.nio.support.BasicResponseConsumer; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.hamcrest.CoreMatchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public abstract class AbstractHttpAsyncFundamentalsTest extends AbstractIntegrationTestBase { +public abstract class AbstractHttpAsyncFundamentalsTest extends AbstractIntegrationTestBase { - public AbstractHttpAsyncFundamentalsTest(final URIScheme scheme) { + protected AbstractHttpAsyncFundamentalsTest(final URIScheme scheme) { super(scheme); } + abstract protected H2TestServer startServer() throws Exception; + + abstract protected T startClient() throws Exception; + @Test - public void testSequenctialGetRequests() throws Exception { - final HttpHost target = start(); + public void testSequentialGetRequests() throws Exception { + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + final T client = startClient(); for (int i = 0; i < 3; i++) { - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -81,10 +89,13 @@ public abstract class AbstractHttpAsyncFundamentalsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.head() .setHttpHost(target) .setPath("/random/2048") @@ -98,13 +109,16 @@ public abstract class AbstractHttpAsyncFundamentalsTest> future = httpclient.execute( + final Future> future = client.execute( new BasicRequestProducer(Method.GET, target, "/echo/", AsyncEntityProducers.create(b1, ContentType.APPLICATION_OCTET_STREAM)), new BasicResponseConsumer<>(new BasicAsyncEntityConsumer()), HttpClientContext.create(), null); @@ -119,7 +133,10 @@ public abstract class AbstractHttpAsyncFundamentalsTest>> queue = new LinkedList<>(); for (int i = 0; i < reqCount; i++) { - final Future> future = httpclient.execute( + final Future> future = client.execute( new BasicRequestProducer(Method.POST, target, "/echo/", AsyncEntityProducers.create(b1, ContentType.APPLICATION_OCTET_STREAM)), new BasicResponseConsumer<>(new BasicAsyncEntityConsumer()), HttpClientContext.create(), null); @@ -148,7 +165,10 @@ public abstract class AbstractHttpAsyncFundamentalsTest resultQueue = new ConcurrentLinkedQueue<>(); @@ -161,7 +181,7 @@ public abstract class AbstractHttpAsyncFundamentalsTest 0) { - httpclient.execute( + client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -188,7 +208,7 @@ public abstract class AbstractHttpAsyncFundamentalsTest { if (!Thread.currentThread().isInterrupted()) { - httpclient.execute( + client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -213,8 +233,11 @@ public abstract class AbstractHttpAsyncFundamentalsTest future = httpclient.execute( + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + final T client = startClient(); + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/boom") diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncRedirectsTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncRedirectsTest.java index 3bed9ac0d..0f9d97356 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncRedirectsTest.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncRedirectsTest.java @@ -63,49 +63,43 @@ import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; import org.apache.hc.core5.http.protocol.HttpCoreContext; import org.apache.hc.core5.http2.config.H2Config; import org.apache.hc.core5.net.URIBuilder; -import org.apache.hc.core5.reactive.ReactiveServerExchangeHandler; import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.testing.nio.H2TestServer; -import org.apache.hc.core5.testing.reactive.ReactiveRandomProcessor; import org.apache.hc.core5.util.TimeValue; import org.hamcrest.CoreMatchers; -import org.junit.Test; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -public abstract class AbstractHttpAsyncRedirectsTest extends AbstractIntegrationTestBase { +public abstract class AbstractHttpAsyncRedirectsTest extends AbstractIntegrationTestBase { - protected final HttpVersion version; + private final HttpVersion version; - public AbstractHttpAsyncRedirectsTest(final HttpVersion version, final URIScheme scheme) { + public AbstractHttpAsyncRedirectsTest(final URIScheme scheme, final HttpVersion version) { super(scheme); this.version = version; } - @Override - public final HttpHost start() throws Exception { - if (version.greaterEquals(HttpVersion.HTTP_2)) { - return super.start(null, H2Config.DEFAULT); - } else { - return super.start(null, Http1Config.DEFAULT); - } + abstract protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception; + + protected H2TestServer startServer() throws Exception { + return startServer(null); } - public final HttpHost start(final Decorator exchangeHandlerDecorator) throws Exception { - if (version.greaterEquals(HttpVersion.HTTP_2)) { - return super.start(null, exchangeHandlerDecorator, H2Config.DEFAULT); - } else { - return super.start(null, exchangeHandlerDecorator, Http1Config.DEFAULT); - } - } + abstract protected T startClient() throws Exception; @Test public void testBasicRedirect300() throws Exception { - final HttpHost target = start(exchangeHandler -> new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") @@ -121,11 +115,16 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/100") @@ -142,11 +141,16 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/123") @@ -163,7 +167,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -172,8 +176,13 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/100") @@ -189,11 +198,16 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_SEE_OTHER))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/123") @@ -210,6 +224,8 @@ public abstract class AbstractHttpAsyncRedirectsTest new AbstractSimpleServerExchangeHandler() { @Override @@ -218,9 +234,12 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") @@ -236,6 +255,8 @@ public abstract class AbstractHttpAsyncRedirectsTest new AbstractSimpleServerExchangeHandler() { @Override @@ -244,9 +265,12 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") @@ -262,11 +286,16 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_TEMPORARY_REDIRECT))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/123") @@ -283,16 +312,20 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/", HttpStatus.SC_MOVED_TEMPORARILY))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); final RequestConfig config = RequestConfig.custom() .setCircularRedirectsAllowed(true) .setMaxRedirects(5).build(); final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> { - final Future future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/circular-oldlocation/") .setRequestConfig(config) @@ -304,16 +337,20 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/", HttpStatus.SC_MOVED_TEMPORARILY))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); final RequestConfig config = RequestConfig.custom() .setCircularRedirectsAllowed(false) .build(); final ExecutionException exception = Assertions.assertThrows(ExecutionException.class, () -> { - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/circular-oldlocation/") @@ -326,12 +363,17 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_TEMPORARY_REDIRECT))); + server.register("/echo/*", AsyncEchoHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.post() .setHttpHost(target) .setPath("/oldlocation/stuff") @@ -349,12 +391,17 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_SEE_OTHER))); + server.register("/echo/*", AsyncEchoHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.post() .setHttpHost(target) .setPath("/oldlocation/stuff") @@ -372,7 +419,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -383,9 +430,14 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/stuff") @@ -402,7 +454,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -413,9 +465,14 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/oldlocation") @@ -432,7 +489,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -442,9 +499,13 @@ public abstract class AbstractHttpAsyncRedirectsTest { - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") @@ -456,7 +517,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -466,9 +527,13 @@ public abstract class AbstractHttpAsyncRedirectsTest { - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") @@ -480,11 +545,16 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY))); final CookieStore cookieStore = new BasicCookieStore(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + final HttpClientContext context = HttpClientContext.create(); context.setCookieStore(cookieStore); @@ -494,7 +564,7 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/100") @@ -513,16 +583,11 @@ public abstract class AbstractHttpAsyncRedirectsTest { - if (isReactive()) { - return new ReactiveServerExchangeHandler(new ReactiveRandomProcessor()); - } else { - return new AsyncRandomHandler(); - } - }); + secondServer.register("/random/*", AsyncRandomHandler::new); final InetSocketAddress address2; if (version.greaterEquals(HttpVersion.HTTP_2)) { address2 = secondServer.start(H2Config.DEFAULT); @@ -531,7 +596,7 @@ public abstract class AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, requestUri -> { final String path = requestUri.getPath(); @@ -545,8 +610,13 @@ public abstract class AbstractHttpAsyncRedirectsTest future = httpclient.execute( + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final T client = startClient(); + + final HttpClientContext context = HttpClientContext.create(); + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation") @@ -560,7 +630,7 @@ public abstract class AbstractHttpAsyncRedirectsTest extends AbstractIntegrationTestBase { +public abstract class AbstractHttpReactiveFundamentalsTest extends AbstractIntegrationTestBase { public AbstractHttpReactiveFundamentalsTest(final URIScheme scheme) { super(scheme); } - @Override - protected final boolean isReactive() { - return true; - } + abstract protected H2TestServer startServer() throws Exception; + + abstract protected T startClient() throws Exception; @Test @Timeout(value = 60_000, unit = MILLISECONDS) public void testSequentialGetRequests() throws Exception { - final HttpHost target = start(); + final H2TestServer server = startServer(); + server.register("/random/*", () -> + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); for (int i = 0; i < 3; i++) { final ReactiveResponseConsumer consumer = new ReactiveResponseConsumer(); - httpclient.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); + client.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); final Message> response = consumer.getResponseFuture().get(); assertThat(response, CoreMatchers.notNullValue()); @@ -105,11 +112,15 @@ public abstract class AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); for (int i = 0; i < 3; i++) { final ReactiveResponseConsumer consumer = new ReactiveResponseConsumer(); - httpclient.execute(AsyncRequestBuilder.head(target + "/random/2048").build(), consumer, null); + client.execute(AsyncRequestBuilder.head(target + "/random/2048").build(), consumer, null); final Message> response = consumer.getResponseFuture().get(); assertThat(response, CoreMatchers.notNullValue()); @@ -123,7 +134,11 @@ public abstract class AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveEchoProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); for (int i = 0; i < 3; i++) { final byte[] b1 = new byte[1024]; final Random rnd = new Random(System.currentTimeMillis()); @@ -134,7 +149,7 @@ public abstract class AbstractHttpReactiveFundamentalsTest>> responseFuture = consumer.getResponseFuture(); final Message> responseMessage = responseFuture.get(); @@ -149,7 +164,11 @@ public abstract class AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveEchoProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); final int reqCount = 500; final int maxSize = 128 * 1024; @@ -175,7 +194,7 @@ public abstract class AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); final int requestNum = 50; final AtomicInteger count = new AtomicInteger(requestNum); final Queue>> resultQueue = new ConcurrentLinkedQueue<>(); @@ -207,7 +230,7 @@ public abstract class AbstractHttpReactiveFundamentalsTest 0) { final ReactiveResponseConsumer consumer = new ReactiveResponseConsumer(this); - httpclient.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); + client.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); } } finally { countDownLatch.countDown(); @@ -231,7 +254,7 @@ public abstract class AbstractHttpReactiveFundamentalsTest { if (!Thread.currentThread().isInterrupted()) { final ReactiveResponseConsumer consumer = new ReactiveResponseConsumer(callback); - httpclient.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); + client.execute(AsyncRequestBuilder.get(target + "/random/2048").build(), consumer, null); } }); } @@ -252,11 +275,15 @@ public abstract class AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + final T client = startClient(); final AsyncRequestProducer request = AsyncRequestBuilder.get(target + "/random/boom").build(); final ReactiveResponseConsumer consumer = new ReactiveResponseConsumer(); - httpclient.execute(request, consumer, null); + client.execute(request, consumer, null); final Future>> future = consumer.getResponseFuture(); final HttpResponse response = future.get().getHead(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java index d13a608c9..3e80e3e86 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractIntegrationTestBase.java @@ -27,10 +27,16 @@ package org.apache.hc.client5.testing.async; -import java.net.InetSocketAddress; -import java.util.concurrent.Future; +import java.util.function.Consumer; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient; +import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.testing.async.extension.TestAsyncResources; import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; @@ -38,77 +44,79 @@ import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; import org.apache.hc.core5.http.protocol.HttpProcessor; import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.io.CloseMode; -import org.apache.hc.core5.reactor.ListenerEndpoint; -import org.junit.Rule; -import org.junit.rules.ExternalResource; +import org.apache.hc.core5.testing.nio.H2TestServer; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.extension.RegisterExtension; -public abstract class AbstractIntegrationTestBase extends AbstractServerTestBase { +public abstract class AbstractIntegrationTestBase { - public AbstractIntegrationTestBase(final URIScheme scheme) { - super(scheme); + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private final TestAsyncResources testResources; + + protected AbstractIntegrationTestBase(final URIScheme scheme) { + this.testResources = new TestAsyncResources(scheme, TIMEOUT); } - public AbstractIntegrationTestBase() { - super(URIScheme.HTTP); + public URIScheme scheme() { + return testResources.scheme(); } - protected T httpclient; - - protected abstract T createClient() throws Exception; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void after() { - if (httpclient != null) { - httpclient.close(CloseMode.GRACEFUL); - httpclient = null; - } - } - - }; - - public abstract HttpHost start() throws Exception; - - public final HttpHost start( + public H2TestServer startServer( + final H2Config h2Config, final HttpProcessor httpProcessor, - final Decorator exchangeHandlerDecorator, - final Http1Config h1Config) throws Exception { - server.start(httpProcessor, exchangeHandlerDecorator, h1Config); - final Future endpointFuture = server.listen(new InetSocketAddress(0)); - httpclient = createClient(); - httpclient.start(); - final ListenerEndpoint endpoint = endpointFuture.get(); - final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress(); - return new HttpHost(scheme.name(), "localhost", address.getPort()); + final Decorator exchangeHandlerDecorator) throws Exception { + return testResources.startServer(h2Config, httpProcessor, exchangeHandlerDecorator); } - public final HttpHost start( + public H2TestServer startServer( + final Http1Config http1Config, final HttpProcessor httpProcessor, - final Http1Config h1Config) throws Exception { - return start(httpProcessor, null, h1Config); + final Decorator exchangeHandlerDecorator) throws Exception { + return testResources.startServer(http1Config, httpProcessor, exchangeHandlerDecorator); } - public final HttpHost start( - final HttpProcessor httpProcessor, - final Decorator exchangeHandlerDecorator, - final H2Config h2Config) throws Exception { - server.start(httpProcessor, exchangeHandlerDecorator, h2Config); - final Future endpointFuture = server.listen(new InetSocketAddress(0)); - httpclient = createClient(); - httpclient.start(); - final ListenerEndpoint endpoint = endpointFuture.get(); - final InetSocketAddress address = (InetSocketAddress) endpoint.getAddress(); - return new HttpHost(scheme.name(), "localhost", address.getPort()); + public HttpHost targetHost() { + return testResources.targetHost(); } + public CloseableHttpAsyncClient startClient( + final Consumer connManagerCustomizer, + final Consumer clientCustomizer) throws Exception { + return testResources.startClient(connManagerCustomizer, clientCustomizer); + } - public final HttpHost start( - final HttpProcessor httpProcessor, - final H2Config h2Config) throws Exception { - return start(httpProcessor, null, h2Config); + public CloseableHttpAsyncClient startClient( + final Consumer clientCustomizer) throws Exception { + return testResources.startClient(clientCustomizer); + } + + public PoolingAsyncClientConnectionManager connManager() { + return testResources.connManager(); + } + + public CloseableHttpAsyncClient startH2Client( + final Consumer clientCustomizer) throws Exception { + return testResources.startH2Client(clientCustomizer); + } + + public MinimalHttpAsyncClient startMinimalClient( + final Http1Config http1Config, + final H2Config h2Config, + final Consumer connManagerCustomizer) throws Exception { + return testResources.startMinimalClient(http1Config, h2Config, connManagerCustomizer); + } + + public MinimalHttpAsyncClient startMinimalH2Client( + final Http1Config http1Config, + final H2Config h2Config, + final Consumer connManagerCustomizer) throws Exception { + return testResources.startMinimalClient(http1Config, h2Config, connManagerCustomizer); + } + + public MinimalH2AsyncClient startMinimalH2Client(final H2Config h2Config) throws Exception { + return testResources.startMinimalH2Client(h2Config); } } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractServerTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractServerTestBase.java deleted file mode 100644 index 16a3674af..000000000 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractServerTestBase.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.hc.client5.testing.async; - -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.reactive.ReactiveServerExchangeHandler; -import org.apache.hc.core5.reactor.IOReactorConfig; -import org.apache.hc.core5.testing.nio.H2TestServer; -import org.apache.hc.core5.testing.reactive.ReactiveEchoProcessor; -import org.apache.hc.core5.testing.reactive.ReactiveRandomProcessor; -import org.apache.hc.core5.util.TimeValue; -import org.apache.hc.core5.util.Timeout; -import org.junit.Rule; -import org.junit.rules.ExternalResource; - -public abstract class AbstractServerTestBase { - - public static final Timeout TIMEOUT = Timeout.ofMinutes(1); - public static final Timeout LONG_TIMEOUT = Timeout.ofMinutes(3); - - protected final URIScheme scheme; - - public AbstractServerTestBase(final URIScheme scheme) { - this.scheme = scheme; - } - - public AbstractServerTestBase() { - this(URIScheme.HTTP); - } - - protected H2TestServer server; - - @Rule - public ExternalResource serverResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - server = new H2TestServer( - IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(), - scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null, null, null); - server.register("/echo/*", () -> { - if (isReactive()) { - return new ReactiveServerExchangeHandler(new ReactiveEchoProcessor()); - } else { - return new AsyncEchoHandler(); - } - }); - server.register("/random/*", () -> { - if (isReactive()) { - return new ReactiveServerExchangeHandler(new ReactiveRandomProcessor()); - } else { - return new AsyncRandomHandler(); - } - }); - } - - @Override - protected void after() { - if (server != null) { - server.shutdown(TimeValue.ofSeconds(5)); - server = null; - } - } - - }; - - protected boolean isReactive() { - return false; - } -} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpIntegrationTests.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpIntegrationTests.java new file mode 100644 index 000000000..452919c4d --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpIntegrationTests.java @@ -0,0 +1,216 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import org.apache.hc.core5.http.HttpVersion; +import org.apache.hc.core5.http.URIScheme; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; + +public class HttpIntegrationTests { + + @Nested + @DisplayName("Fundamentals (HTTP/1.1)") + public class Http1 extends TestHttp1Async { + + public Http1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/1.1, TLS)") + public class Http1Tls extends TestHttp1Async { + + public Http1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2)") + public class H2 extends TestH2Async { + + public H2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2, TLS)") + public class H2Tls extends TestH2Async { + + public H2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Request re-execution (HTTP/1.1)") + public class Http1RequestReExecution extends TestHttp1RequestReExecution { + + public Http1RequestReExecution() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Request re-execution (HTTP/1.1, TLS)") + public class Http1RequestReExecutionTls extends TestHttp1RequestReExecution { + + public Http1RequestReExecutionTls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("HTTP protocol policy (HTTP/1.1)") + public class Http1ProtocolPolicy extends TestHttpAsyncProtocolPolicy { + + public Http1ProtocolPolicy() throws Exception { + super(URIScheme.HTTP, HttpVersion.HTTP_1_1); + } + + } + + @Nested + @DisplayName("HTTP protocol policy (HTTP/1.1, TLS)") + public class Http1ProtocolPolicyTls extends TestHttpAsyncProtocolPolicy { + + public Http1ProtocolPolicyTls() throws Exception { + super(URIScheme.HTTPS, HttpVersion.HTTP_1_1); + } + + } + + @Nested + @DisplayName("HTTP protocol policy (HTTP/2)") + public class H2ProtocolPolicy extends TestHttpAsyncProtocolPolicy { + + public H2ProtocolPolicy() throws Exception { + super(URIScheme.HTTP, HttpVersion.HTTP_2); + } + + } + + @Nested + @DisplayName("HTTP protocol policy (HTTP/2, TLS)") + public class H2ProtocolPolicyTls extends TestHttpAsyncProtocolPolicy { + + public H2ProtocolPolicyTls() throws Exception { + super(URIScheme.HTTPS, HttpVersion.HTTP_2); + } + + } + + @Nested + @DisplayName("Redirects (HTTP/1.1)") + public class RedirectsHttp1 extends TestHttp1AsyncRedirects { + + public RedirectsHttp1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Redirects (HTTP/1.1, TLS)") + public class RedirectsHttp1Tls extends TestHttp1AsyncRedirects { + + public RedirectsHttp1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Redirects (HTTP/2)") + public class RedirectsH2 extends TestH2AsyncRedirect { + + public RedirectsH2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Redirects (HTTP/2, TLS)") + public class RedirectsH2Tls extends TestH2AsyncRedirect { + + public RedirectsH2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Client authentication (HTTP/1.1)") + public class AuthenticationHttp1 extends TestHttp1ClientAuthentication { + + public AuthenticationHttp1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Client authentication (HTTP/1.1, TLS)") + public class AuthenticationHttp1Tls extends TestHttp1ClientAuthentication { + + public AuthenticationHttp1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Client authentication (HTTP/2)") + public class AuthenticationH2 extends TestH2ClientAuthentication { + + public AuthenticationH2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Client authentication (HTTP/2, TLS)") + public class AuthenticationH2Tls extends TestH2ClientAuthentication { + + public AuthenticationH2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + +} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpMinimalIntegrationTests.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpMinimalIntegrationTests.java new file mode 100644 index 000000000..fc0169e64 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/HttpMinimalIntegrationTests.java @@ -0,0 +1,75 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import org.apache.hc.core5.http.URIScheme; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; + +public class HttpMinimalIntegrationTests { + + @Nested + @DisplayName("Fundamentals (HTTP/1.1)") + public class Http1 extends TestHttp1AsyncMinimal { + + public Http1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/1.1, TLS)") + public class Http1Tls extends TestHttp1AsyncMinimal { + + public Http1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2)") + public class H2 extends TestH2AsyncMinimal { + + public H2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2, TLS)") + public class H2Tls extends TestH2AsyncMinimal { + + public H2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + +} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveIntegrationTests.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveIntegrationTests.java new file mode 100644 index 000000000..81e49b544 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveIntegrationTests.java @@ -0,0 +1,75 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import org.apache.hc.core5.http.URIScheme; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; + +public class ReactiveIntegrationTests { + + @Nested + @DisplayName("Fundamentals (HTTP/1.1)") + public class Http1 extends TestHttp1Reactive { + + public Http1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/1.1, TLS)") + public class Http1Tls extends TestHttp1Reactive { + + public Http1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2)") + public class H2 extends TestH2Reactive { + + public H2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2, TLS)") + public class H2Tls extends TestH2Reactive { + + public H2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + +} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveMinimalIntegrationTests.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveMinimalIntegrationTests.java new file mode 100644 index 000000000..27a7da833 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/ReactiveMinimalIntegrationTests.java @@ -0,0 +1,75 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import org.apache.hc.core5.http.URIScheme; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; + +public class ReactiveMinimalIntegrationTests { + + @Nested + @DisplayName("Fundamentals (HTTP/1.1)") + public class Http1 extends TestHttp1ReactiveMinimal { + + public Http1() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/1.1, TLS)") + public class Http1Tls extends TestHttp1ReactiveMinimal { + + public Http1Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2)") + public class H2 extends TestH2ReactiveMinimal { + + public H2() throws Exception { + super(URIScheme.HTTP); + } + + } + + @Nested + @DisplayName("Fundamentals (HTTP/2, TLS)") + public class H2Tls extends TestH2ReactiveMinimal { + + public H2Tls() throws Exception { + super(URIScheme.HTTPS); + } + + } + +} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRequestContext.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRequestContext.java deleted file mode 100644 index 6a8797630..000000000 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncRequestContext.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.hc.client5.testing.async; - -import static org.hamcrest.MatcherAssert.assertThat; - -import java.util.Arrays; -import java.util.Collection; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; -import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.config.TlsConfig; -import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.HttpVersion; -import org.apache.hc.core5.http.ProtocolVersion; -import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.config.Http1Config; -import org.apache.hc.core5.http2.HttpVersionPolicy; -import org.apache.hc.core5.http2.config.H2Config; -import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestAsyncRequestContext extends AbstractIntegrationTestBase { - - @Parameterized.Parameters(name = "{0} {1}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { HttpVersion.HTTP_1_1, URIScheme.HTTP }, - { HttpVersion.HTTP_1_1, URIScheme.HTTPS }, - { HttpVersion.HTTP_2, URIScheme.HTTP }, - { HttpVersion.HTTP_2, URIScheme.HTTPS } - }); - } - - protected final HttpVersion version; - - public TestAsyncRequestContext(final HttpVersion version, final URIScheme scheme) { - super(scheme); - this.version = version; - } - - HttpAsyncClientBuilder clientBuilder; - PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager.setDefaultTlsConfig(TlsConfig.custom() - .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1) - .build()); - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; - - @Override - public final HttpHost start() throws Exception { - if (version.greaterEquals(HttpVersion.HTTP_2)) { - return super.start(null, H2Config.DEFAULT); - } else { - return super.start(null, Http1Config.DEFAULT); - } - } - - @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); - } - - @Test - public void testRequestContext() throws Exception { - final AtomicReference versionRef = new AtomicReference<>(); - clientBuilder.addRequestInterceptorFirst((request, entity, context) -> - versionRef.set(context.getProtocolVersion())); - final HttpHost target = start(); - final Future future = httpclient.execute( - SimpleRequestBuilder.get() - .setHttpHost(target) - .setPath("/random/2048") - .build(), null); - final SimpleHttpResponse response = future.get(); - assertThat(response, CoreMatchers.notNullValue()); - assertThat(response.getCode(), CoreMatchers.equalTo(200)); - final String body = response.getBodyText(); - assertThat(body, CoreMatchers.notNullValue()); - assertThat(body.length(), CoreMatchers.equalTo(2048)); - assertThat(versionRef.get(), CoreMatchers.equalTo(version)); - } - -} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java index 95626a646..e6485229c 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java @@ -26,68 +26,25 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; - -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy; import org.apache.hc.core5.http2.config.H2Config; -import org.junit.Rule; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.testing.nio.H2TestServer; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestH2Async extends AbstractHttpAsyncFundamentalsTest { - - @Parameterized.Parameters(name = "HTTP/2 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS } - }); - } - - protected H2AsyncClientBuilder clientBuilder; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = H2AsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext())); - } - - }; +public abstract class TestH2Async extends AbstractHttpAsyncFundamentalsTest { public TestH2Async(final URIScheme scheme) { super(scheme); } @Override - protected CloseableHttpAsyncClient createClient() { - return clientBuilder.build(); + protected H2TestServer startServer() throws Exception { + return startServer(H2Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, H2Config.DEFAULT); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startH2Client(b -> {}); } } \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncMinimal.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncMinimal.java index 9116f1829..81785aa34 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncMinimal.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncMinimal.java @@ -26,49 +26,25 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; - -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.reactor.IOReactorConfig; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.testing.nio.H2TestServer; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestH2AsyncMinimal extends AbstractHttpAsyncFundamentalsTest { - - @Parameterized.Parameters(name = "{0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS }, - }); - } +public abstract class TestH2AsyncMinimal extends AbstractHttpAsyncFundamentalsTest { public TestH2AsyncMinimal(final URIScheme scheme) { super(scheme); } @Override - protected MinimalH2AsyncClient createClient() throws Exception { - final IOReactorConfig ioReactorConfig = IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(); - return HttpAsyncClients.createHttp2Minimal( - H2Config.DEFAULT, ioReactorConfig, new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + protected H2TestServer startServer() throws Exception { + return startServer(H2Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, H2Config.DEFAULT); + protected MinimalH2AsyncClient startClient() throws Exception { + return startMinimalH2Client(H2Config.DEFAULT); } } \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java index 4a32c57d2..78d7aebd5 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java @@ -26,62 +26,28 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; - -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; +import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.URIScheme; -import org.junit.Rule; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.testing.nio.H2TestServer; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestH2AsyncRedirect extends AbstractHttpAsyncRedirectsTest { - - @Parameterized.Parameters(name = "HTTP/2 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS } - }); - } - - protected H2AsyncClientBuilder clientBuilder; +public abstract class TestH2AsyncRedirect extends AbstractHttpAsyncRedirectsTest { public TestH2AsyncRedirect(final URIScheme scheme) { - super(HttpVersion.HTTP_2, scheme); + super(scheme, HttpVersion.HTTP_2); } - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = H2AsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); - } - - }; + @Override + protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception { + return startServer(H2Config.DEFAULT, null, exchangeHandlerDecorator); + } @Override - protected CloseableHttpAsyncClient createClient() { - return clientBuilder.build(); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startH2Client(b -> {}); } } \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java index e18e54b9d..af0f21a40 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java @@ -26,89 +26,71 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; +import java.util.function.Consumer; import org.apache.hc.client5.http.AuthenticationStrategy; import org.apache.hc.client5.http.auth.AuthSchemeFactory; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; +import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.HttpResponseInterceptor; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Lookup; -import org.junit.Rule; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.testing.nio.H2TestServer; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestH2ClientAuthentication extends AbstractHttpAsyncClientAuthentication { +public abstract class TestH2ClientAuthentication extends AbstractHttpAsyncClientAuthenticationTest { + + public TestH2ClientAuthentication(final URIScheme scheme) { + super(scheme); + } + + @Override + protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception { + return startServer(H2Config.DEFAULT, null, exchangeHandlerDecorator); + } + + @Override + protected CloseableHttpAsyncClient startClientCustom(final Consumer clientCustomizer) throws Exception { + + return startH2Client(new Consumer() { + + @Override + public void accept(final H2AsyncClientBuilder builder) { + + clientCustomizer.accept(new TestClientBuilder() { + + @Override + public TestClientBuilder setDefaultAuthSchemeRegistry(final Lookup authSchemeRegistry) { + builder.setDefaultAuthSchemeRegistry(authSchemeRegistry); + return this; + } + + @Override + public TestClientBuilder setTargetAuthenticationStrategy(final AuthenticationStrategy targetAuthStrategy) { + builder.setTargetAuthenticationStrategy(targetAuthStrategy); + return this; + } + + @Override + public TestClientBuilder addResponseInterceptor(final HttpResponseInterceptor responseInterceptor) { + builder.addResponseInterceptorLast(responseInterceptor); + return this; + } + + @Override + public TestClientBuilder addRequestInterceptor(final HttpRequestInterceptor requestInterceptor) { + builder.addRequestInterceptorFirst(requestInterceptor); + return this; + } + + }); + + } - @Parameterized.Parameters(name = "HTTP/2 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - {URIScheme.HTTP}, - {URIScheme.HTTPS}, }); } - protected H2AsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = H2AsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); - } - - }; - - public TestH2ClientAuthentication(final URIScheme scheme) { - super(scheme, HttpVersion.HTTP_2); - } - - @Override - void setDefaultAuthSchemeRegistry(final Lookup authSchemeRegistry) { - clientBuilder.setDefaultAuthSchemeRegistry(authSchemeRegistry); - } - - @Override - void setTargetAuthenticationStrategy(final AuthenticationStrategy targetAuthStrategy) { - clientBuilder.setTargetAuthenticationStrategy(targetAuthStrategy); - } - - @Override - void addResponseInterceptor(final HttpResponseInterceptor responseInterceptor) { - clientBuilder.addResponseInterceptorLast(responseInterceptor); - } - - @Override - void addRequestInterceptor(final HttpRequestInterceptor requestInterceptor) { - clientBuilder.addRequestInterceptorLast(requestInterceptor); - } - - @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); - } - } \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java index 989e51c09..50d940335 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java @@ -26,66 +26,25 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; - -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy; import org.apache.hc.core5.http2.config.H2Config; -import org.junit.Rule; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.testing.nio.H2TestServer; -@RunWith(Parameterized.class) -public class TestH2Reactive extends AbstractHttpReactiveFundamentalsTest { - - @Parameterized.Parameters(name = "HTTP/2 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS } - }); - } - - protected H2AsyncClientBuilder clientBuilder; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = H2AsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext())); - } - - }; +public abstract class TestH2Reactive extends AbstractHttpReactiveFundamentalsTest { public TestH2Reactive(final URIScheme scheme) { super(scheme); } @Override - protected CloseableHttpAsyncClient createClient() { - return clientBuilder.build(); + protected H2TestServer startServer() throws Exception { + return startServer(H2Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, H2Config.DEFAULT); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startH2Client(b -> {}); } } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2MinimalReactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ReactiveMinimal.java similarity index 52% rename from httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2MinimalReactive.java rename to httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ReactiveMinimal.java index 8fbcc573c..ffaf9104f 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2MinimalReactive.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ReactiveMinimal.java @@ -26,47 +26,26 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; - -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.reactor.IOReactorConfig; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.apache.hc.core5.testing.nio.H2TestServer; -@RunWith(Parameterized.class) -public class TestH2MinimalReactive extends AbstractHttpReactiveFundamentalsTest { +public abstract class TestH2ReactiveMinimal extends AbstractHttpReactiveFundamentalsTest { - @Parameterized.Parameters(name = "{0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS }, - }); - } - - public TestH2MinimalReactive(final URIScheme scheme) { + public TestH2ReactiveMinimal(final URIScheme scheme) { super(scheme); } @Override - protected MinimalH2AsyncClient createClient() throws Exception { - final IOReactorConfig ioReactorConfig = IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(); - return HttpAsyncClients.createHttp2Minimal( - H2Config.DEFAULT, ioReactorConfig, new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + protected H2TestServer startServer() throws Exception { + return startServer(H2Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, H2Config.DEFAULT); + protected MinimalH2AsyncClient startClient() throws Exception { + return startMinimalH2Client(H2Config.DEFAULT); } + } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java index 0fdafe7a1..3e20f86ad 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java @@ -28,8 +28,6 @@ package org.apache.hc.client5.testing.async; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.Arrays; -import java.util.Collection; import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -39,100 +37,49 @@ import java.util.concurrent.TimeoutException; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest { - - @Parameterized.Parameters(name = "HTTP/1.1 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS }, - }); - } - - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; +public abstract class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest { public TestHttp1Async(final URIScheme scheme) { super(scheme); } @Override - protected CloseableHttpAsyncClient createClient() { - return clientBuilder.build(); + protected H2TestServer startServer() throws Exception { + return startServer(Http1Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, Http1Config.DEFAULT); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startClient(b -> {}); } - @Test - public void testSequenctialGetRequestsCloseConnection() throws Exception { - final HttpHost target = start(); + @ParameterizedTest(name = "{displayName}; concurrent connections: {0}") + @ValueSource(ints = {5, 1, 20}) + public void testSequentialGetRequestsCloseConnection(final int concurrentConns) throws Exception { + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final PoolingAsyncClientConnectionManager connManager = connManager(); + connManager.setDefaultMaxPerRoute(concurrentConns); + connManager.setMaxTotal(100); for (int i = 0; i < 3; i++) { - final Future future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -147,24 +94,15 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest future1 = httpclient.execute( + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final PoolingAsyncClientConnectionManager connManager = connManager(); + final Future future1 = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -195,7 +133,7 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest future3 = httpclient.execute( + final Future future3 = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -210,16 +148,20 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/1000") @@ -243,7 +185,7 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/1000") @@ -266,7 +208,7 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest future = httpclient.execute( + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/1000") diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncMinimal.java similarity index 61% rename from httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java rename to httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncMinimal.java index 60e4dd473..e801b410a 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncMinimal.java @@ -28,25 +28,17 @@ package org.apache.hc.client5.testing.async; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.Arrays; -import java.util.Collection; import java.util.LinkedList; import java.util.Queue; import java.util.Random; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.apache.hc.client5.http.config.TlsConfig; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.Message; import org.apache.hc.core5.http.Method; import org.apache.hc.core5.http.URIScheme; @@ -56,72 +48,45 @@ import org.apache.hc.core5.http.nio.entity.AsyncEntityProducers; import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityConsumer; import org.apache.hc.core5.http.nio.support.BasicRequestProducer; import org.apache.hc.core5.http.nio.support.BasicResponseConsumer; -import org.apache.hc.core5.http2.HttpVersionPolicy; import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.hamcrest.CoreMatchers; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttpAsyncMinimal extends AbstractHttpAsyncFundamentalsTest { +public abstract class TestHttp1AsyncMinimal extends AbstractHttpAsyncFundamentalsTest { - @Parameterized.Parameters(name = "Minimal {0} {1}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { HttpVersion.HTTP_1_1, URIScheme.HTTP }, - { HttpVersion.HTTP_1_1, URIScheme.HTTPS }, - { HttpVersion.HTTP_2, URIScheme.HTTP }, - { HttpVersion.HTTP_2, URIScheme.HTTPS } - }); - } - - protected final HttpVersion version; - - public TestHttpAsyncMinimal(final HttpVersion version, final URIScheme scheme) { + public TestHttp1AsyncMinimal(final URIScheme scheme) { super(scheme); - this.version = version; } @Override - protected MinimalHttpAsyncClient createClient() throws Exception { - return HttpAsyncClients.createMinimal( - H2Config.DEFAULT, + protected H2TestServer startServer() throws Exception { + return startServer(Http1Config.DEFAULT, null, null); + } + + @Override + protected MinimalHttpAsyncClient startClient() throws Exception { + return startMinimalClient( Http1Config.DEFAULT, - IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(), - PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultTlsConfig(TlsConfig.custom() - .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) - ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1) - .build()) - .build()); - } - - @Override - public HttpHost start() throws Exception { - if (version.greaterEquals(HttpVersion.HTTP_2)) { - return super.start(null, H2Config.DEFAULT); - } else { - return super.start(null, Http1Config.DEFAULT); - } + H2Config.DEFAULT, + b -> {}); } @Test public void testConcurrentPostRequestsSameEndpoint() throws Exception { - final HttpHost target = start(); + final H2TestServer server = startServer(); + server.register("/echo/*", AsyncEchoHandler::new); + final HttpHost target = targetHost(); + + final MinimalHttpAsyncClient client = startClient(); + final byte[] b1 = new byte[1024]; final Random rnd = new Random(System.currentTimeMillis()); rnd.nextBytes(b1); final int reqCount = 20; - final Future endpointLease = httpclient.lease(target, null); + final Future endpointLease = client.lease(target, null); final AsyncClientEndpoint endpoint = endpointLease.get(5, TimeUnit.SECONDS); try { final Queue>> queue = new LinkedList<>(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java index fe7ab64fc..77d47461e 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java @@ -27,24 +27,16 @@ package org.apache.hc.client5.testing.async; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.concurrent.Future; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.client5.testing.OldPathRedirectResolver; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.client5.testing.redirect.Redirect; +import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; @@ -53,88 +45,45 @@ import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.message.BasicHeader; -import org.junit.Test; +import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.junit.jupiter.api.Assertions; -import org.junit.Rule; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; /** * Redirection test cases. */ -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest { - - @Parameterized.Parameters(name = "HTTP/1.1 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - {URIScheme.HTTP}, - {URIScheme.HTTPS}, - }); - } - - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; +public abstract class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest { public TestHttp1AsyncRedirects(final URIScheme scheme) { - super(HttpVersion.HTTP_1_1, scheme); + super(scheme, HttpVersion.HTTP_1_1); } - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; + @Override + protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception { + return startServer(Http1Config.DEFAULT, null, exchangeHandlerDecorator); + } @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startClient(b -> {}); } @Test public void testBasicRedirect300NoKeepAlive() throws Exception { - final HttpHost target = start(exchangeHandler -> new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES, Redirect.ConnControl.CLOSE))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/") .build(), context, null); @@ -149,12 +98,17 @@ public class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY, Redirect.ConnControl.CLOSE))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final HttpClientContext context = HttpClientContext.create(); - final Future future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/100") .build(), context, null); @@ -170,18 +124,21 @@ public class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest defaultHeaders = new ArrayList<>(1); - defaultHeaders.add(new BasicHeader(HttpHeaders.USER_AGENT, "my-test-client")); - clientBuilder.setDefaultHeaders(defaultHeaders); - - final HttpHost target = start(exchangeHandler -> new RedirectingAsyncDecorator( + final H2TestServer server = startServer(exchangeHandler -> new RedirectingAsyncDecorator( exchangeHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY, Redirect.ConnControl.CLOSE))); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final List
defaultHeaders = new ArrayList<>(1); + defaultHeaders.add(new BasicHeader(HttpHeaders.USER_AGENT, "my-test-client")); + final CloseableHttpAsyncClient client = startClient(builder -> builder + .setDefaultHeaders(defaultHeaders) + ); final HttpClientContext context = HttpClientContext.create(); - - final Future future = httpclient.execute(SimpleRequestBuilder.get() + final Future future = client.execute(SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/oldlocation/123") .build(), context, null); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java index 4414df57b..7abff2973 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java @@ -28,90 +28,41 @@ package org.apache.hc.client5.testing.async; import java.util.concurrent.Future; -import org.apache.hc.client5.http.UserTokenHandler; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.EndpointDetails; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.protocol.BasicHttpContext; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpCoreContext; import org.apache.hc.core5.net.URIAuthority; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.junit.jupiter.api.Assertions; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExternalResource; +import org.junit.jupiter.api.Test; -public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTestBase { +public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTestBase { - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; - - @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); + public TestHttp1AsyncStatefulConnManagement() { + super(URIScheme.HTTP); } - @Override - public HttpHost start() throws Exception { - return super.start(null, Http1Config.DEFAULT); + protected H2TestServer startServer() throws Exception { + return startServer(Http1Config.DEFAULT, null, null); } @Test public void testStatefulConnections() throws Exception { + final H2TestServer server = startServer(); server.register("*", () -> new AbstractSimpleServerExchangeHandler() { @Override @@ -124,9 +75,10 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes } }); - final UserTokenHandler userTokenHandler = (route, context) -> context.getAttribute("user"); - clientBuilder.setUserTokenHandler(userTokenHandler); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(builer -> builer + .setUserTokenHandler((route, context) -> context.getAttribute("user"))); final int workerCount = 2; final int requestCount = 5; @@ -138,14 +90,14 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes contexts[i] = context; workers[i] = new HttpWorker( "user" + i, - context, requestCount, target, httpclient); + context, requestCount, target, client); } for (final HttpWorker worker : workers) { worker.start(); } for (final HttpWorker worker : workers) { - worker.join(LONG_TIMEOUT.toMilliseconds()); + worker.join(TIMEOUT.toMilliseconds()); } for (final HttpWorker worker : workers) { final Exception ex = worker.getException(); @@ -226,6 +178,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes @Test public void testRouteSpecificPoolRecylcing() throws Exception { + final H2TestServer server = startServer(); server.register("*", () -> new AbstractSimpleServerExchangeHandler() { @Override @@ -241,10 +194,13 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes // This tests what happens when a maxed connection pool needs // to kill the last idle connection to a route to build a new // one to the same route. - final UserTokenHandler userTokenHandler = (route, context) -> context.getAttribute("user"); - clientBuilder.setUserTokenHandler(userTokenHandler); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(builer -> builer + .setUserTokenHandler((route, context) -> context.getAttribute("user"))); + final PoolingAsyncClientConnectionManager connManager = connManager(); + final int maxConn = 2; // We build a client with 2 max active // connections, and 2 max per route. connManager.setMaxTotal(maxConn); @@ -258,7 +214,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes .setHttpHost(target) .setPath("/") .build(); - final Future future1 = httpclient.execute(request1, context1, null); + final Future future1 = client.execute(request1, context1, null); final HttpResponse response1 = future1.get(); Assertions.assertNotNull(response1); Assertions.assertEquals(200, response1.getCode()); @@ -278,7 +234,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes .setAuthority(new URIAuthority("127.0.0.1", target.getPort())) .setPath("/") .build(); - final Future future2 = httpclient.execute(request2, context2, null); + final Future future2 = client.execute(request2, context2, null); final HttpResponse response2 = future2.get(); Assertions.assertNotNull(response2); Assertions.assertEquals(200, response2.getCode()); @@ -300,7 +256,7 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes .setHttpHost(target) .setPath("/") .build(); - final Future future3 = httpclient.execute(request3, context3, null); + final Future future3 = client.execute(request3, context3, null); final HttpResponse response3 = future3.get(); Assertions.assertNotNull(response3); Assertions.assertEquals(200, response3.getCode()); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java index 4b0012d46..00702a64b 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java @@ -26,9 +26,8 @@ */ package org.apache.hc.client5.testing.async; -import java.util.Arrays; -import java.util.Collection; import java.util.concurrent.Future; +import java.util.function.Consumer; import org.apache.hc.client5.http.AuthenticationStrategy; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; @@ -38,16 +37,11 @@ import org.apache.hc.client5.http.auth.AuthSchemeFactory; import org.apache.hc.client5.http.auth.AuthScope; import org.apache.hc.client5.http.auth.CredentialsProvider; import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; import org.apache.hc.client5.testing.BasicTestAuthenticator; -import org.apache.hc.client5.testing.SSLTestContexts; +import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; @@ -55,115 +49,81 @@ import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpResponseInterceptor; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.config.Lookup; -import org.apache.hc.core5.http.impl.HttpProcessors; +import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.junit.jupiter.api.Assertions; -import org.junit.Rule; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthentication { - - @Parameterized.Parameters(name = "HTTP/1.1 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - {URIScheme.HTTP}, - {URIScheme.HTTPS}, - }); - } - - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; +public abstract class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthenticationTest { public TestHttp1ClientAuthentication(final URIScheme scheme) { - super(scheme, HttpVersion.HTTP_1_1); + super(scheme); } @Override - void setDefaultAuthSchemeRegistry(final Lookup authSchemeRegistry) { - clientBuilder.setDefaultAuthSchemeRegistry(authSchemeRegistry); + protected H2TestServer startServer(final Decorator exchangeHandlerDecorator) throws Exception { + return startServer(Http1Config.DEFAULT, null, exchangeHandlerDecorator); } @Override - void setTargetAuthenticationStrategy(final AuthenticationStrategy targetAuthStrategy) { - clientBuilder.setTargetAuthenticationStrategy(targetAuthStrategy); - } + protected CloseableHttpAsyncClient startClientCustom(final Consumer clientCustomizer) throws Exception { - @Override - void addResponseInterceptor(final HttpResponseInterceptor responseInterceptor) { - clientBuilder.addResponseInterceptorLast(responseInterceptor); - } + return startClient(new Consumer() { - @Override - void addRequestInterceptor(final HttpRequestInterceptor requestInterceptor) { - clientBuilder.addRequestInterceptorLast(requestInterceptor); - } + @Override + public void accept(final HttpAsyncClientBuilder builder) { - @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); + clientCustomizer.accept(new TestClientBuilder() { + + @Override + public TestClientBuilder setDefaultAuthSchemeRegistry(final Lookup authSchemeRegistry) { + builder.setDefaultAuthSchemeRegistry(authSchemeRegistry); + return this; + } + + @Override + public TestClientBuilder setTargetAuthenticationStrategy(final AuthenticationStrategy targetAuthStrategy) { + builder.setTargetAuthenticationStrategy(targetAuthStrategy); + return this; + } + + @Override + public TestClientBuilder addResponseInterceptor(final HttpResponseInterceptor responseInterceptor) { + builder.addResponseInterceptorLast(responseInterceptor); + return this; + } + + @Override + public TestClientBuilder addRequestInterceptor(final HttpRequestInterceptor requestInterceptor) { + builder.addRequestInterceptorFirst(requestInterceptor); + return this; + } + + }); + + } + + }); } @Test public void testBasicAuthenticationSuccessNonPersistentConnection() throws Exception { - server.register("*", AsyncEchoHandler::new); - final HttpHost target = start( - HttpProcessors.server(), - exchangeHandler -> new AuthenticatingAsyncDecorator(exchangeHandler, new BasicTestAuthenticator("test:test", "test realm")) { + final H2TestServer server = startServer(exchangeHandler -> + new AuthenticatingAsyncDecorator(exchangeHandler, new BasicTestAuthenticator("test:test", "test realm")) { @Override protected void customizeUnauthorizedResponse(final HttpResponse unauthorized) { unauthorized.addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE); } - }, - Http1Config.DEFAULT); + }); + server.register("*", AsyncEchoHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any())) @@ -175,7 +135,7 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen .setHttpHost(target) .setPath("/") .build(); - final Future future = httpclient.execute(request, context, null); + final Future future = client.execute(request, context, null); final HttpResponse response = future.get(); Assertions.assertNotNull(response); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java index 19ffc628e..e0d6fe336 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java @@ -30,20 +30,12 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.hamcrest.MatcherAssert.assertThat; import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.Collection; import org.apache.hc.client5.http.async.methods.SimpleHttpRequest; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.core5.http.HeaderElements; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; @@ -54,85 +46,46 @@ import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.nio.AsyncRequestProducer; import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder; import org.apache.hc.core5.reactive.ReactiveResponseConsumer; +import org.apache.hc.core5.reactive.ReactiveServerExchangeHandler; +import org.apache.hc.core5.testing.nio.H2TestServer; +import org.apache.hc.core5.testing.reactive.ReactiveRandomProcessor; import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.reactivestreams.Publisher; -@RunWith(Parameterized.class) -public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest { - - @Parameterized.Parameters(name = "HTTP/1.1 {0}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { URIScheme.HTTP }, - { URIScheme.HTTPS }, - }); - } - - protected HttpAsyncClientBuilder clientBuilder; - protected PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .setSocketTimeout(TIMEOUT) - .build()) - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; +public abstract class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest { public TestHttp1Reactive(final URIScheme scheme) { super(scheme); } @Override - protected CloseableHttpAsyncClient createClient() { - return clientBuilder.build(); + protected H2TestServer startServer() throws Exception { + return startServer(Http1Config.DEFAULT, null, null); } @Override - public HttpHost start() throws Exception { - return super.start(null, Http1Config.DEFAULT); + protected CloseableHttpAsyncClient startClient() throws Exception { + return startClient(b -> {}); } - @Test + @ParameterizedTest(name = "{displayName}; concurrent connections: {0}") + @ValueSource(ints = {5, 1, 20}) @Timeout(value = 60_000, unit = MILLISECONDS) - public void testSequentialGetRequestsCloseConnection() throws Exception { - final HttpHost target = start(); + public void testSequentialGetRequestsCloseConnection(final int concurrentConns) throws Exception { + final H2TestServer server = startServer(); + server.register("/random/*", () -> + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final PoolingAsyncClientConnectionManager connManager = connManager(); + connManager.setDefaultMaxPerRoute(concurrentConns); + connManager.setMaxTotal(100); + for (int i = 0; i < 3; i++) { final SimpleHttpRequest get = SimpleRequestBuilder.get() .setHttpHost(target) @@ -142,7 +95,7 @@ public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest> response = consumer.getResponseFuture().get(); assertThat(response, CoreMatchers.notNullValue()); @@ -153,30 +106,21 @@ public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest + new ReactiveServerExchangeHandler(new ReactiveRandomProcessor())); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(); + final PoolingAsyncClientConnectionManager connManager = connManager(); + final AsyncRequestProducer request1 = AsyncRequestBuilder.get(target + "/random/2048").build(); final ReactiveResponseConsumer consumer1 = new ReactiveResponseConsumer(); - httpclient.execute(request1, consumer1, null); + client.execute(request1, consumer1, null); final Message> response1 = consumer1.getResponseFuture().get(); assertThat(response1, CoreMatchers.notNullValue()); @@ -208,7 +152,7 @@ public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest> response3 = consumer3.getResponseFuture().get(); assertThat(response3, CoreMatchers.notNullValue()); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ReactiveMinimal.java similarity index 61% rename from httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java rename to httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ReactiveMinimal.java index a97f2b01b..1992fa519 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ReactiveMinimal.java @@ -28,25 +28,17 @@ package org.apache.hc.client5.testing.async; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.Arrays; -import java.util.Collection; import java.util.LinkedList; import java.util.Queue; import java.util.Random; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.apache.hc.client5.http.config.TlsConfig; -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpResponse; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.Message; import org.apache.hc.core5.http.Method; import org.apache.hc.core5.http.URIScheme; @@ -56,72 +48,48 @@ import org.apache.hc.core5.http.nio.entity.AsyncEntityProducers; import org.apache.hc.core5.http.nio.entity.BasicAsyncEntityConsumer; import org.apache.hc.core5.http.nio.support.BasicRequestProducer; import org.apache.hc.core5.http.nio.support.BasicResponseConsumer; -import org.apache.hc.core5.http2.HttpVersionPolicy; import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.reactive.ReactiveServerExchangeHandler; +import org.apache.hc.core5.testing.nio.H2TestServer; +import org.apache.hc.core5.testing.reactive.ReactiveEchoProcessor; import org.hamcrest.CoreMatchers; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttpMinimalReactive extends AbstractHttpReactiveFundamentalsTest { +public abstract class TestHttp1ReactiveMinimal extends AbstractHttpReactiveFundamentalsTest { - @Parameterized.Parameters(name = "Minimal {0} {1}") - public static Collection protocols() { - return Arrays.asList(new Object[][]{ - { HttpVersion.HTTP_1_1, URIScheme.HTTP }, - { HttpVersion.HTTP_1_1, URIScheme.HTTPS }, - { HttpVersion.HTTP_2, URIScheme.HTTP }, - { HttpVersion.HTTP_2, URIScheme.HTTPS } - }); - } - - protected final HttpVersion version; - - public TestHttpMinimalReactive(final HttpVersion version, final URIScheme scheme) { + public TestHttp1ReactiveMinimal(final URIScheme scheme) { super(scheme); - this.version = version; } @Override - protected MinimalHttpAsyncClient createClient() throws Exception { - return HttpAsyncClients.createMinimal( - H2Config.DEFAULT, + protected H2TestServer startServer() throws Exception { + return startServer(Http1Config.DEFAULT, null, null); + } + + @Override + protected MinimalHttpAsyncClient startClient() throws Exception { + return startMinimalClient( Http1Config.DEFAULT, - IOReactorConfig.custom() - .setSoTimeout(LONG_TIMEOUT) - .build(), - PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setDefaultTlsConfig(TlsConfig.custom() - .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) - ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1) - .build()) - .build()); - } - - @Override - public HttpHost start() throws Exception { - if (version.greaterEquals(HttpVersion.HTTP_2)) { - return super.start(null, H2Config.DEFAULT); - } else { - return super.start(null, Http1Config.DEFAULT); - } + H2Config.DEFAULT, + b -> {}); } @Test public void testConcurrentPostRequestsSameEndpoint() throws Exception { - final HttpHost target = start(); + final H2TestServer server = startServer(); + server.register("/echo/*", () -> + new ReactiveServerExchangeHandler(new ReactiveEchoProcessor())); + final HttpHost target = targetHost(); + + final MinimalHttpAsyncClient client = startClient(); + final byte[] b1 = new byte[1024]; final Random rnd = new Random(System.currentTimeMillis()); rnd.nextBytes(b1); final int reqCount = 20; - final Future endpointLease = httpclient.lease(target, null); + final Future endpointLease = client.lease(target, null); final AsyncClientEndpoint endpoint = endpointLease.get(5, TimeUnit.SECONDS); try { final Queue>> queue = new LinkedList<>(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java index 7ab743ea8..50294e9bb 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java @@ -28,99 +28,31 @@ package org.apache.hc.client5.testing.async; import static org.hamcrest.MatcherAssert.assertThat; -import java.util.Arrays; -import java.util.Collection; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.config.TlsConfig; import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; -import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.core5.function.Resolver; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Http1Config; -import org.apache.hc.core5.http2.HttpVersionPolicy; -import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.testing.nio.H2TestServer; import org.apache.hc.core5.util.TimeValue; import org.hamcrest.CoreMatchers; -import org.junit.Rule; -import org.junit.Test; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; +import org.junit.jupiter.api.Test; -@EnableRuleMigrationSupport -@RunWith(Parameterized.class) -public class TestHttp1RequestReExecution extends AbstractIntegrationTestBase { +public abstract class TestHttp1RequestReExecution extends AbstractIntegrationTestBase { - @Parameterized.Parameters(name = "{0}") - public static Collection protocolVersions() { - return Arrays.asList(new Object[][]{ - { HttpVersion.HTTP_1_1 }, - { HttpVersion.HTTP_2 } - }); + public TestHttp1RequestReExecution(final URIScheme scheme) { + super(scheme); } - private final HttpVersion version; - - public TestHttp1RequestReExecution(final HttpVersion version) { - super(URIScheme.HTTP); - this.version = version; - } - - HttpAsyncClientBuilder clientBuilder; - PoolingAsyncClientConnectionManager connManager; - - @Rule - public ExternalResource connManagerResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = PoolingAsyncClientConnectionManagerBuilder.create() - .build(); - } - - @Override - protected void after() { - if (connManager != null) { - connManager.close(); - connManager = null; - } - } - - }; - - @Rule - public ExternalResource clientBuilderResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager.setDefaultTlsConfig(TlsConfig.custom() - .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1) - .build()); - clientBuilder = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - }; - - @Override - public final HttpHost start() throws Exception { - + protected H2TestServer startServer() throws Exception { final Resolver serviceAvailabilityResolver = new Resolver() { private final AtomicInteger count = new AtomicInteger(0); @@ -133,23 +65,20 @@ public class TestHttp1RequestReExecution extends AbstractIntegrationTestBase new ServiceUnavailableAsyncDecorator(handler, serviceAvailabilityResolver), H2Config.DEFAULT); - } else { - return super.start(null, handler -> new ServiceUnavailableAsyncDecorator(handler, serviceAvailabilityResolver), Http1Config.DEFAULT); - } - } - - @Override - protected CloseableHttpAsyncClient createClient() throws Exception { - return clientBuilder.build(); + return startServer(Http1Config.DEFAULT, null, handler -> + new ServiceUnavailableAsyncDecorator(handler, serviceAvailabilityResolver)); } @Test public void testGiveUpAfterOneRetry() throws Exception { - clientBuilder.setRetryStrategy(new DefaultHttpRequestRetryStrategy(1, TimeValue.ofSeconds(1))); - final HttpHost target = start(); - final Future future = httpclient.execute( + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(builder -> builder + .setRetryStrategy(new DefaultHttpRequestRetryStrategy(1, TimeValue.ofSeconds(1)))); + + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") @@ -161,9 +90,14 @@ public class TestHttp1RequestReExecution extends AbstractIntegrationTestBase future = httpclient.execute( + final H2TestServer server = startServer(); + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final CloseableHttpAsyncClient client = startClient(builder -> builder + .setRetryStrategy(new DefaultHttpRequestRetryStrategy(5, TimeValue.ofSeconds(1)))); + + final Future future = client.execute( SimpleRequestBuilder.get() .setHttpHost(target) .setPath("/random/2048") diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTls.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTls.java deleted file mode 100644 index b960e4e90..000000000 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTls.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ -package org.apache.hc.client5.testing.async; - -import java.net.InetSocketAddress; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.SSLException; - -import org.apache.hc.client5.http.impl.async.HttpAsyncClients; -import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; -import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; -import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.config.Http1Config; -import org.apache.hc.core5.http.nio.AsyncClientEndpoint; -import org.apache.hc.core5.http2.config.H2Config; -import org.apache.hc.core5.io.CloseMode; -import org.apache.hc.core5.reactor.IOReactorConfig; -import org.apache.hc.core5.reactor.ListenerEndpoint; -import org.apache.hc.core5.ssl.SSLContexts; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; -import org.junit.rules.ExternalResource; - -@EnableRuleMigrationSupport -public class TestHttpAsyncMinimalTls extends AbstractServerTestBase { - - public TestHttpAsyncMinimalTls() { - super(URIScheme.HTTPS); - } - - MinimalHttpAsyncClient httpclient; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void after() { - if (httpclient != null) { - httpclient.close(CloseMode.GRACEFUL); - httpclient = null; - } - } - - }; - - @Test - public void testSuccessfulTlsHandshake() throws Exception { - final int maxConnNo = 2; - - httpclient = HttpAsyncClients.createMinimal( - H2Config.DEFAULT, - Http1Config.DEFAULT, - IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(), - PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())) - .setMaxConnPerRoute(maxConnNo) - .setMaxConnTotal(maxConnNo) - .build()); - - server.start(Http1Config.DEFAULT); - final Future endpointFuture = server.listen(new InetSocketAddress(0)); - - final ListenerEndpoint listenerEndpoint = endpointFuture.get(); - final InetSocketAddress address = (InetSocketAddress) listenerEndpoint.getAddress(); - final HttpHost target = new HttpHost(scheme.name(), "localhost", address.getPort()); - httpclient.start(); - - for (int i = 0; i < maxConnNo + 1; i++) { - final Future endpointLease = httpclient.lease(target, null); - final AsyncClientEndpoint endpoint = endpointLease.get(5, TimeUnit.SECONDS); - endpoint.releaseAndDiscard(); - } - } - - @Test - public void testTlsHandshakeFailure() throws Exception { - final int maxConnNo = 2; - - httpclient = HttpAsyncClients.createMinimal( - H2Config.DEFAULT, - Http1Config.DEFAULT, - IOReactorConfig.custom() - .setSoTimeout(TIMEOUT) - .build(), - PoolingAsyncClientConnectionManagerBuilder.create() - .setTlsStrategy(new DefaultClientTlsStrategy(SSLContexts.createDefault())) - .setMaxConnPerRoute(2) - .setMaxConnTotal(2) - .build()); - - server.start(Http1Config.DEFAULT); - final Future endpointFuture = server.listen(new InetSocketAddress(0)); - - final ListenerEndpoint listenerEndpoint = endpointFuture.get(); - final InetSocketAddress address = (InetSocketAddress) listenerEndpoint.getAddress(); - final HttpHost target = new HttpHost(scheme.name(), "localhost", address.getPort()); - httpclient.start(); - - for (int i = 0; i < maxConnNo + 1; i++) { - final Future endpointLease = httpclient.lease(target, null); - final ExecutionException executionException = Assert.assertThrows(ExecutionException.class, - () -> endpointLease.get(5, TimeUnit.SECONDS)); - Assertions.assertInstanceOf(SSLException.class, executionException.getCause()); - } - } - -} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTlsHandshake.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTlsHandshake.java new file mode 100644 index 000000000..86545fce9 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimalTlsHandshake.java @@ -0,0 +1,98 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +import javax.net.ssl.SSLException; + +import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.http.nio.AsyncClientEndpoint; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.ssl.SSLContexts; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestHttpAsyncMinimalTlsHandshake extends AbstractIntegrationTestBase { + + public TestHttpAsyncMinimalTlsHandshake() { + super(URIScheme.HTTPS); + } + + protected MinimalHttpAsyncClient startMinimalClient( + final Consumer connManagerCustomizer) throws Exception { + return startMinimalClient( + Http1Config.DEFAULT, + H2Config.DEFAULT, + connManagerCustomizer); + } + + @Test + public void testSuccessfulTlsHandshake() throws Exception { + startServer(Http1Config.DEFAULT, null, null); + final HttpHost target = targetHost(); + + final int maxConnNo = 2; + final MinimalHttpAsyncClient client = startMinimalClient(builder -> builder + .setMaxConnPerRoute(maxConnNo) + .setMaxConnTotal(maxConnNo)); + + for (int i = 0; i < maxConnNo + 1; i++) { + final Future endpointLease = client.lease(target, null); + final AsyncClientEndpoint endpoint = endpointLease.get(5, TimeUnit.SECONDS); + endpoint.releaseAndDiscard(); + } + } + + @Test + public void testTlsHandshakeFailure() throws Exception { + startServer(Http1Config.DEFAULT, null, null); + final HttpHost target = targetHost(); + + final int maxConnNo = 2; + final MinimalHttpAsyncClient client = startMinimalClient(builder -> builder + .setTlsStrategy(new DefaultClientTlsStrategy(SSLContexts.createDefault())) + .setMaxConnPerRoute(maxConnNo) + .setMaxConnTotal(maxConnNo)); + + for (int i = 0; i < maxConnNo + 1; i++) { + final Future endpointLease = client.lease(target, null); + final ExecutionException executionException = Assertions.assertThrows(ExecutionException.class, + () -> endpointLease.get(5, TimeUnit.SECONDS)); + Assertions.assertInstanceOf(SSLException.class, executionException.getCause()); + } + } + +} \ No newline at end of file diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncProtocolPolicy.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncProtocolPolicy.java new file mode 100644 index 000000000..aceeca195 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncProtocolPolicy.java @@ -0,0 +1,94 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.hc.client5.testing.async; + +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; +import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; +import org.apache.hc.client5.http.config.TlsConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpVersion; +import org.apache.hc.core5.http.ProtocolVersion; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.http2.HttpVersionPolicy; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.testing.nio.H2TestServer; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; + +public abstract class TestHttpAsyncProtocolPolicy extends AbstractIntegrationTestBase { + + private final HttpVersion version; + + public TestHttpAsyncProtocolPolicy(final URIScheme scheme, final HttpVersion version) { + super(scheme); + this.version = version; + } + + @Test + public void testRequestContext() throws Exception { + final H2TestServer server; + if (version.greaterEquals(HttpVersion.HTTP_2)) { + server = startServer(H2Config.DEFAULT, null, null); + } else { + server = startServer(Http1Config.DEFAULT, null, null); + } + server.register("/random/*", AsyncRandomHandler::new); + final HttpHost target = targetHost(); + + final AtomicReference versionRef = new AtomicReference<>(); + final CloseableHttpAsyncClient client = startClient( + builder -> builder + .setDefaultTlsConfig(TlsConfig.custom() + .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1) + .build()), + builder -> builder + .addRequestInterceptorFirst((request, entity, context) -> + versionRef.set(context.getProtocolVersion()) + )); + + final Future future = client.execute( + SimpleRequestBuilder.get() + .setHttpHost(target) + .setPath("/random/2048") + .build(), null); + final SimpleHttpResponse response = future.get(); + assertThat(response, CoreMatchers.notNullValue()); + assertThat(response.getCode(), CoreMatchers.equalTo(200)); + final String body = response.getBodyText(); + assertThat(body, CoreMatchers.notNullValue()); + assertThat(body.length(), CoreMatchers.equalTo(2048)); + assertThat(versionRef.get(), CoreMatchers.equalTo(version)); + } + +} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/extension/TestAsyncResources.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/extension/TestAsyncResources.java new file mode 100644 index 000000000..49a411e74 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/extension/TestAsyncResources.java @@ -0,0 +1,235 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.testing.async.extension; + +import java.net.InetSocketAddress; +import java.util.function.Consumer; + +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.async.HttpAsyncClients; +import org.apache.hc.client5.http.impl.async.MinimalH2AsyncClient; +import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy; +import org.apache.hc.client5.testing.SSLTestContexts; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; +import org.apache.hc.core5.function.Decorator; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler; +import org.apache.hc.core5.http.protocol.HttpProcessor; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.io.CloseMode; +import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.testing.nio.H2TestServer; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestAsyncResources implements BeforeEachCallback, AfterEachCallback { + + private static final Logger LOG = LoggerFactory.getLogger(TestClientResources.class); + + private final URIScheme scheme; + private final Timeout timeout; + + private H2TestServer server; + private InetSocketAddress socketAddress; + private PoolingAsyncClientConnectionManager connManager; + private CloseableHttpAsyncClient client; + + public TestAsyncResources(final URIScheme scheme, final Timeout timeout) { + this.scheme = scheme; + this.timeout = timeout; + } + + @Override + public void beforeEach(final ExtensionContext extensionContext) throws Exception { + LOG.debug("Starting up test server"); + server = new H2TestServer( + IOReactorConfig.custom() + .setSoTimeout(timeout) + .build(), + scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null, + null, + null); + } + + @Override + public void afterEach(final ExtensionContext extensionContext) throws Exception { + LOG.debug("Shutting down test server"); + + if (client != null) { + client.close(CloseMode.GRACEFUL); + } + + if (connManager != null) { + connManager.close(CloseMode.IMMEDIATE); + } + + if (server != null) { + server.shutdown(TimeValue.ofSeconds(5)); + } + } + + public URIScheme scheme() { + return this.scheme; + } + + public H2TestServer startServer( + final H2Config h2Config, + final HttpProcessor httpProcessor, + final Decorator exchangeHandlerDecorator) throws Exception { + Assertions.assertNotNull(server); + socketAddress = server.start(httpProcessor, exchangeHandlerDecorator, h2Config); + return server; + } + + public H2TestServer startServer( + final Http1Config http1Config, + final HttpProcessor httpProcessor, + final Decorator exchangeHandlerDecorator) throws Exception { + Assertions.assertNotNull(server); + socketAddress = server.start(httpProcessor, exchangeHandlerDecorator, http1Config); + return server; + } + + public HttpHost targetHost() { + Assertions.assertNotNull(socketAddress); + return new HttpHost(scheme.id, "localhost", socketAddress.getPort()); + } + + public CloseableHttpAsyncClient startClient( + final Consumer connManagerCustomizer, + final Consumer clientCustomizer) throws Exception { + Assertions.assertNull(connManager); + Assertions.assertNull(client); + + final PoolingAsyncClientConnectionManagerBuilder connManagerBuilder = PoolingAsyncClientConnectionManagerBuilder.create(); + connManagerBuilder.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + connManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setSocketTimeout(timeout) + .setConnectTimeout(timeout) + .build()); + connManagerCustomizer.accept(connManagerBuilder); + + connManager = connManagerBuilder.build(); + + final HttpAsyncClientBuilder clientBuilder = HttpAsyncClientBuilder.create() + .setConnectionManager(connManager) + .setIOReactorConfig(IOReactorConfig.custom() + .setSoTimeout(timeout) + .build()); + + clientCustomizer.accept(clientBuilder); + client = clientBuilder.build(); + client.start(); + return client; + } + + public CloseableHttpAsyncClient startClient( + final Consumer clientCustomizer) throws Exception { + return startClient(b -> { + }, clientCustomizer); + } + + public PoolingAsyncClientConnectionManager connManager() { + Assertions.assertNotNull(connManager); + return connManager; + } + + public CloseableHttpAsyncClient startH2Client( + final Consumer clientCustomizer) throws Exception { + Assertions.assertNull(connManager); + Assertions.assertNull(client); + + final H2AsyncClientBuilder clientBuilder = H2AsyncClientBuilder.create(); + clientBuilder.setIOReactorConfig(IOReactorConfig.custom() + .setSoTimeout(timeout) + .build()); + clientBuilder.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + clientCustomizer.accept(clientBuilder); + client = clientBuilder.build(); + client.start(); + return client; + } + + public MinimalHttpAsyncClient startMinimalClient( + final Http1Config http1Config, + final H2Config h2Config, + final Consumer connManagerCustomizer) throws Exception { + Assertions.assertNull(connManager); + Assertions.assertNull(client); + + final PoolingAsyncClientConnectionManagerBuilder connManagerBuilder = PoolingAsyncClientConnectionManagerBuilder.create(); + connManagerBuilder.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + connManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setSocketTimeout(timeout) + .setConnectTimeout(timeout) + .build()); + connManagerCustomizer.accept(connManagerBuilder); + + connManager = connManagerBuilder.build(); + + final MinimalHttpAsyncClient minimal = HttpAsyncClients.createMinimal( + h2Config, + http1Config, + IOReactorConfig.custom() + .setSoTimeout(timeout) + .build(), + connManager); + client = minimal; + client.start(); + return minimal; + } + + public MinimalH2AsyncClient startMinimalH2Client(final H2Config h2Config) throws Exception { + Assertions.assertNull(client); + + final MinimalH2AsyncClient minimal = HttpAsyncClients.createHttp2Minimal( + h2Config, + IOReactorConfig.custom() + .setSoTimeout(timeout) + .build(), + new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext())); + client = minimal; + client.start(); + return minimal; + } + +} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/fluent/TestFluent.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/fluent/TestFluent.java index 453e9073e..35e3ae464 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/fluent/TestFluent.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/fluent/TestFluent.java @@ -33,22 +33,37 @@ import java.nio.charset.StandardCharsets; import org.apache.hc.client5.http.ClientProtocolException; import org.apache.hc.client5.http.fluent.Content; import org.apache.hc.client5.http.fluent.Request; -import org.apache.hc.client5.testing.sync.LocalServerTestBase; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; -import org.junit.Before; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class TestFluent extends LocalServerTestBase { +public class TestFluent { - @Before + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public HttpHost targetHost() { + return testResources.targetHost(); + } + + @BeforeEach public void setUp() throws Exception { - this.server.registerHandler("/", (request, response, context) -> response.setEntity(new StringEntity("All is well", ContentType.TEXT_PLAIN))); - this.server.registerHandler("/echo", (request, response, context) -> { + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("/", (request, response, context) -> + response.setEntity(new StringEntity("All is well", ContentType.TEXT_PLAIN))); + server.registerHandler("/echo", (request, response, context) -> { HttpEntity responseEntity = null; final HttpEntity requestEntity = request.getEntity(); if (requestEntity != null) { @@ -68,7 +83,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testGetRequest() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); final String message = Request.get(baseURL + "/").execute().returnContent().asString(); Assertions.assertEquals("All is well", message); @@ -76,7 +91,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testGetRequestByName() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); final String message = Request.create("GET", baseURL + "/").execute().returnContent().asString(); Assertions.assertEquals("All is well", message); @@ -84,7 +99,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testGetRequestByNameWithURI() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); final String message = Request.create("GET", new URI(baseURL + "/")).execute().returnContent().asString(); Assertions.assertEquals("All is well", message); @@ -92,7 +107,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testGetRequestFailure() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); Assertions.assertThrows(ClientProtocolException.class, () -> Request.get(baseURL + "/boom").execute().returnContent().asString()); @@ -100,7 +115,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testPostRequest() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); final String message1 = Request.post(baseURL + "/echo") .bodyString("what is up?", ContentType.TEXT_PLAIN) @@ -114,7 +129,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testContentAsStringWithCharset() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); final Content content = Request.post(baseURL + "/echo").bodyByteArray("Ü".getBytes(StandardCharsets.UTF_8)).execute() .returnContent(); @@ -125,7 +140,7 @@ public class TestFluent extends LocalServerTestBase { @Test public void testConnectionRelease() throws Exception { - final HttpHost target = start(); + final HttpHost target = targetHost(); final String baseURL = "http://localhost:" + target.getPort(); for (int i = 0; i < 20; i++) { Request.get(baseURL + "/").execute().returnContent(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java deleted file mode 100644 index 6067a0493..000000000 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - */ - -package org.apache.hc.client5.testing.sync; - -import java.io.IOException; - -import org.apache.hc.client5.http.config.ConnectionConfig; -import org.apache.hc.client5.http.config.RequestConfig; -import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; -import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; -import org.apache.hc.client5.testing.SSLTestContexts; -import org.apache.hc.client5.testing.classic.EchoHandler; -import org.apache.hc.client5.testing.classic.RandomHandler; -import org.apache.hc.core5.function.Decorator; -import org.apache.hc.core5.http.HttpHost; -import org.apache.hc.core5.http.URIScheme; -import org.apache.hc.core5.http.config.Http1Config; -import org.apache.hc.core5.http.io.HttpServerRequestHandler; -import org.apache.hc.core5.http.io.SocketConfig; -import org.apache.hc.core5.http.protocol.HttpProcessor; -import org.apache.hc.core5.io.CloseMode; -import org.apache.hc.core5.io.Closer; -import org.apache.hc.core5.testing.classic.ClassicTestServer; -import org.apache.hc.core5.util.Timeout; -import org.junit.Rule; -import org.junit.rules.ExternalResource; - -/** - * Base class for tests using local test server. The server will not be started per default. - */ -public abstract class LocalServerTestBase { - - public static final Timeout TIMEOUT = Timeout.ofMinutes(1); - public static final Timeout LONG_TIMEOUT = Timeout.ofMinutes(3); - - public LocalServerTestBase(final URIScheme scheme) { - this.scheme = scheme; - } - - public LocalServerTestBase() { - this(URIScheme.HTTP); - } - - protected final URIScheme scheme; - - protected ClassicTestServer server; - - @Rule - public ExternalResource serverResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - server = new ClassicTestServer( - scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null, - SocketConfig.custom() - .setSoTimeout(TIMEOUT) - .build()); - server.registerHandler("/echo/*", new EchoHandler()); - server.registerHandler("/random/*", new RandomHandler()); - } - - @Override - protected void after() { - if (server != null) { - try { - server.shutdown(CloseMode.IMMEDIATE); - server = null; - } catch (final Exception ignore) { - } - } - } - - }; - - protected PoolingHttpClientConnectionManager connManager; - protected HttpClientBuilder clientBuilder; - protected CloseableHttpClient httpclient; - - @Rule - public ExternalResource clientResource = new ExternalResource() { - - @Override - protected void before() throws Throwable { - connManager = new PoolingHttpClientConnectionManager(); - connManager.setDefaultSocketConfig(SocketConfig.custom() - .setSoTimeout(TIMEOUT) - .build()); - connManager.setDefaultConnectionConfig(ConnectionConfig.custom() - .setConnectTimeout(TIMEOUT) - .build()); - - clientBuilder = HttpClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setConnectionRequestTimeout(TIMEOUT) - .build()) - .setConnectionManager(connManager); - } - - @Override - protected void after() { - Closer.closeQuietly(httpclient); - httpclient = null; - } - - }; - - public HttpHost start( - final Http1Config http1Config, - final HttpProcessor httpProcessor, - final Decorator handlerDecorator) throws IOException { - this.server.start(http1Config, httpProcessor, handlerDecorator); - - if (this.httpclient == null) { - this.httpclient = this.clientBuilder.build(); - } - - return new HttpHost(this.scheme.name(), "localhost", this.server.getPort()); - } - - public HttpHost start( - final HttpProcessor httpProcessor, - final Decorator handlerDecorator) throws IOException { - return start(null, httpProcessor, handlerDecorator); - } - - public HttpHost start() throws Exception { - return start(null, null, null); - } - -} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestBasicConnectionManager.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestBasicConnectionManager.java index 9c4ca2826..1d29bc8e0 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestBasicConnectionManager.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestBasicConnectionManager.java @@ -27,21 +27,38 @@ package org.apache.hc.client5.testing.sync; import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager; +import org.apache.hc.client5.testing.classic.RandomHandler; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.junit.Test; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class TestBasicConnectionManager extends LocalServerTestBase { +public class TestBasicConnectionManager { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); @Test public void testBasics() throws Exception { - this.clientBuilder.setConnectionManager(new BasicHttpClientConnectionManager()); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = testResources.targetHost(); + + final CloseableHttpClient client = testResources.startClient(builder -> builder + .setConnectionManager(new BasicHttpClientConnectionManager()) + ); - final HttpHost target = start(); final HttpGet get = new HttpGet("/random/1024"); - this.httpclient.execute(target, get, response -> { + client.execute(target, get, response -> { Assertions.assertEquals(200, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -50,14 +67,19 @@ public class TestBasicConnectionManager extends LocalServerTestBase { @Test public void testConnectionStillInUse() throws Exception { - this.clientBuilder.setConnectionManager(new BasicHttpClientConnectionManager()); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = testResources.targetHost(); + + final CloseableHttpClient client = testResources.startClient(builder -> builder + .setConnectionManager(new BasicHttpClientConnectionManager()) + ); - final HttpHost target = start(); final HttpGet get1 = new HttpGet("/random/1024"); - this.httpclient.executeOpen(target, get1, null); + client.executeOpen(target, get1, null); final HttpGet get2 = new HttpGet("/random/1024"); Assertions.assertThrows(IllegalStateException.class, () -> - this.httpclient.executeOpen(target, get2, null)); + client.executeOpen(target, get2, null)); } } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java index 9120a1a19..441d934ee 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; import java.util.stream.Collectors; import org.apache.hc.client5.http.ClientProtocolException; @@ -55,11 +56,14 @@ import org.apache.hc.client5.http.impl.auth.BasicAuthCache; import org.apache.hc.client5.http.impl.auth.BasicScheme; import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.testing.BasicTestAuthenticator; import org.apache.hc.client5.testing.auth.Authenticator; import org.apache.hc.client5.testing.classic.AuthenticatingDecorator; import org.apache.hc.client5.testing.classic.EchoHandler; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HeaderElements; @@ -69,6 +73,8 @@ 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.HttpStatus; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.impl.HttpProcessors; @@ -79,36 +85,61 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.support.BasicResponseBuilder; import org.apache.hc.core5.net.URIAuthority; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.Mockito; /** * Unit tests for automatic client authentication. */ -public class TestClientAuthentication extends LocalServerTestBase { +public class TestClientAuthentication { - public HttpHost start(final Authenticator authenticator) throws IOException { - return super.start(null, requestHandler -> new AuthenticatingDecorator(requestHandler, authenticator)); + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer(final Authenticator authenticator) throws IOException { + return testResources.startServer( + null, + null, + requestHandler -> new AuthenticatingDecorator(requestHandler, authenticator)); } - @Override - public HttpHost start() throws IOException { - return start(new BasicTestAuthenticator("test:test", "test realm")); + public ClassicTestServer startServer() throws IOException { + return startServer(new BasicTestAuthenticator("test:test", "test realm")); + } + + public CloseableHttpClient startClient(final Consumer clientCustomizer) { + return testResources.startClient(clientCustomizer); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(builder -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); } @Test public void testBasicAuthenticationNoCreds() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); context.setCredentialsProvider(credsProvider); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); Assertions.assertNotNull(entity); @@ -121,8 +152,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationFailure() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); @@ -131,7 +165,7 @@ public class TestClientAuthentication extends LocalServerTestBase { context.setCredentialsProvider(credsProvider); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); Assertions.assertNotNull(entity); @@ -144,7 +178,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationSuccess() throws Exception { - this.server.registerHandler("*", new EchoHandler()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet httpget = new HttpGet("/"); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); @@ -152,9 +190,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray())); context.setCredentialsProvider(credsProvider); - final HttpHost target = start(); - - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity); @@ -167,8 +203,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationSuccessOnNonRepeatablePutExpectContinue() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final RequestConfig config = RequestConfig.custom() .setExpectContinueEnabled(true) @@ -185,7 +224,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray())); context.setCredentialsProvider(credsProvider); - this.httpclient.execute(target, httpput, context, response -> { + client.execute(target, httpput, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity); @@ -195,8 +234,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationFailureOnNonRepeatablePutDontExpectContinue() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(false).build(); final HttpPut httpput = new HttpPut("/"); @@ -212,7 +254,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .thenReturn(new UsernamePasswordCredentials("test", "boom".toCharArray())); context.setCredentialsProvider(credsProvider); - this.httpclient.execute(target, httpput, context, response -> { + client.execute(target, httpput, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(401, response.getCode()); Assertions.assertNotNull(entity); @@ -223,8 +265,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationSuccessOnRepeatablePost() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpPost httppost = new HttpPost("/"); httppost.setEntity(new StringEntity("some important stuff", StandardCharsets.US_ASCII)); @@ -235,7 +280,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray())); context.setCredentialsProvider(credsProvider); - this.httpclient.execute(target, httppost, context, response -> { + client.execute(target, httppost, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity); @@ -248,8 +293,11 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationFailureOnNonRepeatablePost() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpPost httppost = new HttpPost("/"); httppost.setEntity(new InputStreamEntity( @@ -265,7 +313,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray())); context.setCredentialsProvider(credsProvider); - this.httpclient.execute(target, httppost, context, response -> { + client.execute(target, httppost, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(401, response.getCode()); Assertions.assertNotNull(entity); @@ -276,14 +324,17 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationCredentialsCaching() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy()); - this.clientBuilder.setTargetAuthenticationStrategy(authStrategy); - final Queue responseQueue = new ConcurrentLinkedQueue<>(); - this.clientBuilder.addResponseInterceptorLast((response, entity, context) - -> responseQueue.add(BasicResponseBuilder.copy(response).build())); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy()); + final Queue responseQueue = new ConcurrentLinkedQueue<>(); + + final CloseableHttpClient client = startClient(builder -> builder + .setTargetAuthenticationStrategy(authStrategy) + .addResponseInterceptorLast((response, entity, context) + -> responseQueue.add(BasicResponseBuilder.copy(response).build()))); final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(CredentialsProviderBuilder.create() @@ -292,7 +343,7 @@ public class TestClientAuthentication extends LocalServerTestBase { for (int i = 0; i < 5; i++) { final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity1); @@ -310,14 +361,17 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testBasicAuthenticationCredentialsCachingByPathPrefix() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy()); - this.clientBuilder.setTargetAuthenticationStrategy(authStrategy); - final Queue responseQueue = new ConcurrentLinkedQueue<>(); - this.clientBuilder.addResponseInterceptorLast((response, entity, context) - -> responseQueue.add(BasicResponseBuilder.copy(response).build())); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy()); + final Queue responseQueue = new ConcurrentLinkedQueue<>(); + + final CloseableHttpClient client = startClient(builder -> builder + .setTargetAuthenticationStrategy(authStrategy) + .addResponseInterceptorLast((response, entity, context) + -> responseQueue.add(BasicResponseBuilder.copy(response).build()))); final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() .add(target, "test", "test".toCharArray()) @@ -330,7 +384,7 @@ public class TestClientAuthentication extends LocalServerTestBase { for (final String requestPath: new String[] {"/blah/a", "/blah/b?huh", "/blah/c", "/bl%61h/%61"}) { final HttpGet httpget = new HttpGet(requestPath); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity1); @@ -352,7 +406,7 @@ public class TestClientAuthentication extends LocalServerTestBase { for (final String requestPath: new String[] {"/blah/a", "/yada/a", "/blah/blah/", "/buh/a"}) { final HttpGet httpget = new HttpGet(requestPath); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity1); @@ -371,8 +425,7 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testAuthenticationCredentialsCachingReauthenticationOnDifferentRealm() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(new Authenticator() { + final ClassicTestServer server = startServer(new Authenticator() { @Override public boolean authenticate(final URIAuthority authority, final String requestUri, final String credentials) { @@ -397,22 +450,26 @@ public class TestClientAuthentication extends LocalServerTestBase { } }); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy()); + + final CloseableHttpClient client = startClient(builder -> builder + .setTargetAuthenticationStrategy(authStrategy) + ); + final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() .add(new AuthScope(target, "this realm", null), "test", "this".toCharArray()) .add(new AuthScope(target, "that realm", null), "test", "that".toCharArray()) .build(); - this.clientBuilder.setTargetAuthenticationStrategy(authStrategy); - this.httpclient = this.clientBuilder.build(); - final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(credsProvider); final HttpGet httpget1 = new HttpGet("/this"); - this.httpclient.execute(target, httpget1, context, response -> { + client.execute(target, httpget1, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity1); @@ -422,7 +479,7 @@ public class TestClientAuthentication extends LocalServerTestBase { final HttpGet httpget2 = new HttpGet("/this"); - this.httpclient.execute(target, httpget2, context, response -> { + client.execute(target, httpget2, context, response -> { final HttpEntity entity2 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity2); @@ -432,7 +489,7 @@ public class TestClientAuthentication extends LocalServerTestBase { final HttpGet httpget3 = new HttpGet("/that"); - this.httpclient.execute(target, httpget3, context, response -> { + client.execute(target, httpget3, context, response -> { final HttpEntity entity3 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity3); @@ -445,19 +502,25 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testAuthenticationUserinfoInRequest() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet httpget = new HttpGet("http://test:test@" + target.toHostString() + "/"); final HttpClientContext context = HttpClientContext.create(); - Assertions.assertThrows(ClientProtocolException.class, () -> this.httpclient.execute(target, httpget, context, response -> null)); + Assertions.assertThrows(ClientProtocolException.class, () -> client.execute(target, httpget, context, response -> null)); } @Test public void testPreemptiveAuthentication() throws Exception { - this.server.registerHandler("*", new EchoHandler()); final Authenticator authenticator = Mockito.spy(new BasicTestAuthenticator("test:test", "test realm")); - final HttpHost target = start(authenticator); + final ClassicTestServer server = startServer(authenticator); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final BasicScheme basicScheme = new BasicScheme(); basicScheme.initPreemptive(new UsernamePasswordCredentials("test", "test".toCharArray())); @@ -467,7 +530,7 @@ public class TestClientAuthentication extends LocalServerTestBase { context.setAuthCache(authCache); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity1); @@ -480,9 +543,12 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testPreemptiveAuthenticationFailure() throws Exception { - this.server.registerHandler("*", new EchoHandler()); final Authenticator authenticator = Mockito.spy(new BasicTestAuthenticator("test:test", "test realm")); - final HttpHost target = start(authenticator); + final ClassicTestServer server = startServer(authenticator); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final AuthCache authCache = new BasicAuthCache(); @@ -493,7 +559,7 @@ public class TestClientAuthentication extends LocalServerTestBase { .build()); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity1 = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); Assertions.assertNotNull(entity1); @@ -525,16 +591,18 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testAuthenticationTargetAsProxy() throws Exception { - this.server.registerHandler("*", new ProxyAuthHandler()); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new ProxyAuthHandler()); + final HttpHost target = testResources.targetHost(); - final HttpHost target = super.start(); + final CloseableHttpClient client = testResources.startClient(builder -> {}); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); context.setCredentialsProvider(credsProvider); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED, response.getCode()); EntityUtils.consume(entity); @@ -544,9 +612,8 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testConnectionCloseAfterAuthenticationSuccess() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - - final HttpHost target = start( + final ClassicTestServer server = testResources.startServer( + Http1Config.DEFAULT, HttpProcessors.server(), requestHandler -> new AuthenticatingDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm")) { @@ -555,7 +622,12 @@ public class TestClientAuthentication extends LocalServerTestBase { unauthorized.addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE); } - }); + } + ); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() @@ -566,7 +638,7 @@ public class TestClientAuthentication extends LocalServerTestBase { for (int i = 0; i < 2; i++) { final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); return null; @@ -576,8 +648,6 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testReauthentication() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - final BasicSchemeFactory myBasicAuthSchemeFactory = new BasicSchemeFactory() { @Override @@ -605,10 +675,6 @@ public class TestClientAuthentication extends LocalServerTestBase { final Registry authSchemeRegistry = RegistryBuilder.create() .register("MyBasic", myBasicAuthSchemeFactory) .build(); - this.httpclient = this.clientBuilder - .setDefaultAuthSchemeRegistry(authSchemeRegistry) - .setDefaultCredentialsProvider(credsProvider) - .build(); final Authenticator authenticator = new BasicTestAuthenticator("test:test", "test realm") { @@ -624,7 +690,8 @@ public class TestClientAuthentication extends LocalServerTestBase { } }; - final HttpHost target = start( + final ClassicTestServer server = testResources.startServer( + Http1Config.DEFAULT, HttpProcessors.server(), requestHandler -> new AuthenticatingDecorator(requestHandler, authenticator) { @@ -634,13 +701,21 @@ public class TestClientAuthentication extends LocalServerTestBase { unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, "MyBasic realm=\"test realm\""); } - }); + } + ); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(builder -> builder + .setDefaultAuthSchemeRegistry(authSchemeRegistry) + .setDefaultCredentialsProvider(credsProvider) + ); final HttpClientContext context = HttpClientContext.create(); for (int i = 0; i < 10; i++) { final HttpGet httpget = new HttpGet("/"); httpget.setConfig(config); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity); @@ -652,9 +727,8 @@ public class TestClientAuthentication extends LocalServerTestBase { @Test public void testAuthenticationFallback() throws Exception { - this.server.registerHandler("*", new EchoHandler()); - - final HttpHost target = start( + final ClassicTestServer server = testResources.startServer( + Http1Config.DEFAULT, HttpProcessors.server(), requestHandler -> new AuthenticatingDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm")) { @@ -663,7 +737,12 @@ public class TestClientAuthentication extends LocalServerTestBase { unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"test realm\" invalid"); } - }); + } + ); + server.registerHandler("*", new EchoHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class); @@ -672,7 +751,7 @@ public class TestClientAuthentication extends LocalServerTestBase { context.setCredentialsProvider(credsProvider); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpEntity entity = response.getEntity(); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); Assertions.assertNotNull(entity); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java index 337ab51fb..4c531408b 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java @@ -27,30 +27,58 @@ package org.apache.hc.client5.testing.sync; import java.io.IOException; +import java.util.function.Consumer; import org.apache.hc.client5.http.auth.CredentialsProvider; import org.apache.hc.client5.http.auth.NTCredentials; import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; -import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; 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.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Unit tests for some of the NTLM auth functionality.. */ -public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { +public class TestClientAuthenticationFakeNTLM { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer() throws IOException { + return testResources.startServer(null, null, null); + } + + public CloseableHttpClient startClient(final Consumer clientCustomizer) { + return testResources.startClient(clientCustomizer); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(builder -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); + } static class NtlmResponseHandler implements HttpRequestHandler { @@ -67,22 +95,22 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { @Test public void testNTLMAuthenticationFailure() throws Exception { - this.server.registerHandler("*", new NtlmResponseHandler()); - - final HttpHost target = start(); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new NtlmResponseHandler()); + final HttpHost target = targetHost(); final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() .add(target, new NTCredentials("test", "test".toCharArray(), null, null)) .build(); - this.httpclient = HttpClients.custom() + final CloseableHttpClient client = startClient(builder -> builder .setDefaultCredentialsProvider(credsProvider) - .build(); + ); final HttpContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; @@ -114,23 +142,24 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { @Test public void testNTLMv1Type2Message() throws Exception { - this.server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" + + final ClassicTestServer server = startServer(); + server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" + "AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" + "AGUAcgB2AGUAcgA=")); - final HttpHost target = start(); + final HttpHost target = targetHost(); final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() .add(target, new NTCredentials("test", "test".toCharArray(), null, null)) .build(); - this.httpclient = HttpClients.custom() + final CloseableHttpClient client = startClient(builder -> builder .setDefaultCredentialsProvider(credsProvider) - .build(); + ); final HttpContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; @@ -139,23 +168,24 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { @Test public void testNTLMv2Type2Message() throws Exception { - this.server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" + + final ClassicTestServer server = startServer(); + server.registerHandler("*", new NtlmType2MessageResponseHandler("TlRMTVNTUAACAA" + "AADAAMADgAAAAzgoriASNFZ4mrze8AAAAAAAAAACQAJABEAAAABgBwFwAAAA9T" + "AGUAcgB2AGUAcgACAAwARABvAG0AYQBpAG4AAQAMAFMAZQByAHYAZQByAAAAAAA=")); - final HttpHost target = start(); + final HttpHost target = targetHost(); final CredentialsProvider credsProvider = CredentialsProviderBuilder.create() .add(target, new NTCredentials("test", "test".toCharArray(), null, null)) .build(); - this.httpclient = HttpClients.custom() + final CloseableHttpClient client = startClient(builder -> builder .setDefaultCredentialsProvider(credsProvider) - .build(); + ); final HttpContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; @@ -183,11 +213,13 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { @Test public void testNTLMType2MessageOnlyAuthenticationFailure() throws Exception { - this.server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" + + final ClassicTestServer server = startServer(); + server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" + "AADAAMADgAAAAzggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" + "AGUAcgB2AGUAcgA=")); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(CredentialsProviderBuilder.create() @@ -195,7 +227,7 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { .build()); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; @@ -204,11 +236,14 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { @Test public void testNTLMType2NonUnicodeMessageOnlyAuthenticationFailure() throws Exception { - this.server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" + + final ClassicTestServer server = startServer(); + server.registerHandler("*", new NtlmType2MessageOnlyResponseHandler("TlRMTVNTUAACAA" + "AABgAGADgAAAAyggLiASNFZ4mrze8AAAAAAAAAAAAAAAAAAAAABgBwFwAAAA9T" + "ZXJ2ZXI=")); + final HttpHost target = targetHost(); - final HttpHost target = start(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(CredentialsProviderBuilder.create() @@ -216,7 +251,7 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase { .build()); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientRequestExecution.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientRequestExecution.java index 300b4cb78..39d3f508f 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientRequestExecution.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientRequestExecution.java @@ -33,13 +33,17 @@ import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; import org.apache.hc.client5.http.HttpRequestRetryStrategy; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.RedirectLocations; import org.apache.hc.client5.http.utils.URIUtils; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; @@ -49,6 +53,7 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.impl.io.HttpRequestExecutor; import org.apache.hc.core5.http.io.HttpClientConnection; import org.apache.hc.core5.http.io.HttpRequestHandler; @@ -58,14 +63,38 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.net.URIBuilder; +import org.apache.hc.core5.testing.classic.ClassicTestServer; import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Client protocol handling tests. */ -public class TestClientRequestExecution extends LocalServerTestBase { +public class TestClientRequestExecution { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer() throws IOException { + return testResources.startServer(null, null, null); + } + + public CloseableHttpClient startClient(final Consumer clientCustomizer) { + return testResources.startClient(clientCustomizer); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(builder -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); + } private static class SimpleService implements HttpRequestHandler { @@ -113,7 +142,9 @@ public class TestClientRequestExecution extends LocalServerTestBase { @Test public void testAutoGeneratedHeaders() throws Exception { - this.server.registerHandler("*", new SimpleService()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new SimpleService()); + final HttpHost target = targetHost(); final HttpRequestInterceptor interceptor = (request, entityDetails, context) -> request.addHeader("my-header", "stuff"); @@ -146,19 +177,17 @@ public class TestClientRequestExecution extends LocalServerTestBase { }; - this.httpclient = this.clientBuilder - .addRequestInterceptorFirst(interceptor) - .setRequestExecutor(new FaultyHttpRequestExecutor("Oppsie")) - .setRetryStrategy(requestRetryStrategy) - .build(); - - final HttpHost target = start(); + final CloseableHttpClient client = startClient(builder -> builder + .addRequestInterceptorFirst(interceptor) + .setRequestExecutor(new FaultyHttpRequestExecutor("Oppsie")) + .setRetryStrategy(requestRetryStrategy) + ); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { EntityUtils.consume(response.getEntity()); final HttpRequest reqWrapper = context.getRequest(); @@ -173,7 +202,9 @@ public class TestClientRequestExecution extends LocalServerTestBase { @Test public void testNonRepeatableEntity() throws Exception { - this.server.registerHandler("*", new SimpleService()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new SimpleService()); + final HttpHost target = targetHost(); final HttpRequestRetryStrategy requestRetryStrategy = new HttpRequestRetryStrategy() { @@ -204,12 +235,10 @@ public class TestClientRequestExecution extends LocalServerTestBase { }; - this.httpclient = this.clientBuilder - .setRequestExecutor(new FaultyHttpRequestExecutor("a message showing that this failed")) - .setRetryStrategy(requestRetryStrategy) - .build(); - - final HttpHost target = start(); + final CloseableHttpClient client = startClient(builder -> builder + .setRequestExecutor(new FaultyHttpRequestExecutor("a message showing that this failed")) + .setRetryStrategy(requestRetryStrategy) + ); final HttpClientContext context = HttpClientContext.create(); @@ -219,18 +248,20 @@ public class TestClientRequestExecution extends LocalServerTestBase { new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ), -1, null)); Assertions.assertThrows(IOException.class, () -> - this.httpclient.execute(target, httppost, context, response -> null)); + client.execute(target, httppost, context, response -> null)); } @Test public void testNonCompliantURI() throws Exception { - this.server.registerHandler("*", new SimpleService()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new SimpleService()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final ClassicHttpRequest request = new BasicClassicHttpRequest("GET", "{{|boom|}}"); - this.httpclient.execute(target, request, context, response -> { + client.execute(target, request, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -243,14 +274,16 @@ public class TestClientRequestExecution extends LocalServerTestBase { @Test public void testRelativeRequestURIWithFragment() throws Exception { - this.server.registerHandler("*", new SimpleService()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new SimpleService()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = startClient(); final HttpGet httpget = new HttpGet("/stuff#blahblah"); final HttpClientContext context = HttpClientContext.create(); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -262,9 +295,11 @@ public class TestClientRequestExecution extends LocalServerTestBase { @Test public void testAbsoluteRequestURIWithFragment() throws Exception { - this.server.registerHandler("*", new SimpleService()); + final ClassicTestServer server = startServer(); + server.registerHandler("*", new SimpleService()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = startClient(); final URI uri = new URIBuilder() .setHost(target.getHostName()) @@ -277,7 +312,7 @@ public class TestClientRequestExecution extends LocalServerTestBase { final HttpGet httpget = new HttpGet(uri); final HttpClientContext context = HttpClientContext.create(); - this.httpclient.execute(httpget, context, response -> { + client.execute(httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); return null; }); @@ -292,10 +327,14 @@ public class TestClientRequestExecution extends LocalServerTestBase { @Test public void testRequestCancellation() throws Exception { - this.connManager.setDefaultMaxPerRoute(1); - this.connManager.setMaxTotal(1); + startServer(); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnPerRoute(1) + .setMaxConnTotal(1), + builder -> {}); final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); try { @@ -306,7 +345,7 @@ public class TestClientRequestExecution extends LocalServerTestBase { executorService.schedule(httpget::cancel, 1, TimeUnit.MILLISECONDS); try { - this.httpclient.execute(target, httpget, response -> { + client.execute(target, httpget, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -322,7 +361,7 @@ public class TestClientRequestExecution extends LocalServerTestBase { executorService.schedule(httpget::cancel, rnd.nextInt(200), TimeUnit.MILLISECONDS); try { - this.httpclient.execute(target, httpget, response -> { + client.execute(target, httpget, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -333,7 +372,7 @@ public class TestClientRequestExecution extends LocalServerTestBase { for (int i = 0; i < 5; i++) { final HttpGet httpget = new HttpGet("/random/1000"); - this.httpclient.execute(target, httpget, response -> { + client.execute(target, httpget, response -> { EntityUtils.consume(response.getEntity()); return null; }); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java index b02b250b2..a9dd59b44 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java @@ -27,20 +27,22 @@ package org.apache.hc.client5.testing.sync; +import java.io.IOException; import java.util.concurrent.TimeoutException; import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; import org.apache.hc.client5.http.io.ConnectionEndpoint; import org.apache.hc.client5.http.io.LeaseRequest; -import org.apache.hc.client5.http.socket.ConnectionSocketFactory; -import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.client5.testing.classic.RandomHandler; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; -import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.impl.io.HttpRequestExecutor; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.protocol.BasicHttpContext; @@ -52,37 +54,62 @@ import org.apache.hc.core5.http.protocol.RequestContent; import org.apache.hc.core5.http.protocol.RequestTargetHost; import org.apache.hc.core5.pool.PoolConcurrencyPolicy; import org.apache.hc.core5.pool.PoolReusePolicy; +import org.apache.hc.core5.testing.classic.ClassicTestServer; import org.apache.hc.core5.util.TimeValue; import org.apache.hc.core5.util.Timeout; -import org.junit.Test; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Tests for {@code PoolingHttpClientConnectionManager} that do require a server * to communicate with. */ -public class TestConnectionManagement extends LocalServerTestBase { +public class TestConnectionManagement { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer() throws IOException { + return testResources.startServer(null, null, null); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(b -> {}, b -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); + } /** * Tests releasing and re-using a connection after a response is read. */ @Test public void testReleaseConnection() throws Exception { + final ClassicTestServer server = startServer(); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - this.connManager.setMaxTotal(1); + startClient(); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); + connManager.setMaxTotal(1); - final HttpHost target = start(); final HttpRoute route = new HttpRoute(target, null, false); - final int rsplen = 8; - final String uri = "/random/" + rsplen; + final int rsplen = 8; + final String uri = "/random/" + rsplen; final ClassicHttpRequest request = new BasicClassicHttpRequest("GET", target, uri); final HttpContext context = new BasicHttpContext(); - final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null); + final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null); final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS); - this.connManager.connect(endpoint1, null, context); + connManager.connect(endpoint1, null, context); final HttpProcessor httpProcessor = new DefaultHttpProcessor( new RequestTargetHost(), new RequestContent(), new RequestConnControl()); @@ -95,16 +122,16 @@ public class TestConnectionManagement extends LocalServerTestBase { // check that there is no auto-release by default // this should fail quickly, connection has not been released - final LeaseRequest leaseRequest2 = this.connManager.lease("id2", route,null); + final LeaseRequest leaseRequest2 = connManager.lease("id2", route, null); Assertions.assertThrows(TimeoutException.class, () -> leaseRequest2.get(Timeout.ofMilliseconds(10))); endpoint1.close(); - this.connManager.release(endpoint1, null, TimeValue.NEG_ONE_MILLISECOND); - final LeaseRequest leaseRequest3 = this.connManager.lease("id2", route,null); + connManager.release(endpoint1, null, TimeValue.NEG_ONE_MILLISECOND); + final LeaseRequest leaseRequest3 = connManager.lease("id2", route, null); final ConnectionEndpoint endpoint2 = leaseRequest3.get(Timeout.ZERO_MILLISECONDS); Assertions.assertFalse(endpoint2.isConnected()); - this.connManager.connect(endpoint2, null, context); + connManager.connect(endpoint2, null, context); try (final ClassicHttpResponse response2 = endpoint2.execute("id2", request, exec, context)) { Assertions.assertEquals(HttpStatus.SC_OK, response2.getCode()); @@ -112,9 +139,9 @@ public class TestConnectionManagement extends LocalServerTestBase { // release connection after marking it for re-use // expect the next connection obtained to be open - this.connManager.release(endpoint2, null, TimeValue.NEG_ONE_MILLISECOND); + connManager.release(endpoint2, null, TimeValue.NEG_ONE_MILLISECOND); - final LeaseRequest leaseRequest4 = this.connManager.lease("id3", route,null); + final LeaseRequest leaseRequest4 = connManager.lease("id3", route, null); final ConnectionEndpoint endpoint3 = leaseRequest4.get(Timeout.ZERO_MILLISECONDS); Assertions.assertTrue(endpoint3.isConnected()); @@ -123,8 +150,8 @@ public class TestConnectionManagement extends LocalServerTestBase { Assertions.assertEquals(HttpStatus.SC_OK, response3.getCode()); } - this.connManager.release(endpoint3, null, TimeValue.NEG_ONE_MILLISECOND); - this.connManager.close(); + connManager.release(endpoint3, null, TimeValue.NEG_ONE_MILLISECOND); + connManager.close(); } /** @@ -132,20 +159,25 @@ public class TestConnectionManagement extends LocalServerTestBase { */ @Test public void testReleaseConnectionWithTimeLimits() throws Exception { + final ClassicTestServer server = startServer(); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - this.connManager.setMaxTotal(1); + startClient(); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); + connManager.setMaxTotal(1); - final HttpHost target = start(); final HttpRoute route = new HttpRoute(target, null, false); - final int rsplen = 8; - final String uri = "/random/" + rsplen; + final int rsplen = 8; + final String uri = "/random/" + rsplen; final ClassicHttpRequest request = new BasicClassicHttpRequest("GET", target, uri); final HttpContext context = new BasicHttpContext(); - final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null); + final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null); final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS); - this.connManager.connect(endpoint1, null, context); + connManager.connect(endpoint1, null, context); final HttpProcessor httpProcessor = new DefaultHttpProcessor( new RequestTargetHost(), new RequestContent(), new RequestConnControl()); @@ -157,26 +189,26 @@ public class TestConnectionManagement extends LocalServerTestBase { } // check that there is no auto-release by default - final LeaseRequest leaseRequest2 = this.connManager.lease("id2", route,null); + final LeaseRequest leaseRequest2 = connManager.lease("id2", route, null); // this should fail quickly, connection has not been released Assertions.assertThrows(TimeoutException.class, () -> leaseRequest2.get(Timeout.ofMilliseconds(10))); endpoint1.close(); - this.connManager.release(endpoint1, null, TimeValue.ofMilliseconds(100)); + connManager.release(endpoint1, null, TimeValue.ofMilliseconds(100)); - final LeaseRequest leaseRequest3 = this.connManager.lease("id2", route,null); + final LeaseRequest leaseRequest3 = connManager.lease("id2", route, null); final ConnectionEndpoint endpoint2 = leaseRequest3.get(Timeout.ZERO_MILLISECONDS); Assertions.assertFalse(endpoint2.isConnected()); - this.connManager.connect(endpoint2, null, context); + connManager.connect(endpoint2, null, context); try (final ClassicHttpResponse response2 = endpoint2.execute("id2", request, exec, context)) { Assertions.assertEquals(HttpStatus.SC_OK, response2.getCode()); } - this.connManager.release(endpoint2, null, TimeValue.ofMilliseconds(100)); + connManager.release(endpoint2, null, TimeValue.ofMilliseconds(100)); - final LeaseRequest leaseRequest4 = this.connManager.lease("id3", route,null); + final LeaseRequest leaseRequest4 = connManager.lease("id3", route, null); final ConnectionEndpoint endpoint3 = leaseRequest4.get(Timeout.ZERO_MILLISECONDS); Assertions.assertTrue(endpoint3.isConnected()); @@ -185,109 +217,115 @@ public class TestConnectionManagement extends LocalServerTestBase { Assertions.assertEquals(HttpStatus.SC_OK, response3.getCode()); } - this.connManager.release(endpoint3, null, TimeValue.ofMilliseconds(100)); + connManager.release(endpoint3, null, TimeValue.ofMilliseconds(100)); Thread.sleep(150); - final LeaseRequest leaseRequest5 = this.connManager.lease("id4", route,null); + final LeaseRequest leaseRequest5 = connManager.lease("id4", route, null); final ConnectionEndpoint endpoint4 = leaseRequest5.get(Timeout.ZERO_MILLISECONDS); Assertions.assertFalse(endpoint4.isConnected()); // repeat the communication, no need to prepare the request again - this.connManager.connect(endpoint4, null, context); + connManager.connect(endpoint4, null, context); try (final ClassicHttpResponse response4 = endpoint4.execute("id4", request, exec, context)) { Assertions.assertEquals(HttpStatus.SC_OK, response4.getCode()); } - this.connManager.close(); + connManager.close(); } @Test public void testCloseExpiredIdleConnections() throws Exception { + startServer(); + final HttpHost target = targetHost(); + startClient(); - this.connManager.setMaxTotal(1); + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); + connManager.setMaxTotal(1); - final HttpHost target = start(); final HttpRoute route = new HttpRoute(target, null, false); final HttpContext context = new BasicHttpContext(); - final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null); + final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null); final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS); - this.connManager.connect(endpoint1, null, context); + connManager.connect(endpoint1, null, context); - Assertions.assertEquals(1, this.connManager.getTotalStats().getLeased()); - Assertions.assertEquals(1, this.connManager.getStats(route).getLeased()); + Assertions.assertEquals(1, connManager.getTotalStats().getLeased()); + Assertions.assertEquals(1, connManager.getStats(route).getLeased()); - this.connManager.release(endpoint1, null, TimeValue.ofMilliseconds(100)); + connManager.release(endpoint1, null, TimeValue.ofMilliseconds(100)); // Released, still active. - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(1, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getStats(route).getAvailable()); - this.connManager.closeExpired(); + connManager.closeExpired(); // Time has not expired yet. - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(1, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getStats(route).getAvailable()); Thread.sleep(150); - this.connManager.closeExpired(); + connManager.closeExpired(); // Time expired now, connections are destroyed. - Assertions.assertEquals(0, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(0, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(0, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(0, connManager.getStats(route).getAvailable()); - this.connManager.close(); + connManager.close(); } - @Test + @Test @Disabled public void testCloseExpiredTTLConnections() throws Exception { + final ClassicTestServer server = startServer(); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - this.connManager = new PoolingHttpClientConnectionManager( - RegistryBuilder.create() - .register("http", PlainConnectionSocketFactory.getSocketFactory()) - .register("https", SSLConnectionSocketFactory.getSocketFactory()) - .build(), - PoolConcurrencyPolicy.STRICT, - PoolReusePolicy.LIFO, - TimeValue.ofMilliseconds(100)); - this.clientBuilder.setConnectionManager(this.connManager); + testResources.startClient( + builder -> builder + .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT) + .setConnPoolPolicy(PoolReusePolicy.LIFO) + .setDefaultConnectionConfig(ConnectionConfig.custom() + .setTimeToLive(TimeValue.ofMilliseconds(100)) + .build()) + .setMaxConnTotal(1), + builder -> {} + ); - this.connManager.setMaxTotal(1); + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); - final HttpHost target = start(); final HttpRoute route = new HttpRoute(target, null, false); final HttpContext context = new BasicHttpContext(); - final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null); + final LeaseRequest leaseRequest1 = connManager.lease("id1", route, null); final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS); - this.connManager.connect(endpoint1, null, context); + connManager.connect(endpoint1, null, context); - Assertions.assertEquals(1, this.connManager.getTotalStats().getLeased()); - Assertions.assertEquals(1, this.connManager.getStats(route).getLeased()); + Assertions.assertEquals(1, connManager.getTotalStats().getLeased()); + Assertions.assertEquals(1, connManager.getStats(route).getLeased()); // Release, let remain idle for forever - this.connManager.release(endpoint1, null, TimeValue.NEG_ONE_MILLISECOND); + connManager.release(endpoint1, null, TimeValue.NEG_ONE_MILLISECOND); // Released, still active. - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(1, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getStats(route).getAvailable()); - this.connManager.closeExpired(); + connManager.closeExpired(); // Time has not expired yet. - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(1, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getStats(route).getAvailable()); Thread.sleep(150); - this.connManager.closeExpired(); + connManager.closeExpired(); // TTL expired now, connections are destroyed. - Assertions.assertEquals(0, this.connManager.getTotalStats().getAvailable()); - Assertions.assertEquals(0, this.connManager.getStats(route).getAvailable()); + Assertions.assertEquals(0, connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(0, connManager.getStats(route).getAvailable()); - this.connManager.close(); + connManager.close(); } } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionReuse.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionReuse.java index 05c0a8454..6029d2574 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionReuse.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionReuse.java @@ -37,6 +37,9 @@ import java.util.List; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.testing.classic.RandomHandler; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.EntityDetails; @@ -47,27 +50,49 @@ 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.HttpResponseInterceptor; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.impl.HttpProcessors; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.InputStreamEntity; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.http.protocol.HttpProcessor; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class TestConnectionReuse extends LocalServerTestBase { +public class TestConnectionReuse { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public HttpHost targetHost() { + return testResources.targetHost(); + } @Test public void testReuseOfPersistentConnections() throws Exception { - this.connManager.setMaxTotal(5); - this.connManager.setDefaultMaxPerRoute(5); + final ClassicTestServer server = testResources.startServer( null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(5) + .setMaxConnPerRoute(5), + builder -> { + } + ); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); final WorkerThread[] workers = new WorkerThread[10]; for (int i = 0; i < workers.length; i++) { workers[i] = new WorkerThread( - this.httpclient, + client, target, new URI("/random/2000"), 10, false); @@ -85,17 +110,26 @@ public class TestConnectionReuse extends LocalServerTestBase { } // Expect leased connections to be returned - Assertions.assertEquals(0, this.connManager.getTotalStats().getLeased()); + Assertions.assertEquals(0, connManager.getTotalStats().getLeased()); // Expect some connection in the pool - Assertions.assertTrue(this.connManager.getTotalStats().getAvailable() > 0); + Assertions.assertTrue(connManager.getTotalStats().getAvailable() > 0); } @Test public void testReuseOfPersistentConnectionsWithStreamedRequestAndResponse() throws Exception { - this.connManager.setMaxTotal(5); - this.connManager.setDefaultMaxPerRoute(5); + final ClassicTestServer server = testResources.startServer( null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(5) + .setMaxConnPerRoute(5), + builder -> { + } + ); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); final WorkerThread[] workers = new WorkerThread[10]; for (int i = 0; i < workers.length; i++) { @@ -108,7 +142,7 @@ public class TestConnectionReuse extends LocalServerTestBase { ContentType.APPLICATION_OCTET_STREAM)); requests.add(post); } - workers[i] = new WorkerThread(this.httpclient, target, false, requests); + workers[i] = new WorkerThread(client, target, false, requests); } for (final WorkerThread worker : workers) { @@ -123,9 +157,9 @@ public class TestConnectionReuse extends LocalServerTestBase { } // Expect leased connections to be returned - Assertions.assertEquals(0, this.connManager.getTotalStats().getLeased()); + Assertions.assertEquals(0, connManager.getTotalStats().getLeased()); // Expect some connection in the pool - Assertions.assertTrue(this.connManager.getTotalStats().getAvailable() > 0); + Assertions.assertTrue(connManager.getTotalStats().getAvailable() > 0); } private static class AlwaysCloseConn implements HttpResponseInterceptor { @@ -142,18 +176,26 @@ public class TestConnectionReuse extends LocalServerTestBase { @Test public void testReuseOfClosedConnections() throws Exception { - this.connManager.setMaxTotal(5); - this.connManager.setDefaultMaxPerRoute(5); - final HttpProcessor httpproc = HttpProcessors.customServer(null) .add(new AlwaysCloseConn()) .build(); - final HttpHost target = start(httpproc, null); + final ClassicTestServer server = testResources.startServer( null, httpproc, null); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(5) + .setMaxConnPerRoute(5), + builder -> { + } + ); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); final WorkerThread[] workers = new WorkerThread[10]; for (int i = 0; i < workers.length; i++) { workers[i] = new WorkerThread( - this.httpclient, + client, target, new URI("/random/2000"), 10, false); @@ -171,22 +213,31 @@ public class TestConnectionReuse extends LocalServerTestBase { } // Expect leased connections to be returned - Assertions.assertEquals(0, this.connManager.getTotalStats().getLeased()); + Assertions.assertEquals(0, connManager.getTotalStats().getLeased()); // Expect zero connections in the pool - Assertions.assertEquals(0, this.connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(0, connManager.getTotalStats().getAvailable()); } @Test public void testReuseOfAbortedConnections() throws Exception { - this.connManager.setMaxTotal(5); - this.connManager.setDefaultMaxPerRoute(5); + final ClassicTestServer server = testResources.startServer( null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(5) + .setMaxConnPerRoute(5), + builder -> { + } + ); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); final WorkerThread[] workers = new WorkerThread[10]; for (int i = 0; i < workers.length; i++) { workers[i] = new WorkerThread( - this.httpclient, + client, target, new URI("/random/2000"), 10, true); @@ -204,55 +255,65 @@ public class TestConnectionReuse extends LocalServerTestBase { } // Expect leased connections to be returned - Assertions.assertEquals(0, this.connManager.getTotalStats().getLeased()); + Assertions.assertEquals(0, connManager.getTotalStats().getLeased()); // Expect some connections in the pool - Assertions.assertTrue(this.connManager.getTotalStats().getAvailable() > 0); + Assertions.assertTrue(connManager.getTotalStats().getAvailable() > 0); } @Test public void testKeepAliveHeaderRespected() throws Exception { - this.connManager.setMaxTotal(1); - this.connManager.setDefaultMaxPerRoute(1); - final HttpProcessor httpproc = HttpProcessors.customServer(null) .add(new ResponseKeepAlive()) .build(); - final HttpHost target = start(httpproc, null); + final ClassicTestServer server = testResources.startServer( null, httpproc, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); - this.httpclient.execute(target, new HttpGet("/random/2000"), response -> { + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(1) + .setMaxConnPerRoute(1), + builder -> { + } + ); + + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); + + + client.execute(target, new HttpGet("/random/2000"), response -> { EntityUtils.consume(response.getEntity()); return null; }); - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); - this.httpclient.execute(target, new HttpGet("/random/2000"), response -> { + client.execute(target, new HttpGet("/random/2000"), response -> { EntityUtils.consume(response.getEntity()); return null; }); - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); // Now sleep for 1.1 seconds and let the timeout do its work Thread.sleep(1100); - this.httpclient.execute(target, new HttpGet("/random/2000"), response -> { + client.execute(target, new HttpGet("/random/2000"), response -> { EntityUtils.consume(response.getEntity()); return null; }); - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); // Do another request just under the 1 second limit & make // sure we reuse that connection. Thread.sleep(500); - this.httpclient.execute(target, new HttpGet("/random/2000"), response -> { + client.execute(target, new HttpGet("/random/2000"), response -> { EntityUtils.consume(response.getEntity()); return null; }); // Expect leased connections to be returned - Assertions.assertEquals(0, this.connManager.getTotalStats().getLeased()); - Assertions.assertEquals(1, this.connManager.getTotalStats().getAvailable()); + Assertions.assertEquals(0, connManager.getTotalStats().getLeased()); + Assertions.assertEquals(1, connManager.getTotalStats().getAvailable()); } private static class WorkerThread extends Thread { diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestContentCodings.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestContentCodings.java index c303f56a9..633670f70 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestContentCodings.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestContentCodings.java @@ -38,33 +38,62 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.function.Consumer; import java.util.zip.Deflater; import java.util.zip.GZIPOutputStream; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HeaderElement; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.InputStreamEntity; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.MessageSupport; import org.apache.hc.core5.http.protocol.HttpContext; -import org.junit.Test; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Test case for how Content Codings are processed. By default, we want to do the right thing and * require no intervention from the user of HttpClient, but we still want to let clients do their * own thing if they so wish. */ -public class TestContentCodings extends LocalServerTestBase { +public class TestContentCodings { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer() throws IOException { + return testResources.startServer(null, null, null); + } + + public CloseableHttpClient startClient(final Consumer clientCustomizer) { + return testResources.startClient(clientCustomizer); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(builder -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); + } /** * Test for when we don't get an entity back; e.g. for a 204 or 304 response; nothing blows @@ -75,7 +104,8 @@ public class TestContentCodings extends LocalServerTestBase { */ @Test public void testResponseWithNoContent() throws Exception { - this.server.registerHandler("*", new HttpRequestHandler() { + final ClassicTestServer server = startServer(); + server.registerHandler("*", new HttpRequestHandler() { /** * {@inheritDoc} @@ -89,10 +119,12 @@ public class TestContentCodings extends LocalServerTestBase { } }); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { Assertions.assertEquals(HttpStatus.SC_NO_CONTENT, response.getCode()); Assertions.assertNull(response.getEntity()); return null; @@ -109,12 +141,15 @@ public class TestContentCodings extends LocalServerTestBase { public void testDeflateSupportForServerReturningRfc1950Stream() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, false)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, false)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { Assertions.assertEquals(entityText, EntityUtils.toString(response.getEntity()), "The entity text is correctly transported"); return null; @@ -131,12 +166,15 @@ public class TestContentCodings extends LocalServerTestBase { public void testDeflateSupportForServerReturningRfc1951Stream() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, true)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, true)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { Assertions.assertEquals(entityText, EntityUtils.toString(response.getEntity()), "The entity text is correctly transported"); return null; @@ -152,12 +190,15 @@ public class TestContentCodings extends LocalServerTestBase { public void testGzipSupport() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { Assertions.assertEquals(entityText, EntityUtils.toString(response.getEntity()), "The entity text is correctly transported"); return null; @@ -174,7 +215,13 @@ public class TestContentCodings extends LocalServerTestBase { public void testThreadSafetyOfContentCodings() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); + + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); /* * Create a load of workers which will access the resource. Half will use the default @@ -182,9 +229,7 @@ public class TestContentCodings extends LocalServerTestBase { */ final int clients = 100; - this.connManager.setMaxTotal(clients); - - final HttpHost target = start(); + connManager.setMaxTotal(clients); final ExecutorService executor = Executors.newFixedThreadPool(clients); @@ -194,7 +239,7 @@ public class TestContentCodings extends LocalServerTestBase { final List workers = new ArrayList<>(); for (int i = 0; i < clients; ++i) { - workers.add(new WorkerTask(this.httpclient, target, i % 2 == 0, startGate, endGate)); + workers.add(new WorkerTask(client, target, i % 2 == 0, startGate, endGate)); } for (final WorkerTask workerTask : workers) { @@ -220,12 +265,15 @@ public class TestContentCodings extends LocalServerTestBase { public void testHttpEntityWriteToForGzip() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { final ByteArrayOutputStream out = new ByteArrayOutputStream(); response.getEntity().writeTo(out); Assertions.assertEquals(entityText, out.toString("utf-8")); @@ -238,12 +286,15 @@ public class TestContentCodings extends LocalServerTestBase { public void testHttpEntityWriteToForDeflate() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, true)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, true)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { final ByteArrayOutputStream out = new ByteArrayOutputStream(); response.getEntity().writeTo(out); Assertions.assertEquals(entityText, out.toString("utf-8")); @@ -255,12 +306,15 @@ public class TestContentCodings extends LocalServerTestBase { public void gzipResponsesWorkWithBasicResponseHandler() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createGzipEncodingRequestHandler(entityText)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - final String response = this.httpclient.execute(target, request, new BasicHttpClientResponseHandler()); + final String response = client.execute(target, request, new BasicHttpClientResponseHandler()); Assertions.assertEquals(entityText, response, "The entity text is correctly transported"); } @@ -268,12 +322,15 @@ public class TestContentCodings extends LocalServerTestBase { public void deflateResponsesWorkWithBasicResponseHandler() throws Exception { final String entityText = "Hello, this is some plain text coming back."; - this.server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, false)); + final ClassicTestServer server = startServer(); + server.registerHandler("*", createDeflateEncodingRequestHandler(entityText, false)); - final HttpHost target = start(); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpGet request = new HttpGet("/some-resource"); - final String response = this.httpclient.execute(target, request, new BasicHttpClientResponseHandler()); + final String response = client.execute(target, request, new BasicHttpClientResponseHandler()); Assertions.assertEquals(entityText, response, "The entity text is correctly transported"); } @@ -437,7 +494,7 @@ public class TestContentCodings extends LocalServerTestBase { try { startGate.await(); try { - text = httpclient.execute(target, request, response -> + text = client.execute(target, request, response -> EntityUtils.toString(response.getEntity())); } catch (final Exception e) { failed = true; diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestCookieVirtualHost.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestCookieVirtualHost.java index c32cad468..195c89ebb 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestCookieVirtualHost.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestCookieVirtualHost.java @@ -33,22 +33,34 @@ import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.cookie.BasicCookieStore; import org.apache.hc.client5.http.cookie.Cookie; import org.apache.hc.client5.http.cookie.CookieStore; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * This class tests cookie matching when using Virtual Host. */ -public class TestCookieVirtualHost extends LocalServerTestBase { +public class TestCookieVirtualHost { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); @Test public void testCookieMatchingWithVirtualHosts() throws Exception { - this.server.registerHandlerVirtual("app.mydomain.fr", "*", (request, response, context) -> { + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandlerVirtual("app.mydomain.fr", "*", (request, response, context) -> { final int n = Integer.parseInt(request.getFirstHeader("X-Request").getValue()); switch (n) { @@ -87,7 +99,9 @@ public class TestCookieVirtualHost extends LocalServerTestBase { } }); - final HttpHost target = start(); + final HttpHost target = testResources.targetHost(); + + final CloseableHttpClient client = testResources.startClient(b -> {}); final CookieStore cookieStore = new BasicCookieStore(); final HttpClientContext context = HttpClientContext.create(); @@ -96,7 +110,7 @@ public class TestCookieVirtualHost extends LocalServerTestBase { // First request : retrieve a domain cookie from remote server. final HttpGet request1 = new HttpGet(new URI("http://app.mydomain.fr")); request1.addHeader("X-Request", "1"); - this.httpclient.execute(target, request1, context, response -> { + client.execute(target, request1, context, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -110,7 +124,7 @@ public class TestCookieVirtualHost extends LocalServerTestBase { // Second request : send the cookie back. final HttpGet request2 = new HttpGet(new URI("http://app.mydomain.fr")); request2.addHeader("X-Request", "2"); - this.httpclient.execute(target, request2, context, response -> { + client.execute(target, request2, context, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -118,7 +132,7 @@ public class TestCookieVirtualHost extends LocalServerTestBase { // Third request : Host header final HttpGet request3 = new HttpGet(new URI("http://app.mydomain.fr")); request3.addHeader("X-Request", "3"); - this.httpclient.execute(target, request3, context, response -> { + client.execute(target, request3, context, response -> { EntityUtils.consume(response.getEntity()); return null; }); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestIdleConnectionEviction.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestIdleConnectionEviction.java index a364ef583..dc2d26435 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestIdleConnectionEviction.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestIdleConnectionEviction.java @@ -33,27 +33,45 @@ import org.apache.hc.client5.http.ClientProtocolException; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.IdleConnectionEvictor; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.testing.classic.RandomHandler; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.testing.classic.ClassicTestServer; import org.apache.hc.core5.util.TimeValue; -import org.junit.Test; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; -public class TestIdleConnectionEviction extends LocalServerTestBase { +public class TestIdleConnectionEviction { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); @Test public void testIdleConnectionEviction() throws Exception { - this.connManager.setDefaultMaxPerRoute(10); - this.connManager.setMaxTotal(50); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = testResources.targetHost(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient(b -> {}); - final IdleConnectionEvictor idleConnectionMonitor = new IdleConnectionEvictor(this.connManager, TimeValue.ofMilliseconds(50)); + final PoolingHttpClientConnectionManager connManager = testResources.connManager(); + + connManager.setDefaultMaxPerRoute(10); + connManager.setMaxTotal(50); + + final IdleConnectionEvictor idleConnectionMonitor = new IdleConnectionEvictor(connManager, TimeValue.ofMilliseconds(50)); idleConnectionMonitor.start(); final URI requestUri = new URI("/random/1024"); final WorkerThread[] workers = new WorkerThread[5]; for (int i = 0; i < workers.length; i++) { - workers[i] = new WorkerThread(httpclient, target, requestUri, 200); + workers[i] = new WorkerThread(client, target, requestUri, 200); } for (final WorkerThread worker : workers) { worker.start(); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestMinimalClientRequestExecution.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestMinimalClientRequestExecution.java index 35ce34969..47bbfb1f4 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestMinimalClientRequestExecution.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestMinimalClientRequestExecution.java @@ -32,8 +32,9 @@ import java.util.Locale; import java.util.Set; import org.apache.hc.client5.http.classic.methods.HttpGet; -import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.classic.MinimalHttpClient; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.Header; @@ -41,17 +42,26 @@ import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Client protocol handling tests. */ -public class TestMinimalClientRequestExecution extends LocalServerTestBase { +public class TestMinimalClientRequestExecution { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); private static class SimpleService implements HttpRequestHandler { @@ -72,14 +82,16 @@ public class TestMinimalClientRequestExecution extends LocalServerTestBase { @Test public void testNonCompliantURIWithContext() throws Exception { - this.server.registerHandler("*", new SimpleService()); - this.httpclient = HttpClients.createMinimal(); - final HttpHost target = start(); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new SimpleService()); + final HttpHost target = testResources.targetHost(); + + final MinimalHttpClient client = testResources.startMinimalClient(); final HttpClientContext context = HttpClientContext.create(); for (int i = 0; i < 10; i++) { final HttpGet request = new HttpGet("/"); - this.httpclient.execute(target, request, context, response -> { + client.execute(target, request, context, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); return null; @@ -102,13 +114,15 @@ public class TestMinimalClientRequestExecution extends LocalServerTestBase { @Test public void testNonCompliantURIWithoutContext() throws Exception { - this.server.registerHandler("*", new SimpleService()); - this.httpclient = HttpClients.createMinimal(); - final HttpHost target = start(); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new SimpleService()); + final HttpHost target = testResources.targetHost(); + + final MinimalHttpClient client = testResources.startMinimalClient(); for (int i = 0; i < 10; i++) { final HttpGet request = new HttpGet("/"); - this.httpclient.execute(target, request, response -> { + client.execute(target, request, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); return null; diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java index f2bf834d9..2499f4798 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestRedirects.java @@ -33,6 +33,7 @@ import java.net.URI; import java.util.Collections; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.function.Consumer; import org.apache.hc.client5.http.CircularRedirectException; import org.apache.hc.client5.http.ClientProtocolException; @@ -42,12 +43,17 @@ import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.cookie.BasicCookieStore; import org.apache.hc.client5.http.cookie.CookieStore; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.cookie.BasicClientCookie; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.http.protocol.RedirectLocations; import org.apache.hc.client5.testing.OldPathRedirectResolver; +import org.apache.hc.client5.testing.classic.EchoHandler; +import org.apache.hc.client5.testing.classic.RandomHandler; import org.apache.hc.client5.testing.classic.RedirectingDecorator; import org.apache.hc.client5.testing.redirect.Redirect; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.function.Decorator; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.Header; @@ -57,30 +63,61 @@ import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.ProtocolException; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.HttpServerRequestHandler; 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.BasicHeader; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.http.protocol.HttpProcessor; import org.apache.hc.core5.net.URIBuilder; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.hamcrest.CoreMatchers; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Redirection test cases. */ -public class TestRedirects extends LocalServerTestBase { +public class TestRedirects { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); + + public ClassicTestServer startServer(final HttpProcessor httpProcessor, + final Decorator handlerDecorator) throws IOException { + return testResources.startServer(null, httpProcessor, handlerDecorator); + } + + public CloseableHttpClient startClient(final Consumer clientCustomizer) { + return testResources.startClient(clientCustomizer); + } + + public CloseableHttpClient startClient() { + return testResources.startClient(builder -> {}); + } + + public HttpHost targetHost() { + return testResources.targetHost(); + } @Test public void testBasicRedirect300() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); + final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -96,14 +133,18 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect300NoKeepAlive() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MULTIPLE_CHOICES, Redirect.ConnControl.CLOSE))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); + final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_MULTIPLE_CHOICES, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -120,15 +161,18 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect301() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_PERMANENTLY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -148,15 +192,18 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect302() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/50"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -170,7 +217,7 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect302NoLocation() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, requestUri -> { final String path = requestUri.getPath(); @@ -179,12 +226,15 @@ public class TestRedirects extends LocalServerTestBase { } return null; })); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { final HttpRequest reqWrapper = context.getRequest(); Assertions.assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getCode()); @@ -197,15 +247,18 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect303() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_SEE_OTHER))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/123"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -218,18 +271,21 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect304() throws Exception { - this.server.registerHandler("/oldlocation/*", (request, response, context) -> { + final ClassicTestServer server = startServer(null ,null); + server.registerHandler("/oldlocation/*", (request, response, context) -> { response.setCode(HttpStatus.SC_NOT_MODIFIED); response.addHeader(HttpHeaders.LOCATION, "/random/100"); }); - final HttpHost target = start(); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/stuff"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_NOT_MODIFIED, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -246,18 +302,21 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect305() throws Exception { - this.server.registerHandler("/oldlocation/*", (request, response, context) -> { + final ClassicTestServer server = startServer(null ,null); + server.registerHandler("/oldlocation/*", (request, response, context) -> { response.setCode(HttpStatus.SC_USE_PROXY); response.addHeader(HttpHeaders.LOCATION, "/random/100"); }); - final HttpHost target = start(); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/stuff"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_USE_PROXY, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -274,15 +333,18 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testBasicRedirect307() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_TEMPORARY_REDIRECT))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/123"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -295,11 +357,14 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testMaxRedirectCheck() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/", HttpStatus.SC_MOVED_TEMPORARILY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final RequestConfig config = RequestConfig.custom() .setCircularRedirectsAllowed(true) .setMaxRedirects(5) @@ -308,17 +373,20 @@ public class TestRedirects extends LocalServerTestBase { final HttpGet httpget = new HttpGet("/circular-oldlocation/123"); httpget.setConfig(config); final ClientProtocolException exception = Assertions.assertThrows(ClientProtocolException.class, () -> - this.httpclient.execute(target, httpget, response -> null)); + client.execute(target, httpget, response -> null)); Assertions.assertTrue(exception.getCause() instanceof RedirectException); } @Test public void testCircularRedirect() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/circular-oldlocation/", "/circular-oldlocation/", HttpStatus.SC_MOVED_TEMPORARILY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final RequestConfig config = RequestConfig.custom() .setCircularRedirectsAllowed(false) .build(); @@ -326,22 +394,25 @@ public class TestRedirects extends LocalServerTestBase { final HttpGet httpget = new HttpGet("/circular-oldlocation/123"); httpget.setConfig(config); final ClientProtocolException exception = Assertions.assertThrows(ClientProtocolException.class, () -> - this.httpclient.execute(target, httpget, response -> null)); + client.execute(target, httpget, response -> null)); Assertions.assertTrue(exception.getCause() instanceof CircularRedirectException); } @Test public void testPostRedirectSeeOther() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/echo", HttpStatus.SC_SEE_OTHER))); + server.registerHandler("/echo/*", new EchoHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpPost httppost = new HttpPost("/oldlocation/stuff"); httppost.setEntity(new StringEntity("stuff")); - this.httpclient.execute(target, httppost, context, response -> { + client.execute(target, httppost, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -355,7 +426,7 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testRelativeRedirect() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, requestUri -> { final String path = requestUri.getPath(); @@ -364,12 +435,15 @@ public class TestRedirects extends LocalServerTestBase { } return null; - })); + })); server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/stuff"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -382,7 +456,7 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testRelativeRedirect2() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, requestUri -> { final String path = requestUri.getPath(); @@ -392,12 +466,15 @@ public class TestRedirects extends LocalServerTestBase { } return null; })); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/random/oldlocation"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -410,7 +487,7 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testRejectBogusRedirectLocation() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, requestUri -> { final String path = requestUri.getPath(); @@ -420,17 +497,20 @@ public class TestRedirects extends LocalServerTestBase { } return null; })); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpGet httpget = new HttpGet("/oldlocation"); final ClientProtocolException exception = Assertions.assertThrows(ClientProtocolException.class, () -> - this.httpclient.execute(target, httpget, response -> null)); + client.execute(target, httpget, response -> null)); assertThat(exception.getCause(), CoreMatchers.instanceOf(HttpException.class)); } @Test public void testRejectInvalidRedirectLocation() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, requestUri -> { final String path = requestUri.getPath(); @@ -440,20 +520,26 @@ public class TestRedirects extends LocalServerTestBase { } return null; })); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpGet httpget = new HttpGet("/oldlocation"); final ClientProtocolException exception = Assertions.assertThrows(ClientProtocolException.class, () -> - this.httpclient.execute(target, httpget, response -> null)); + client.execute(target, httpget, response -> null)); assertThat(exception.getCause(), CoreMatchers.instanceOf(ProtocolException.class)); } @Test public void testRedirectWithCookie() throws Exception { - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final CookieStore cookieStore = new BasicCookieStore(); final BasicClientCookie cookie = new BasicClientCookie("name", "value"); @@ -463,10 +549,11 @@ public class TestRedirects extends LocalServerTestBase { cookieStore.addCookie(cookie); final HttpClientContext context = HttpClientContext.create(); + context.setCookieStore(cookieStore); final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -482,17 +569,21 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testDefaultHeadersRedirect() throws Exception { - this.clientBuilder.setDefaultHeaders(Collections.singletonList(new BasicHeader(HttpHeaders.USER_AGENT, "my-test-client"))); + final CloseableHttpClient client = startClient(builder -> builder + .setDefaultHeaders(Collections.singletonList(new BasicHeader(HttpHeaders.USER_AGENT, "my-test-client"))) + ); - final HttpHost target = start(null, requestHandler -> new RedirectingDecorator( + final ClassicTestServer server = startServer(null, requestHandler -> new RedirectingDecorator( requestHandler, new OldPathRedirectResolver("/oldlocation", "/random", HttpStatus.SC_MOVED_TEMPORARILY))); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; @@ -509,7 +600,7 @@ public class TestRedirects extends LocalServerTestBase { @Test public void testCompressionHeaderRedirect() throws Exception { final Queue values = new ConcurrentLinkedQueue<>(); - final HttpHost target = start(null, new Decorator() { + final ClassicTestServer server = startServer(null, new Decorator() { @Override public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) { @@ -532,12 +623,15 @@ public class TestRedirects extends LocalServerTestBase { } }); + server.registerHandler("/random/*", new RandomHandler()); + final HttpHost target = targetHost(); + final CloseableHttpClient client = startClient(); final HttpClientContext context = HttpClientContext.create(); final HttpGet httpget = new HttpGet("/oldlocation/100"); - this.httpclient.execute(target, httpget, context, response -> { + client.execute(target, httpget, context, response -> { Assertions.assertEquals(HttpStatus.SC_OK, response.getCode()); EntityUtils.consume(response.getEntity()); return null; diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java index 5cea00876..16accd2bf 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java @@ -40,12 +40,14 @@ import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.impl.auth.SPNegoScheme; -import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.io.HttpRequestHandler; @@ -53,18 +55,26 @@ 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.BasicHeader; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; /** * Tests for {@link SPNegoScheme}. */ -public class TestSPNegoScheme extends LocalServerTestBase { +public class TestSPNegoScheme { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); /** * This service will continue to ask for authentication. @@ -150,8 +160,9 @@ public class TestSPNegoScheme extends LocalServerTestBase { */ @Test public void testDontTryToAuthenticateEndlessly() throws Exception { - this.server.registerHandler("*", new PleaseNegotiateService()); - final HttpHost target = start(); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new PleaseNegotiateService()); + final HttpHost target = testResources.targetHost(); final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager(); final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() @@ -161,14 +172,15 @@ public class TestSPNegoScheme extends LocalServerTestBase { final Registry authSchemeRegistry = RegistryBuilder.create() .register(StandardAuthScheme.SPNEGO, nsf) .build(); - this.httpclient = HttpClients.custom() - .setDefaultAuthSchemeRegistry(authSchemeRegistry) - .setDefaultCredentialsProvider(credentialsProvider) - .build(); + + final CloseableHttpClient client = testResources.startClient(builder -> builder + .setDefaultAuthSchemeRegistry(authSchemeRegistry) + .setDefaultCredentialsProvider(credentialsProvider) + ); final String s = "/path"; final HttpGet httpget = new HttpGet(s); - this.httpclient.execute(target, httpget, response -> { + client.execute(target, httpget, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; @@ -181,8 +193,9 @@ public class TestSPNegoScheme extends LocalServerTestBase { */ @Test public void testNoTokenGeneratedError() throws Exception { - this.server.registerHandler("*", new PleaseNegotiateService()); - final HttpHost target = start(); + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new PleaseNegotiateService()); + final HttpHost target = testResources.targetHost(); final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager(); @@ -193,14 +206,15 @@ public class TestSPNegoScheme extends LocalServerTestBase { final Registry authSchemeRegistry = RegistryBuilder.create() .register(StandardAuthScheme.SPNEGO, nsf) .build(); - this.httpclient = HttpClients.custom() - .setDefaultAuthSchemeRegistry(authSchemeRegistry) - .setDefaultCredentialsProvider(credentialsProvider) - .build(); + + final CloseableHttpClient client = testResources.startClient(builder -> builder + .setDefaultAuthSchemeRegistry(authSchemeRegistry) + .setDefaultCredentialsProvider(credentialsProvider) + ); final String s = "/path"; final HttpGet httpget = new HttpGet(s); - this.httpclient.execute(target, httpget, response -> { + client.execute(target, httpget, response -> { EntityUtils.consume(response.getEntity()); Assertions.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode()); return null; diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestStatefulConnManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestStatefulConnManagement.java index bb6017b15..6a85a3d96 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestStatefulConnManagement.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestStatefulConnManagement.java @@ -32,24 +32,35 @@ import org.apache.hc.client5.http.UserTokenHandler; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.EndpointDetails; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.io.HttpRequestHandler; import org.apache.hc.core5.http.io.entity.EntityUtils; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.protocol.BasicHttpContext; import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; import org.junit.jupiter.api.Assertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Test cases for state-ful connections. */ -public class TestStatefulConnManagement extends LocalServerTestBase { +public class TestStatefulConnManagement { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + public static final Timeout LONG_TIMEOUT = Timeout.ofMinutes(3); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); private static class SimpleService implements HttpRequestHandler { @@ -70,22 +81,25 @@ public class TestStatefulConnManagement extends LocalServerTestBase { @Test public void testStatefulConnections() throws Exception { + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new SimpleService()); + final HttpHost target = testResources.targetHost(); final int workerCount = 5; final int requestCount = 5; - this.server.registerHandler("*", new SimpleService()); - - this.connManager.setMaxTotal(workerCount); - this.connManager.setDefaultMaxPerRoute(workerCount); - final UserTokenHandler userTokenHandler = (route, context) -> { final String id = (String) context.getAttribute("user"); return id; }; - this.clientBuilder.setUserTokenHandler(userTokenHandler); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(workerCount) + .setMaxConnPerRoute(workerCount), + builder -> builder + .setUserTokenHandler(userTokenHandler) + ); final HttpClientContext[] contexts = new HttpClientContext[workerCount]; final HttpWorker[] workers = new HttpWorker[workerCount]; @@ -94,7 +108,7 @@ public class TestStatefulConnManagement extends LocalServerTestBase { contexts[i] = context; workers[i] = new HttpWorker( "user" + i, - context, requestCount, target, this.httpclient); + context, requestCount, target, client); } for (final HttpWorker worker : workers) { @@ -181,27 +195,31 @@ public class TestStatefulConnManagement extends LocalServerTestBase { @Test public void testRouteSpecificPoolRecylcing() throws Exception { + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("*", new SimpleService()); + final HttpHost target = testResources.targetHost(); + // This tests what happens when a maxed connection pool needs // to kill the last idle connection to a route to build a new // one to the same route. final int maxConn = 2; - this.server.registerHandler("*", new SimpleService()); - - this.connManager.setMaxTotal(maxConn); - this.connManager.setDefaultMaxPerRoute(maxConn); final UserTokenHandler userTokenHandler = (route, context) -> context.getAttribute("user"); - this.clientBuilder.setUserTokenHandler(userTokenHandler); - - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient( + builder -> builder + .setMaxConnTotal(maxConn) + .setMaxConnPerRoute(maxConn), + builder -> builder + .setUserTokenHandler(userTokenHandler) + ); // Bottom of the pool : a *keep alive* connection to Route 1. final HttpContext context1 = new BasicHttpContext(); context1.setAttribute("user", "stuff"); - this.httpclient.execute(target, new HttpGet("/"), context1, response -> { + client.execute(target, new HttpGet("/"), context1, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -215,7 +233,7 @@ public class TestStatefulConnManagement extends LocalServerTestBase { // Send a very simple HTTP get (it MUST be simple, no auth, no proxy, no 302, no 401, ...) // Send it to another route. Must be a keepalive. final HttpContext context2 = new BasicHttpContext(); - this.httpclient.execute(new HttpHost("127.0.0.1", this.server.getPort()), new HttpGet("/"), context2, response -> { + client.execute(new HttpHost("127.0.0.1", server.getPort()), new HttpGet("/"), context2, response -> { EntityUtils.consume(response.getEntity()); return null; }); @@ -231,7 +249,7 @@ public class TestStatefulConnManagement extends LocalServerTestBase { // The killed conn is the oldest, which means the first HTTPGet ([localhost][stuff]). // When this happens, the RouteSpecificPool becomes empty. final HttpContext context3 = new BasicHttpContext(); - this.httpclient.execute(target, new HttpGet("/"), context3, response -> { + client.execute(target, new HttpGet("/"), context3, response -> { EntityUtils.consume(response.getEntity()); return null; }); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestWindowsNegotiateScheme.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestWindowsNegotiateScheme.java index 7ed9172a3..8214b0f96 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestWindowsNegotiateScheme.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestWindowsNegotiateScheme.java @@ -32,32 +32,42 @@ import org.apache.hc.client5.http.auth.AuthSchemeFactory; import org.apache.hc.client5.http.auth.StandardAuthScheme; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; -import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; import org.apache.hc.client5.http.impl.win.WinHttpClients; import org.apache.hc.client5.http.impl.win.WindowsNegotiateSchemeGetTokenFail; +import org.apache.hc.client5.testing.sync.extension.TestClientResources; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.io.entity.EntityUtils; -import org.junit.Assume; -import org.junit.Test; -import org.junit.jupiter.api.Timeout; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** * Unit tests for Windows negotiate authentication. */ -public class TestWindowsNegotiateScheme extends LocalServerTestBase { +public class TestWindowsNegotiateScheme { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private TestClientResources testResources = new TestClientResources(URIScheme.HTTP, TIMEOUT); @Test // this timeout (in ms) needs to be extended if you're actively debugging the code - @Timeout(value = 30000, unit = MILLISECONDS) + @org.junit.jupiter.api.Timeout(value = 30000, unit = MILLISECONDS) public void testNoInfiniteLoopOnSPNOutsideDomain() throws Exception { - this.server.registerHandler("/", (request, response, context) -> { + final ClassicTestServer server = testResources.startServer(null, null, null); + server.registerHandler("/", (request, response, context) -> { response.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.SPNEGO); response.setCode(HttpStatus.SC_UNAUTHORIZED); }); - Assume.assumeTrue("Test can only be run on Windows", WinHttpClients.isWinAuthAvailable()); + final HttpHost target = testResources.targetHost(); + Assumptions.assumeTrue(WinHttpClients.isWinAuthAvailable(), "Test can only be run on Windows"); // HTTPCLIENT-1545 // If a service principal name (SPN) from outside your Windows domain tree (e.g., HTTP/example.com) is used, @@ -69,12 +79,13 @@ public class TestWindowsNegotiateScheme extends LocalServerTestBase { final Registry authSchemeRegistry = RegistryBuilder.create() .register(StandardAuthScheme.SPNEGO, context -> new WindowsNegotiateSchemeGetTokenFail(StandardAuthScheme.SPNEGO, "HTTP/example.com")).build(); - final CloseableHttpClient customClient = HttpClientBuilder.create() - .setDefaultAuthSchemeRegistry(authSchemeRegistry).build(); - final HttpHost target = start(); + final CloseableHttpClient client = testResources.startClient(builder -> builder + .setDefaultAuthSchemeRegistry(authSchemeRegistry) + ); + final HttpGet httpGet = new HttpGet("/"); - customClient.execute(target, httpGet, response -> { + client.execute(target, httpGet, response -> { EntityUtils.consume(response.getEntity()); return null; }); diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/extension/TestClientResources.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/extension/TestClientResources.java new file mode 100644 index 000000000..083a5f25d --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/extension/TestClientResources.java @@ -0,0 +1,167 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.hc.client5.testing.sync.extension; + +import java.io.IOException; +import java.util.function.Consumer; + +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.classic.MinimalHttpClient; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.testing.SSLTestContexts; +import org.apache.hc.core5.function.Decorator; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.config.Http1Config; +import org.apache.hc.core5.http.io.HttpServerRequestHandler; +import org.apache.hc.core5.http.io.SocketConfig; +import org.apache.hc.core5.http.protocol.HttpProcessor; +import org.apache.hc.core5.io.CloseMode; +import org.apache.hc.core5.testing.classic.ClassicTestServer; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestClientResources implements BeforeEachCallback, AfterEachCallback { + + private static final Logger LOG = LoggerFactory.getLogger(TestClientResources.class); + + private final URIScheme scheme; + private final Timeout timeout; + + private ClassicTestServer server; + private PoolingHttpClientConnectionManager connManager; + private CloseableHttpClient client; + + public TestClientResources(final URIScheme scheme, final Timeout timeout) { + this.scheme = scheme; + this.timeout = timeout; + } + + @Override + public void beforeEach(final ExtensionContext extensionContext) throws Exception { + LOG.debug("Starting up test server"); + server = new ClassicTestServer( + scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null, + SocketConfig.custom() + .setSoTimeout(timeout) + .build()); + } + + @Override + public void afterEach(final ExtensionContext extensionContext) throws Exception { + LOG.debug("Shutting down test server"); + + if (client != null) { + client.close(CloseMode.GRACEFUL); + } + + if (connManager != null) { + connManager.close(CloseMode.IMMEDIATE); + } + + if (server != null) { + server.shutdown(CloseMode.IMMEDIATE); + } + } + + public ClassicTestServer startServer( + final Http1Config http1Config, + final HttpProcessor httpProcessor, + final Decorator handlerDecorator) throws IOException { + Assertions.assertNotNull(server); + server.start(http1Config, httpProcessor, handlerDecorator); + return server; + } + + public HttpHost targetHost() { + Assertions.assertNotNull(server); + return new HttpHost(scheme.id, "localhost", server.getPort()); + } + + public CloseableHttpClient startClient( + final Consumer connManagerCustomizer, + final Consumer clientCustomizer) { + Assertions.assertNull(connManager); + Assertions.assertNull(client); + + final PoolingHttpClientConnectionManagerBuilder connManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create(); + connManagerBuilder.setDefaultSocketConfig(SocketConfig.custom() + .setSoTimeout(timeout) + .build()); + connManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setConnectTimeout(timeout) + .build()); + connManagerCustomizer.accept(connManagerBuilder); + + connManager = connManagerBuilder.build(); + + final HttpClientBuilder clientBuilder = HttpClientBuilder.create() + .setConnectionManager(connManager); + clientCustomizer.accept(clientBuilder); + client = clientBuilder.build(); + return client; + } + + public MinimalHttpClient startMinimalClient() { + Assertions.assertNull(connManager); + Assertions.assertNull(client); + + final PoolingHttpClientConnectionManagerBuilder connManagerBuilder = PoolingHttpClientConnectionManagerBuilder.create(); + connManagerBuilder.setDefaultSocketConfig(SocketConfig.custom() + .setSoTimeout(timeout) + .build()); + connManagerBuilder.setDefaultConnectionConfig(ConnectionConfig.custom() + .setConnectTimeout(timeout) + .build()); + connManager = connManagerBuilder.build(); + + final MinimalHttpClient minimalClient = HttpClients.createMinimal(connManager); + client = minimalClient; + return minimalClient; + } + + public CloseableHttpClient startClient( + final Consumer clientCustomizer) { + return startClient(b -> {}, clientCustomizer); + } + + public PoolingHttpClientConnectionManager connManager() { + Assertions.assertNotNull(connManager); + return connManager; + } + +} diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java index 302e5af96..6f72c6bb0 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java @@ -38,7 +38,6 @@ import org.apache.hc.core5.function.Resolver; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.http.config.RegistryBuilder; -import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.nio.ssl.TlsStrategy; import org.apache.hc.core5.pool.PoolConcurrencyPolicy; import org.apache.hc.core5.pool.PoolReusePolicy; @@ -84,7 +83,6 @@ public class PoolingAsyncClientConnectionManagerBuilder { private int maxConnTotal; private int maxConnPerRoute; - private Resolver socketConfigResolver; private Resolver connectionConfigResolver; private Resolver tlsConfigResolver;