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() + ")");
+                }
+            }
+        }
+    }
+
+}