1 /*
2  * Copyright (c) 2015, 2018, 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 java.base/sun.net.www.http
30  *          java.net.http/jdk.internal.net.http.common
31  *          java.net.http/jdk.internal.net.http.frame
32  *          java.net.http/jdk.internal.net.http.hpack
33  * @run testng/othervm -Djdk.httpclient.HttpClient.log=ssl,requests,responses,errors FixedThreadPoolTest
34  */
35 
36 import java.net.*;
37 import java.net.http.*;
38 import java.net.http.HttpRequest.BodyPublishers;
39 import java.net.http.HttpResponse.BodyHandlers;
40 import javax.net.ssl.*;
41 import java.nio.file.*;
42 import java.util.concurrent.*;
43 import jdk.testlibrary.SimpleSSLContext;
44 import static java.net.http.HttpClient.Version.HTTP_2;
45 import org.testng.annotations.Test;
46 
47 @Test
48 public class FixedThreadPoolTest {
49     static int httpPort, httpsPort;
50     static Http2TestServer httpServer, httpsServer;
51     static HttpClient client = null;
52     static ExecutorService exec;
53     static SSLContext sslContext;
54 
55     static String httpURIString, httpsURIString;
56 
initialize()57     static void initialize() throws Exception {
58         try {
59             SimpleSSLContext sslct = new SimpleSSLContext();
60             sslContext = sslct.get();
61             client = getClient();
62             httpServer = new Http2TestServer(false, 0, exec, sslContext);
63             httpServer.addHandler(new Http2EchoHandler(), "/");
64             httpPort = httpServer.getAddress().getPort();
65 
66             httpsServer = new Http2TestServer(true, 0, exec, sslContext);
67             httpsServer.addHandler(new Http2EchoHandler(), "/");
68 
69             httpsPort = httpsServer.getAddress().getPort();
70             httpURIString = "http://localhost:" + httpPort + "/foo/";
71             httpsURIString = "https://localhost:" + httpsPort + "/bar/";
72 
73             httpServer.start();
74             httpsServer.start();
75         } catch (Throwable e) {
76             System.err.println("Throwing now");
77             e.printStackTrace();
78             throw e;
79         }
80     }
81 
82     @Test
test()83     public static void test() throws Exception {
84         try {
85             initialize();
86             simpleTest(false);
87             simpleTest(true);
88             streamTest(false);
89             streamTest(true);
90             paramsTest();
91             Thread.sleep(1000 * 4);
92         } catch (Exception | Error tt) {
93             tt.printStackTrace();
94             throw tt;
95         } finally {
96             httpServer.stop();
97             httpsServer.stop();
98             exec.shutdownNow();
99         }
100     }
101 
getClient()102     static HttpClient getClient() {
103         if (client == null) {
104             exec = Executors.newCachedThreadPool();
105             // Executor e1 = Executors.newFixedThreadPool(1);
106             // Executor e = (Runnable r) -> e1.execute(() -> {
107             //    System.out.println("[" + Thread.currentThread().getName()
108             //                       + "] Executing: "
109             //                       + r.getClass().getName());
110             //    r.run();
111             // });
112             client = HttpClient.newBuilder()
113                                .executor(Executors.newFixedThreadPool(2))
114                                .sslContext(sslContext)
115                                .version(HTTP_2)
116                                .build();
117         }
118         return client;
119     }
120 
getURI(boolean secure)121     static URI getURI(boolean secure) {
122         if (secure)
123             return URI.create(httpsURIString);
124         else
125             return URI.create(httpURIString);
126     }
127 
checkStatus(int expected, int found)128     static void checkStatus(int expected, int found) throws Exception {
129         if (expected != found) {
130             System.err.printf ("Test failed: wrong status code %d/%d\n",
131                 expected, found);
132             throw new RuntimeException("Test failed");
133         }
134     }
135 
checkStrings(String expected, String found)136     static void checkStrings(String expected, String found) throws Exception {
137         if (!expected.equals(found)) {
138             System.err.printf ("Test failed: wrong string %s/%s\n",
139                 expected, found);
140             throw new RuntimeException("Test failed");
141         }
142     }
143 
compareFiles(Path path1, Path path2)144     static Void compareFiles(Path path1, Path path2) {
145         return TestUtil.compareFiles(path1, path2);
146     }
147 
tempFile()148     static Path tempFile() {
149         return TestUtil.tempFile();
150     }
151 
152     static final String SIMPLE_STRING = "Hello world Goodbye world";
153 
154     static final int LOOPS = 32;
155     static final int FILESIZE = 64 * 1024 + 200;
156 
streamTest(boolean secure)157     static void streamTest(boolean secure) throws Exception {
158         URI uri = getURI(secure);
159         System.err.printf("streamTest %b to %s\n" , secure, uri);
160 
161         HttpClient client = getClient();
162         Path src = TestUtil.getAFile(FILESIZE * 4);
163         HttpRequest req = HttpRequest.newBuilder(uri)
164                                      .POST(BodyPublishers.ofFile(src))
165                                      .build();
166 
167         Path dest = Paths.get("streamtest.txt");
168         dest.toFile().delete();
169         CompletableFuture<Path> response = client.sendAsync(req, BodyHandlers.ofFile(dest))
170                 .thenApply(resp -> {
171                     if (resp.statusCode() != 200)
172                         throw new RuntimeException();
173                     return resp.body();
174                 });
175         response.join();
176         compareFiles(src, dest);
177         System.err.println("DONE");
178     }
179 
180     // expect highest supported version we know about
expectedTLSVersion(SSLContext ctx)181     static String expectedTLSVersion(SSLContext ctx) {
182         SSLParameters params = ctx.getSupportedSSLParameters();
183         String[] protocols = params.getProtocols();
184         for (String prot : protocols) {
185             if (prot.equals("TLSv1.3"))
186                 return "TLSv1.3";
187         }
188         return "TLSv1.2";
189     }
190 
paramsTest()191     static void paramsTest() throws Exception {
192         System.err.println("paramsTest");
193         Http2TestServer server = new Http2TestServer(true, 0, exec, sslContext);
194         server.addHandler((t -> {
195             SSLSession s = t.getSSLSession();
196             String prot = s.getProtocol();
197             if (prot.equals(expectedTLSVersion(sslContext))) {
198                 t.sendResponseHeaders(200, -1);
199             } else {
200                 System.err.printf("Protocols =%s\n", prot);
201                 t.sendResponseHeaders(500, -1);
202             }
203         }), "/");
204         server.start();
205         int port = server.getAddress().getPort();
206         URI u = new URI("https://localhost:"+port+"/foo");
207         HttpClient client = getClient();
208         HttpRequest req = HttpRequest.newBuilder(u).build();
209         HttpResponse<String> resp = client.sendAsync(req, BodyHandlers.ofString()).get();
210         int stat = resp.statusCode();
211         if (stat != 200) {
212             throw new RuntimeException("paramsTest failed "
213                 + Integer.toString(stat));
214         }
215     }
216 
simpleTest(boolean secure)217     static void simpleTest(boolean secure) throws Exception {
218         URI uri = getURI(secure);
219         System.err.println("Request to " + uri);
220 
221         // Do a simple warmup request
222 
223         HttpClient client = getClient();
224         HttpRequest req = HttpRequest.newBuilder(uri)
225                                      .POST(BodyPublishers.ofString(SIMPLE_STRING))
226                                      .build();
227         HttpResponse<String> response = client.sendAsync(req, BodyHandlers.ofString()).get();
228         HttpHeaders h = response.headers();
229 
230         checkStatus(200, response.statusCode());
231 
232         String responseBody = response.body();
233         checkStrings(SIMPLE_STRING, responseBody);
234 
235         checkStrings(h.firstValue("x-hello").get(), "world");
236         checkStrings(h.firstValue("x-bye").get(), "universe");
237 
238         // Do loops asynchronously
239 
240         CompletableFuture[] responses = new CompletableFuture[LOOPS];
241         final Path source = TestUtil.getAFile(FILESIZE);
242         HttpRequest request = HttpRequest.newBuilder(uri)
243                                          .POST(BodyPublishers.ofFile(source))
244                                          .build();
245         for (int i = 0; i < LOOPS; i++) {
246             responses[i] = client.sendAsync(request, BodyHandlers.ofFile(tempFile()))
247                 //.thenApply(resp -> compareFiles(resp.body(), source));
248                 .thenApply(resp -> {
249                     System.out.printf("Resp status %d body size %d\n",
250                                       resp.statusCode(), resp.body().toFile().length());
251                     return compareFiles(resp.body(), source);
252                 });
253         }
254         CompletableFuture.allOf(responses).join();
255         System.err.println("DONE");
256     }
257 }
258