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