diff -r 89829dd3cc54 -r b1c1b4ef4be2 test/jdk/java/net/httpclient/SplitResponse.java --- a/test/jdk/java/net/httpclient/SplitResponse.java Fri Nov 03 10:01:08 2017 -0700 +++ b/test/jdk/java/net/httpclient/SplitResponse.java Wed Dec 06 11:11:59 2017 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,38 +21,49 @@ * questions. */ - import java.io.IOException; +import java.net.URI; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLContext; +import javax.net.ServerSocketFactory; +import javax.net.ssl.SSLServerSocketFactory; import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpClient.Version; import jdk.incubator.http.HttpRequest; import jdk.incubator.http.HttpResponse; -import java.net.URI; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; +import jdk.testlibrary.SimpleSSLContext; +import static java.lang.System.out; +import static java.lang.String.format; import static jdk.incubator.http.HttpResponse.BodyHandler.asString; /** * @test * @bug 8087112 - * @key intermittent - * @build Server - * @run main/othervm -Djava.net.HttpClient.log=all SplitResponse + * @library /lib/testlibrary + * @build jdk.testlibrary.SimpleSSLContext + * @build MockServer + * @run main/othervm -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=all SplitResponse */ /** * Similar test to QuickResponses except that each byte of the response * is sent in a separate packet, which tests the stability of the implementation - * for receiving unusual packet sizes. + * for receiving unusual packet sizes. Additionally, tests scenarios there + * connections that are retrieved from the connection pool may reach EOF before + * being reused. */ public class SplitResponse { - static Server server; + static String response(String body, boolean serverKeepalive) { + StringBuilder sb = new StringBuilder(); + sb.append("HTTP/1.1 200 OK\r\n"); + if (!serverKeepalive) + sb.append("Connection: Close\r\n"); - static String response(String body) { - return "HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-length: " - + Integer.toString(body.length()) - + "\r\n\r\n" + body; + sb.append("Content-length: ").append(body.length()).append("\r\n"); + sb.append("\r\n"); + sb.append(body); + return sb.toString(); } static final String responses[] = { @@ -68,59 +79,151 @@ "Excepteur sint occaecat cupidatat non proident." }; + final ServerSocketFactory factory; + final SSLContext context; + final boolean useSSL; + SplitResponse(boolean useSSL) throws IOException { + this.useSSL = useSSL; + context = new SimpleSSLContext().get(); + SSLContext.setDefault(context); + factory = useSSL ? SSLServerSocketFactory.getDefault() + : ServerSocketFactory.getDefault(); + } + + public HttpClient newHttpClient() { + HttpClient client; + if (useSSL) { + client = HttpClient.newBuilder() + .sslContext(context) + .build(); + } else { + client = HttpClient.newHttpClient(); + } + return client; + } + public static void main(String[] args) throws Exception { - server = new Server(0); + boolean useSSL = false; + if (args != null && args.length == 1) { + useSSL = "SSL".equals(args[0]); + } + SplitResponse sp = new SplitResponse(useSSL); + + for (Version version : Version.values()) { + for (boolean serverKeepalive : new boolean[]{ true, false }) { + // Note: the mock server doesn't support Keep-Alive, but + // pretending that it might exercises code paths in and out of + // the connection pool, and retry logic + for (boolean async : new boolean[]{ true, false }) { + sp.test(version, serverKeepalive, async); + } + } + } + } + + // @Test + void test(Version version, boolean serverKeepalive, boolean async) + throws Exception + { + out.println(format("*** version %s, serverKeepAlive: %s, async: %s ***", + version, serverKeepalive, async)); + MockServer server = new MockServer(0, factory); URI uri = new URI(server.getURL()); + out.println("server is: " + uri); server.start(); - HttpClient client = HttpClient.newHttpClient(); - HttpRequest request = HttpRequest.newBuilder(uri).build(); + + // The following code can be uncommented to verify that the + // MockServer will reject rogue requests whose URI does not + // contain "/foo/". + // + // Thread rogue = new Thread() { + // public void run() { + // try { + // HttpClient client = newHttpClient(); + // URI uri2 = URI.create(uri.toString().replace("/foo/","/")); + // HttpRequest request = HttpRequest + // .newBuilder(uri2).version(version).build(); + // while (true) { + // try { + // client.send(request, HttpResponse.BodyHandler.asString()); + // } catch (IOException ex) { + // System.out.println("Client rejected " + request); + // } + // sleep(250); + // } + // } catch ( Throwable x) { + // } + // } + // }; + // rogue.setDaemon(true); + // rogue.start(); + + + HttpClient client = newHttpClient(); + HttpRequest request = HttpRequest.newBuilder(uri).version(version).build(); HttpResponse r; CompletableFuture> cf1; try { for (int i=0; i { + System.out.println("Waiting for server to receive headers"); + conn = server.activity(); + System.out.println("Start sending response"); + try { int len = s.length(); + out.println("sending " + s); for (int i = 0; i < len; i++) { String onechar = s.substring(i, i + 1); conn.send(onechar); - Thread.sleep(30); + Thread.sleep(10); } - System.out.println("sent"); + out.println("sent " + s); } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); } }); t.setDaemon(true); t.start(); + return t; } }