You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2017/10/16 12:53:52 UTC
[6/6] httpcomponents-client git commit: Added HTTP cache integration
tests
Added HTTP cache integration tests
Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/eac3d937
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/eac3d937
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/eac3d937
Branch: refs/heads/master
Commit: eac3d937a405a1dc9ac8f882aaaa96e7a1dab9a8
Parents: e63bbb8
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Mon Oct 16 14:24:48 2017 +0200
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Mon Oct 16 14:34:52 2017 +0200
----------------------------------------------------------------------
httpclient5-testing/pom.xml | 6 +
...CachingHttpAsyncClientCompatibilityTest.java | 239 +++++++++++++++++++
.../CachingHttpClientCompatibilityTest.java | 205 ++++++++++++++++
3 files changed, 450 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/eac3d937/httpclient5-testing/pom.xml
----------------------------------------------------------------------
diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml
index 01c1026..ced3c84 100644
--- a/httpclient5-testing/pom.xml
+++ b/httpclient5-testing/pom.xml
@@ -60,6 +60,12 @@
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
+ <artifactId>httpclient5-cache</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>${project.version}</version>
<scope>test</scope>
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/eac3d937/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
new file mode 100644
index 0000000..7d836af
--- /dev/null
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
@@ -0,0 +1,239 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.testing.external;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.cache.CacheResponseStatus;
+import org.apache.hc.client5.http.cache.HttpCacheContext;
+import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
+import org.apache.hc.client5.http.impl.cache.CacheConfig;
+import org.apache.hc.client5.http.impl.cache.CachingHttpAsyncClients;
+import org.apache.hc.client5.http.impl.cache.HeapResourceFactory;
+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.H2TlsStrategy;
+import org.apache.hc.core5.http.Header;
+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.http2.HttpVersionPolicy;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.util.TextUtils;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+
+public class CachingHttpAsyncClientCompatibilityTest {
+
+ public static void main(final String... args) throws Exception {
+ final CachingHttpAsyncClientCompatibilityTest[] tests = new CachingHttpAsyncClientCompatibilityTest[] {
+ new CachingHttpAsyncClientCompatibilityTest(
+ HttpVersion.HTTP_1_1, new HttpHost("localhost", 8080, "http")),
+ new CachingHttpAsyncClientCompatibilityTest(
+ HttpVersion.HTTP_2_0, new HttpHost("localhost", 8080, "http"))
+ };
+ for (final CachingHttpAsyncClientCompatibilityTest test: tests) {
+ try {
+ test.execute();
+ } finally {
+ test.shutdown();
+ }
+ }
+ }
+
+ private static final Timeout TIMEOUT = Timeout.ofSeconds(5);
+
+ private final HttpVersion protocolVersion;
+ private final HttpHost target;
+ private final PoolingAsyncClientConnectionManager connManager;
+ private final CloseableHttpAsyncClient client;
+
+ CachingHttpAsyncClientCompatibilityTest(final HttpVersion protocolVersion, final HttpHost target) throws Exception {
+ this.protocolVersion = protocolVersion;
+ this.target = target;
+ final SSLContext sslContext = SSLContexts.custom()
+ .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
+ this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
+ .setTlsStrategy(new H2TlsStrategy(sslContext))
+ .build();
+ this.client = CachingHttpAsyncClients.custom()
+ .setCacheConfig(CacheConfig.custom()
+ .setMaxObjectSize(20480)
+ .build())
+ .setResourceFactory(HeapResourceFactory.INSTANCE)
+ .setVersionPolicy(this.protocolVersion == HttpVersion.HTTP_2 ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
+ .setConnectionManager(this.connManager)
+ .build();
+ }
+
+
+ void shutdown() throws Exception {
+ client.close();
+ }
+
+ enum TestResult {OK, NOK};
+
+ private void logResult(final TestResult result, final HttpRequest request, final String message) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append(result);
+ if (buf.length() == 2) {
+ buf.append(" ");
+ }
+ buf.append(": ").append(target);
+ buf.append(": ");
+ buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
+ if (message != null && !TextUtils.isBlank(message)) {
+ buf.append(" -> ").append(message);
+ }
+ System.out.println(buf.toString());
+ }
+
+ void execute() throws Exception {
+
+ client.start();
+ // Initial ping
+ {
+ final HttpCacheContext context = HttpCacheContext.create();
+ final SimpleHttpRequest options = SimpleHttpRequest.options(target, "*");
+ final Future<SimpleHttpResponse> future = client.execute(options, context, null);
+ try {
+ final SimpleHttpResponse response = future.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ final int code = response.getCode();
+ if (code == HttpStatus.SC_OK) {
+ logResult(TestResult.OK, options, Objects.toString(response.getFirstHeader("server")));
+ } else {
+ logResult(TestResult.NOK, options, "(status " + code + ")");
+ }
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause();
+ logResult(TestResult.NOK, options, "(" + cause.getMessage() + ")");
+ } catch (final TimeoutException ex) {
+ logResult(TestResult.NOK, options, "(time out)");
+ }
+ }
+ // GET with links
+ {
+ connManager.closeIdle(TimeValue.NEG_ONE_MILLISECONDS);
+ final HttpCacheContext context = HttpCacheContext.create();
+
+ final Pattern linkPattern = Pattern.compile("^<(.*)>;rel=preload$");
+ final List<String> links = new ArrayList<>();
+ final SimpleHttpRequest getRoot1 = SimpleHttpRequest.get(target, "/");
+ final Future<SimpleHttpResponse> future1 = client.execute(getRoot1, context, null);
+ try {
+ final SimpleHttpResponse response = future1.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
+ logResult(TestResult.OK, getRoot1, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot1, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ for (final Header header: response.getHeaders("Link")) {
+ final Matcher matcher = linkPattern.matcher(header.getValue());
+ if (matcher.matches()) {
+ links.add(matcher.group(1));
+ }
+ }
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause();
+ logResult(TestResult.NOK, getRoot1, "(" + cause.getMessage() + ")");
+ } catch (final TimeoutException ex) {
+ logResult(TestResult.NOK, getRoot1, "(time out)");
+ }
+ for (final String link: links) {
+ final SimpleHttpRequest getLink = SimpleHttpRequest.get(target, link);
+ final Future<SimpleHttpResponse> linkFuture = client.execute(getLink, context, null);
+ try {
+ final SimpleHttpResponse response = linkFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
+ logResult(TestResult.OK, getLink, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getLink, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause();
+ logResult(TestResult.NOK, getLink, "(" + cause.getMessage() + ")");
+ } catch (final TimeoutException ex) {
+ logResult(TestResult.NOK, getLink, "(time out)");
+ }
+ }
+
+ final SimpleHttpRequest getRoot2 = SimpleHttpRequest.get(target, "/");
+ final Future<SimpleHttpResponse> future2 = client.execute(getRoot2, context, null);
+ try {
+ final SimpleHttpResponse response = future2.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
+ logResult(TestResult.OK, getRoot2, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot2, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause();
+ logResult(TestResult.NOK, getRoot2, "(" + cause.getMessage() + ")");
+ } catch (final TimeoutException ex) {
+ logResult(TestResult.NOK, getRoot2, "(time out)");
+ }
+ for (final String link: links) {
+ final SimpleHttpRequest getLink = SimpleHttpRequest.get(target, link);
+ final Future<SimpleHttpResponse> linkFuture = client.execute(getLink, context, null);
+ try {
+ final SimpleHttpResponse response = linkFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
+ logResult(TestResult.OK, getLink, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getLink, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final ExecutionException ex) {
+ final Throwable cause = ex.getCause();
+ logResult(TestResult.NOK, getLink, "(" + cause.getMessage() + ")");
+ } catch (final TimeoutException ex) {
+ logResult(TestResult.NOK, getLink, "(time out)");
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/eac3d937/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpClientCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpClientCompatibilityTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpClientCompatibilityTest.java
new file mode 100644
index 0000000..4b9b0ef
--- /dev/null
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpClientCompatibilityTest.java
@@ -0,0 +1,205 @@
+/*
+ * ====================================================================
+ * 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
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.testing.external;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.hc.client5.http.cache.CacheResponseStatus;
+import org.apache.hc.client5.http.cache.HttpCacheContext;
+import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.classic.methods.HttpOptions;
+import org.apache.hc.client5.http.impl.cache.CacheConfig;
+import org.apache.hc.client5.http.impl.cache.CachingHttpClients;
+import org.apache.hc.client5.http.impl.cache.HeapResourceFactory;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.Header;
+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.io.entity.EntityUtils;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.util.TextUtils;
+import org.apache.hc.core5.util.TimeValue;
+
+public class CachingHttpClientCompatibilityTest {
+
+ public static void main(final String... args) throws Exception {
+ final CachingHttpClientCompatibilityTest[] tests = new CachingHttpClientCompatibilityTest[] {
+ new CachingHttpClientCompatibilityTest(
+ new HttpHost("localhost", 8080, "http"))
+ };
+ for (final CachingHttpClientCompatibilityTest test: tests) {
+ try {
+ test.execute();
+ } finally {
+ test.shutdown();
+ }
+ }
+ }
+
+ private final HttpHost target;
+ private final PoolingHttpClientConnectionManager connManager;
+ private final CloseableHttpClient client;
+
+ CachingHttpClientCompatibilityTest(final HttpHost target) throws Exception {
+ this.target = target;
+ final SSLContext sslContext = SSLContexts.custom()
+ .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
+ this.connManager = PoolingHttpClientConnectionManagerBuilder.create()
+ .setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext))
+ .build();
+ this.client = CachingHttpClients.custom()
+ .setCacheConfig(CacheConfig.custom()
+ .setMaxObjectSize(20480)
+ .build())
+ .setResourceFactory(HeapResourceFactory.INSTANCE)
+ .setConnectionManager(this.connManager)
+ .build();
+ }
+
+ void shutdown() throws Exception {
+ client.close();
+ }
+
+ enum TestResult {OK, NOK};
+
+ private void logResult(final TestResult result, final HttpRequest request, final String message) {
+ final StringBuilder buf = new StringBuilder();
+ buf.append(result);
+ if (buf.length() == 2) {
+ buf.append(" ");
+ }
+ buf.append(": ").append(target);
+ buf.append(": ");
+ buf.append(request.getMethod()).append(" ").append(request.getRequestUri());
+ if (message != null && !TextUtils.isBlank(message)) {
+ buf.append(" -> ").append(message);
+ }
+ System.out.println(buf.toString());
+ }
+
+ void execute() {
+
+ // Initial ping
+ {
+ final HttpCacheContext context = HttpCacheContext.create();
+ final HttpOptions options = new HttpOptions("*");
+ try (final ClassicHttpResponse response = client.execute(target, options, context)) {
+ final int code = response.getCode();
+ EntityUtils.consume(response.getEntity());
+ if (code == HttpStatus.SC_OK) {
+ logResult(TestResult.OK, options, Objects.toString(response.getFirstHeader("server")));
+ } else {
+ logResult(TestResult.NOK, options, "(status " + code + ")");
+ }
+ } catch (final Exception ex) {
+ logResult(TestResult.NOK, options, "(" + ex.getMessage() + ")");
+ }
+ }
+ // GET with links
+ {
+ connManager.closeIdle(TimeValue.NEG_ONE_MILLISECONDS);
+ final HttpCacheContext context = HttpCacheContext.create();
+ final Pattern linkPattern = Pattern.compile("^<(.*)>;rel=preload$");
+ final List<String> links = new ArrayList<>();
+ final HttpGet getRoot1 = new HttpGet("/");
+ try (ClassicHttpResponse response = client.execute(target, getRoot1, context)) {
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ EntityUtils.consume(response.getEntity());
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
+ logResult(TestResult.OK, getRoot1, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot1, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ for (final Header header: response.getHeaders("Link")) {
+ final Matcher matcher = linkPattern.matcher(header.getValue());
+ if (matcher.matches()) {
+ links.add(matcher.group(1));
+ }
+ }
+ } catch (final Exception ex) {
+ logResult(TestResult.NOK, getRoot1, "(" + ex.getMessage() + ")");
+ }
+
+ for (final String link: links) {
+ final HttpGet getLink = new HttpGet(link);
+ try (ClassicHttpResponse response = client.execute(target, getLink, context)) {
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ EntityUtils.consume(response.getEntity());
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.CACHE_MISS) {
+ logResult(TestResult.OK, getRoot1, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot1, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final Exception ex) {
+ logResult(TestResult.NOK, getLink, "(" + ex.getMessage() + ")");
+ }
+ }
+ final HttpGet getRoot2 = new HttpGet("/");
+ try (ClassicHttpResponse response = client.execute(target, getRoot2, context)) {
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ EntityUtils.consume(response.getEntity());
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
+ logResult(TestResult.OK, getRoot2, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot2, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final Exception ex) {
+ logResult(TestResult.NOK, getRoot2, "(" + ex.getMessage() + ")");
+ }
+ for (final String link: links) {
+ final HttpGet getLink = new HttpGet(link);
+ try (ClassicHttpResponse response = client.execute(target, getLink, context)) {
+ final int code = response.getCode();
+ final CacheResponseStatus cacheResponseStatus = context.getCacheResponseStatus();
+ EntityUtils.consume(response.getEntity());
+ if (code == HttpStatus.SC_OK && cacheResponseStatus == CacheResponseStatus.VALIDATED) {
+ logResult(TestResult.OK, getRoot2, "200, " + cacheResponseStatus);
+ } else {
+ logResult(TestResult.NOK, getRoot2, "(status " + code + ", " + cacheResponseStatus + ")");
+ }
+ } catch (final Exception ex) {
+ logResult(TestResult.NOK, getLink, "(" + ex.getMessage() + ")");
+ }
+ }
+ }
+ }
+
+}