1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  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
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8087112 8177935
  27  * @library /lib/testlibrary server
  28  * @build jdk.testlibrary.SimpleSSLContext
  29  * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.common
  30  *          jdk.incubator.httpclient/jdk.incubator.http.internal.frame
  31  *          jdk.incubator.httpclient/jdk.incubator.http.internal.hpack
  32  * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors FixedThreadPoolTest
  33  */
  34 
  35 import java.net.*;
  36 import jdk.incubator.http.*;
  37 import static jdk.incubator.http.HttpClient.Version.HTTP_2;
  38 import javax.net.ssl.*;
  39 import java.nio.file.*;
  40 import java.util.concurrent.*;
  41 import jdk.testlibrary.SimpleSSLContext;
  42 import static jdk.incubator.http.HttpRequest.BodyProcessor.fromFile;
  43 import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString;
  44 import static jdk.incubator.http.HttpResponse.BodyHandler.asFile;
  45 import static jdk.incubator.http.HttpResponse.BodyHandler.asString;
  46 
  47 import org.testng.annotations.Test;
  48 
  49 @Test
  50 public class FixedThreadPoolTest {
  51     static int httpPort, httpsPort;
  52     static Http2TestServer httpServer, httpsServer;
  53     static HttpClient client = null;
  54     static ExecutorService exec;
  55     static SSLContext sslContext;
  56 
  57     static String httpURIString, httpsURIString;
  58 
  59     static void initialize() throws Exception {
  60         try {
  61             SimpleSSLContext sslct = new SimpleSSLContext();
  62             sslContext = sslct.get();
  63             client = getClient();
  64             httpServer = new Http2TestServer(false, 0, exec, sslContext);
  65             httpServer.addHandler(new Http2EchoHandler(), "/");
  66             httpPort = httpServer.getAddress().getPort();
  67 
  68             httpsServer = new Http2TestServer(true, 0, exec, sslContext);
  69             httpsServer.addHandler(new Http2EchoHandler(), "/");
  70 
  71             httpsPort = httpsServer.getAddress().getPort();
  72             httpURIString = "http://127.0.0.1:" + httpPort + "/foo/";
  73             httpsURIString = "https://127.0.0.1:" + httpsPort + "/bar/";
  74 
  75             httpServer.start();
  76             httpsServer.start();
  77         } catch (Throwable e) {
  78             System.err.println("Throwing now");
  79             e.printStackTrace();
  80             throw e;
  81         }
  82     }
  83 
  84     @Test(timeOut=3000000)
  85     public static void test() throws Exception {
  86         try {
  87             initialize();
  88             simpleTest(false);
  89             simpleTest(true);
  90             streamTest(false);
  91             streamTest(true);
  92             paramsTest();
  93             Thread.sleep(1000 * 4);
  94         } catch (Exception | Error tt) {
  95             tt.printStackTrace();
  96             throw tt;
  97         } finally {
  98             httpServer.stop();
  99             httpsServer.stop();
 100             exec.shutdownNow();
 101         }
 102     }
 103 
 104     static HttpClient getClient() {
 105         if (client == null) {
 106             exec = Executors.newCachedThreadPool();
 107             client = HttpClient.newBuilder()
 108                                .executor(Executors.newFixedThreadPool(2))
 109                                .sslContext(sslContext)
 110                                .version(HTTP_2)
 111                                .build();
 112         }
 113         return client;
 114     }
 115 
 116     static URI getURI(boolean secure) {
 117         if (secure)
 118             return URI.create(httpsURIString);
 119         else
 120             return URI.create(httpURIString);
 121     }
 122 
 123     static void checkStatus(int expected, int found) throws Exception {
 124         if (expected != found) {
 125             System.err.printf ("Test failed: wrong status code %d/%d\n",
 126                 expected, found);
 127             throw new RuntimeException("Test failed");
 128         }
 129     }
 130 
 131     static void checkStrings(String expected, String found) throws Exception {
 132         if (!expected.equals(found)) {
 133             System.err.printf ("Test failed: wrong string %s/%s\n",
 134                 expected, found);
 135             throw new RuntimeException("Test failed");
 136         }
 137     }
 138 
 139     static Void compareFiles(Path path1, Path path2) {
 140         return TestUtil.compareFiles(path1, path2);
 141     }
 142 
 143     static Path tempFile() {
 144         return TestUtil.tempFile();
 145     }
 146 
 147     static final String SIMPLE_STRING = "Hello world Goodbye world";
 148 
 149     static final int LOOPS = 32;
 150     static final int FILESIZE = 64 * 1024 + 200;
 151 
 152     static void streamTest(boolean secure) throws Exception {
 153         URI uri = getURI(secure);
 154         System.err.printf("streamTest %b to %s\n" , secure, uri);
 155 
 156         HttpClient client = getClient();
 157         Path src = TestUtil.getAFile(FILESIZE * 4);
 158         HttpRequest req = HttpRequest.newBuilder(uri)
 159                                      .POST(fromFile(src))
 160                                      .build();
 161 
 162         Path dest = Paths.get("streamtest.txt");
 163         dest.toFile().delete();
 164         CompletableFuture<Path> response = client.sendAsync(req, asFile(dest))
 165                 .thenApply(resp -> {
 166                     if (resp.statusCode() != 200)
 167                         throw new RuntimeException();
 168                     return resp.body();
 169                 });
 170         response.join();
 171         compareFiles(src, dest);
 172         System.err.println("DONE");
 173     }
 174 
 175     static void paramsTest() throws Exception {
 176         System.err.println("paramsTest");
 177         Http2TestServer server = new Http2TestServer(true, 0, exec, sslContext);
 178         server.addHandler((t -> {
 179             SSLSession s = t.getSSLSession();
 180             String prot = s.getProtocol();
 181             if (prot.equals("TLSv1.2")) {
 182                 t.sendResponseHeaders(200, -1);
 183             } else {
 184                 System.err.printf("Protocols =%s\n", prot);
 185                 t.sendResponseHeaders(500, -1);
 186             }
 187         }), "/");
 188         server.start();
 189         int port = server.getAddress().getPort();
 190         URI u = new URI("https://127.0.0.1:"+port+"/foo");
 191         HttpClient client = getClient();
 192         HttpRequest req = HttpRequest.newBuilder(u).build();
 193         HttpResponse<String> resp = client.sendAsync(req, asString()).get();
 194         int stat = resp.statusCode();
 195         if (stat != 200) {
 196             throw new RuntimeException("paramsTest failed "
 197                 + Integer.toString(stat));
 198         }
 199     }
 200 
 201     static void simpleTest(boolean secure) throws Exception {
 202         URI uri = getURI(secure);
 203         System.err.println("Request to " + uri);
 204 
 205         // Do a simple warmup request
 206 
 207         HttpClient client = getClient();
 208         HttpRequest req = HttpRequest.newBuilder(uri)
 209                                      .POST(fromString(SIMPLE_STRING))
 210                                      .build();
 211         HttpResponse<String> response = client.sendAsync(req, asString()).get();
 212         HttpHeaders h = response.headers();
 213 
 214         checkStatus(200, response.statusCode());
 215 
 216         String responseBody = response.body();
 217         checkStrings(SIMPLE_STRING, responseBody);
 218 
 219         checkStrings(h.firstValue("x-hello").get(), "world");
 220         checkStrings(h.firstValue("x-bye").get(), "universe");
 221 
 222         // Do loops asynchronously
 223 
 224         CompletableFuture[] responses = new CompletableFuture[LOOPS];
 225         final Path source = TestUtil.getAFile(FILESIZE);
 226         HttpRequest request = HttpRequest.newBuilder(uri)
 227                                          .POST(fromFile(source))
 228                                          .build();
 229         for (int i = 0; i < LOOPS; i++) {
 230             responses[i] = client.sendAsync(request, asFile(tempFile()))
 231                 //.thenApply(resp -> compareFiles(resp.body(), source));
 232                 .thenApply(resp -> {
 233                     System.out.printf("Resp status %d body size %d\n",
 234                                       resp.statusCode(), resp.body().toFile().length());
 235                     return compareFiles(resp.body(), source);
 236                 });
 237         }
 238         CompletableFuture.allOf(responses).join();
 239         System.err.println("DONE");
 240     }
 241 }