test/jdk/java/net/httpclient/SplitResponse.java
branchhttp-client-branch
changeset 55763 634d8e14c172
parent 47216 71c04702a3d5
child 55891 050803da27e5
equal deleted inserted replaced
55762:e947a3a50a95 55763:634d8e14c172
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 
       
    25 import java.io.IOException;
    24 import java.io.IOException;
    26 import jdk.incubator.http.HttpClient;
       
    27 import jdk.incubator.http.HttpRequest;
       
    28 import jdk.incubator.http.HttpResponse;
       
    29 import java.net.URI;
    25 import java.net.URI;
    30 import java.util.concurrent.CompletableFuture;
    26 import java.util.concurrent.CompletableFuture;
    31 import java.util.concurrent.Executor;
    27 import java.util.concurrent.Executor;
    32 import java.util.concurrent.ExecutorService;
    28 import java.util.concurrent.ExecutorService;
       
    29 import javax.net.ssl.SSLContext;
       
    30 import javax.net.ServerSocketFactory;
       
    31 import javax.net.ssl.SSLServerSocketFactory;
       
    32 import jdk.incubator.http.HttpClient;
       
    33 import jdk.incubator.http.HttpClient.Version;
       
    34 import jdk.incubator.http.HttpRequest;
       
    35 import jdk.incubator.http.HttpResponse;
       
    36 import jdk.testlibrary.SimpleSSLContext;
       
    37 import static java.lang.System.out;
       
    38 import static java.lang.String.format;
    33 import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
    39 import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
    34 
    40 
    35 /**
    41 /**
    36  * @test
    42  * @test
    37  * @bug 8087112
    43  * @bug 8087112
    38  * @key intermittent
    44  * @library /lib/testlibrary
    39  * @build Server
    45  * @build jdk.testlibrary.SimpleSSLContext
    40  * @run main/othervm -Djava.net.HttpClient.log=all SplitResponse
    46  * @build MockServer
       
    47  * @run main/othervm -Djdk.internal.httpclient.debug=true -Djdk.httpclient.HttpClient.log=all SplitResponse
    41  */
    48  */
    42 
    49 
    43 /**
    50 /**
    44  * Similar test to QuickResponses except that each byte of the response
    51  * Similar test to QuickResponses except that each byte of the response
    45  * is sent in a separate packet, which tests the stability of the implementation
    52  * is sent in a separate packet, which tests the stability of the implementation
    46  * for receiving unusual packet sizes.
    53  * for receiving unusual packet sizes. Additionally, tests scenarios there
       
    54  * connections that are retrieved from the connection pool may reach EOF before
       
    55  * being reused.
    47  */
    56  */
    48 public class SplitResponse {
    57 public class SplitResponse {
    49 
    58 
    50     static Server server;
    59     static String response(String body, boolean serverKeepalive) {
    51 
    60         StringBuilder sb = new StringBuilder();
    52     static String response(String body) {
    61         sb.append("HTTP/1.1 200 OK\r\n");
    53         return "HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-length: "
    62         if (!serverKeepalive)
    54                 + Integer.toString(body.length())
    63             sb.append("Connection: Close\r\n");
    55                 + "\r\n\r\n" + body;
    64 
       
    65         sb.append("Content-length: ").append(body.length()).append("\r\n");
       
    66         sb.append("\r\n");
       
    67         sb.append(body);
       
    68         return sb.toString();
    56     }
    69     }
    57 
    70 
    58     static final String responses[] = {
    71     static final String responses[] = {
    59         "Lorem ipsum",
    72         "Lorem ipsum",
    60         "dolor sit amet",
    73         "dolor sit amet",
    66         "Duis aute irure dolor in reprehenderit in voluptate velit esse" +
    79         "Duis aute irure dolor in reprehenderit in voluptate velit esse" +
    67         "cillum dolore eu fugiat nulla pariatur.",
    80         "cillum dolore eu fugiat nulla pariatur.",
    68         "Excepteur sint occaecat cupidatat non proident."
    81         "Excepteur sint occaecat cupidatat non proident."
    69     };
    82     };
    70 
    83 
       
    84     final ServerSocketFactory factory;
       
    85     final SSLContext context;
       
    86     final boolean useSSL;
       
    87     SplitResponse(boolean useSSL) throws IOException {
       
    88         this.useSSL = useSSL;
       
    89         context = new SimpleSSLContext().get();
       
    90         SSLContext.setDefault(context);
       
    91         factory = useSSL ? SSLServerSocketFactory.getDefault()
       
    92                          : ServerSocketFactory.getDefault();
       
    93     }
       
    94 
       
    95     public HttpClient newHttpClient() {
       
    96         HttpClient client;
       
    97         if (useSSL) {
       
    98             client = HttpClient.newBuilder()
       
    99                                .sslContext(context)
       
   100                                .build();
       
   101         } else {
       
   102             client = HttpClient.newHttpClient();
       
   103         }
       
   104         return client;
       
   105     }
       
   106 
    71     public static void main(String[] args) throws Exception {
   107     public static void main(String[] args) throws Exception {
    72         server = new Server(0);
   108         boolean useSSL = false;
       
   109         if (args != null && args.length == 1) {
       
   110             useSSL = "SSL".equals(args[0]);
       
   111         }
       
   112         SplitResponse sp = new SplitResponse(useSSL);
       
   113 
       
   114         for (Version version : Version.values()) {
       
   115             for (boolean serverKeepalive : new boolean[]{ true, false }) {
       
   116                 // Note: the mock server doesn't support Keep-Alive, but
       
   117                 // pretending that it might exercises code paths in and out of
       
   118                 // the connection pool, and retry logic
       
   119                 for (boolean async : new boolean[]{ true, false }) {
       
   120                     sp.test(version, serverKeepalive, async);
       
   121                 }
       
   122             }
       
   123         }
       
   124     }
       
   125 
       
   126     // @Test
       
   127     void test(Version version, boolean serverKeepalive, boolean async)
       
   128         throws Exception
       
   129     {
       
   130         out.println(format("*** version %s, serverKeepAlive: %s, async: %s ***",
       
   131                            version, serverKeepalive, async));
       
   132         MockServer server = new MockServer(0, factory);
    73         URI uri = new URI(server.getURL());
   133         URI uri = new URI(server.getURL());
       
   134         out.println("server is: " + uri);
    74         server.start();
   135         server.start();
    75 
   136 
    76         HttpClient client = HttpClient.newHttpClient();
   137         HttpClient client = newHttpClient();
    77         HttpRequest request = HttpRequest.newBuilder(uri).build();
   138         HttpRequest request = HttpRequest.newBuilder(uri).version(version).build();
    78         HttpResponse<String> r;
   139         HttpResponse<String> r;
    79         CompletableFuture<HttpResponse<String>> cf1;
   140         CompletableFuture<HttpResponse<String>> cf1;
    80 
   141 
    81         try {
   142         try {
    82             for (int i=0; i<responses.length; i++) {
   143             for (int i=0; i<responses.length; i++) {
    83                 cf1 = client.sendAsync(request, asString());
   144                 out.println("----- iteration " + i + " -----");
    84                 String body = responses[i];
   145                 String body = responses[i];
    85 
   146                 Thread t = sendSplitResponse(response(body, serverKeepalive), server);
    86                 Server.Connection c = server.activity();
   147 
    87                 sendSplitResponse(response(body), c);
   148                 if (async) {
    88                 r = cf1.get();
   149                     out.println("send async: " + request);
    89                 if (r.statusCode()!= 200)
   150                     cf1 = client.sendAsync(request, asString());
       
   151                     r = cf1.get();
       
   152                 } else { // sync
       
   153                     out.println("send sync: " + request);
       
   154                     r = client.send(request, asString());
       
   155                 }
       
   156 
       
   157                 if (r.statusCode() != 200)
    90                     throw new RuntimeException("Failed");
   158                     throw new RuntimeException("Failed");
    91 
   159 
    92                 String rxbody = r.body();
   160                 String rxbody = r.body();
    93                 System.out.println("received " + rxbody);
   161                 out.println("received " + rxbody);
    94                 if (!rxbody.equals(body))
   162                 if (!rxbody.equals(body))
    95                     throw new RuntimeException("Failed");
   163                     throw new RuntimeException(format("Expected:%s, got:%s", body, rxbody));
    96                 c.close();
   164 
       
   165                 t.join();
       
   166                 conn.close();
    97             }
   167             }
    98         } finally {
   168         } finally {
    99             Executor def = client.executor();
   169             server.close();
   100             if (def instanceof ExecutorService) {
       
   101                 ((ExecutorService)def).shutdownNow();
       
   102             }
       
   103         }
   170         }
   104         System.out.println("OK");
   171         System.out.println("OK");
   105     }
   172     }
   106 
   173 
   107     // send the response one byte at a time with a small delay between bytes
   174     // required for cleanup
   108     // to ensure that each byte is read in a separate read
   175     volatile MockServer.Connection conn;
   109     static void sendSplitResponse(String s, Server.Connection conn) {
   176 
       
   177     // Sends the response, mostly, one byte at a time with a small delay
       
   178     // between bytes, to encourage that each byte is read in a separate read
       
   179     Thread sendSplitResponse(String s, MockServer server) {
   110         System.out.println("Sending: ");
   180         System.out.println("Sending: ");
   111         Thread t = new Thread(() -> {
   181         Thread t = new Thread(() -> {
       
   182             System.out.println("Waiting for server to receive headers");
       
   183             conn = server.activity();
       
   184             System.out.println("Start sending response");
       
   185 
   112             try {
   186             try {
   113                 int len = s.length();
   187                 int len = s.length();
       
   188                 out.println("sending " + s);
   114                 for (int i = 0; i < len; i++) {
   189                 for (int i = 0; i < len; i++) {
   115                     String onechar = s.substring(i, i + 1);
   190                     String onechar = s.substring(i, i + 1);
   116                     conn.send(onechar);
   191                     conn.send(onechar);
   117                     Thread.sleep(30);
   192                     Thread.sleep(10);
   118                 }
   193                 }
   119                 System.out.println("sent");
   194                 out.println("sent " + s);
   120             } catch (IOException | InterruptedException e) {
   195             } catch (IOException | InterruptedException e) {
       
   196                 throw new RuntimeException(e);
   121             }
   197             }
   122         });
   198         });
   123         t.setDaemon(true);
   199         t.setDaemon(true);
   124         t.start();
   200         t.start();
       
   201         return t;
   125     }
   202     }
   126 }
   203 }