1 /* |
1 /* |
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
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. |
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. |
23 |
23 |
24 import java.io.IOException; |
24 import java.io.IOException; |
25 import java.io.InputStream; |
25 import java.io.InputStream; |
26 import java.io.OutputStream; |
26 import java.io.OutputStream; |
27 import java.io.UncheckedIOException; |
27 import java.io.UncheckedIOException; |
|
28 import java.net.InetAddress; |
|
29 import java.net.InetSocketAddress; |
28 import java.net.ServerSocket; |
30 import java.net.ServerSocket; |
29 import java.net.Socket; |
31 import java.net.Socket; |
30 import java.net.URI; |
32 import java.net.URI; |
|
33 import java.net.http.HttpClient; |
|
34 import java.net.http.HttpRequest; |
|
35 import java.net.http.HttpRequest.BodyPublishers; |
|
36 import java.net.http.HttpResponse; |
|
37 import java.net.http.HttpResponse.BodyHandlers; |
|
38 import java.net.http.HttpTimeoutException; |
31 import java.nio.file.Files; |
39 import java.nio.file.Files; |
32 import java.nio.file.Path; |
40 import java.nio.file.Path; |
33 import java.nio.file.Paths; |
41 import java.nio.file.Paths; |
34 import java.nio.ByteBuffer; |
42 import java.nio.ByteBuffer; |
35 import java.util.ArrayList; |
43 import java.util.ArrayList; |
38 import java.util.concurrent.ExecutionException; |
46 import java.util.concurrent.ExecutionException; |
39 import java.util.concurrent.Flow; |
47 import java.util.concurrent.Flow; |
40 import java.util.concurrent.TimeoutException; |
48 import java.util.concurrent.TimeoutException; |
41 import java.util.concurrent.TimeUnit; |
49 import java.util.concurrent.TimeUnit; |
42 import java.util.function.Supplier; |
50 import java.util.function.Supplier; |
43 import jdk.incubator.http.HttpClient; |
|
44 import jdk.incubator.http.HttpResponse; |
|
45 import jdk.incubator.http.HttpRequest; |
|
46 import jdk.incubator.http.HttpTimeoutException; |
|
47 |
|
48 import static java.lang.System.err; |
51 import static java.lang.System.err; |
49 import static java.nio.charset.StandardCharsets.US_ASCII; |
52 import static java.nio.charset.StandardCharsets.US_ASCII; |
50 import static jdk.incubator.http.HttpResponse.BodyHandler.discard; |
|
51 import static java.nio.charset.StandardCharsets.UTF_8; |
53 import static java.nio.charset.StandardCharsets.UTF_8; |
52 |
54 |
53 /** |
55 /** |
54 * @test |
56 * @test |
55 * @bug 8151441 |
57 * @bug 8151441 |
100 // Request body Publishers that may generate a different number of actual |
102 // Request body Publishers that may generate a different number of actual |
101 // bytes to that of what is reported through their {@code contentLength}. |
103 // bytes to that of what is reported through their {@code contentLength}. |
102 |
104 |
103 static class StringRequestBody extends AbstractDelegateRequestBody { |
105 static class StringRequestBody extends AbstractDelegateRequestBody { |
104 StringRequestBody(String body, int additionalLength) { |
106 StringRequestBody(String body, int additionalLength) { |
105 super(HttpRequest.BodyPublisher.fromString(body), |
107 super(HttpRequest.BodyPublishers.ofString(body), |
106 body.getBytes(UTF_8).length + additionalLength); |
108 body.getBytes(UTF_8).length + additionalLength); |
107 } |
109 } |
108 } |
110 } |
109 |
111 |
110 static class ByteArrayRequestBody extends AbstractDelegateRequestBody { |
112 static class ByteArrayRequestBody extends AbstractDelegateRequestBody { |
111 ByteArrayRequestBody(byte[] body, int additionalLength) { |
113 ByteArrayRequestBody(byte[] body, int additionalLength) { |
112 super(HttpRequest.BodyPublisher.fromByteArray(body), |
114 super(BodyPublishers.ofByteArray(body), |
113 body.length + additionalLength); |
115 body.length + additionalLength); |
114 } |
116 } |
115 } |
117 } |
116 |
118 |
117 static class FileRequestBody extends AbstractDelegateRequestBody { |
119 static class FileRequestBody extends AbstractDelegateRequestBody { |
118 FileRequestBody(Path path, int additionalLength) throws IOException { |
120 FileRequestBody(Path path, int additionalLength) throws IOException { |
119 super(HttpRequest.BodyPublisher.fromFile(path), |
121 super(BodyPublishers.ofFile(path), |
120 Files.size(path) + additionalLength); |
122 Files.size(path) + additionalLength); |
121 } |
123 } |
122 } |
124 } |
123 |
125 |
124 // --- |
126 // --- |
130 clientSuppliers.add(() -> sharedClient); |
132 clientSuppliers.add(() -> sharedClient); |
131 |
133 |
132 try (Server server = new Server()) { |
134 try (Server server = new Server()) { |
133 for (Supplier<HttpClient> cs : clientSuppliers) { |
135 for (Supplier<HttpClient> cs : clientSuppliers) { |
134 err.println("\n---- next supplier ----\n"); |
136 err.println("\n---- next supplier ----\n"); |
135 URI uri = new URI("http://127.0.0.1:" + server.getPort() + "/"); |
137 URI uri = new URI("http://localhost:" + server.getPort() + "/"); |
136 |
138 |
137 // sanity ( 6 requests to keep client and server offsets easy to workout ) |
139 // sanity ( 6 requests to keep client and server offsets easy to workout ) |
138 success(cs, uri, new StringRequestBody(STRING_BODY, 0)); |
140 success(cs, uri, new StringRequestBody(STRING_BODY, 0)); |
139 success(cs, uri, new ByteArrayRequestBody(BYTE_ARRAY_BODY, 0)); |
141 success(cs, uri, new ByteArrayRequestBody(BYTE_ARRAY_BODY, 0)); |
140 success(cs, uri, new FileRequestBody(FILE_BODY, 0)); |
142 success(cs, uri, new FileRequestBody(FILE_BODY, 0)); |
162 { |
164 { |
163 CompletableFuture<HttpResponse<Void>> cf; |
165 CompletableFuture<HttpResponse<Void>> cf; |
164 HttpRequest request = HttpRequest.newBuilder(uri) |
166 HttpRequest request = HttpRequest.newBuilder(uri) |
165 .POST(publisher) |
167 .POST(publisher) |
166 .build(); |
168 .build(); |
167 cf = clientSupplier.get().sendAsync(request, discard(null)); |
169 cf = clientSupplier.get().sendAsync(request, BodyHandlers.discarding()); |
168 |
170 |
169 HttpResponse<Void> resp = cf.get(30, TimeUnit.SECONDS); |
171 HttpResponse<Void> resp = cf.get(30, TimeUnit.SECONDS); |
170 err.println("Response code: " + resp.statusCode()); |
172 err.println("Response code: " + resp.statusCode()); |
171 check(resp.statusCode() == 200, "Expected 200, got ", resp.statusCode()); |
173 check(resp.statusCode() == 200, null, |
|
174 "Expected 200, got ", resp.statusCode()); |
172 } |
175 } |
173 |
176 |
174 static void failureNonBlocking(Supplier<HttpClient> clientSupplier, |
177 static void failureNonBlocking(Supplier<HttpClient> clientSupplier, |
175 URI uri, |
178 URI uri, |
176 HttpRequest.BodyPublisher publisher) |
179 HttpRequest.BodyPublisher publisher) |
178 { |
181 { |
179 CompletableFuture<HttpResponse<Void>> cf; |
182 CompletableFuture<HttpResponse<Void>> cf; |
180 HttpRequest request = HttpRequest.newBuilder(uri) |
183 HttpRequest request = HttpRequest.newBuilder(uri) |
181 .POST(publisher) |
184 .POST(publisher) |
182 .build(); |
185 .build(); |
183 cf = clientSupplier.get().sendAsync(request, discard(null)); |
186 cf = clientSupplier.get().sendAsync(request, BodyHandlers.discarding()); |
184 |
187 |
185 try { |
188 try { |
186 HttpResponse<Void> r = cf.get(30, TimeUnit.SECONDS); |
189 HttpResponse<Void> r = cf.get(30, TimeUnit.SECONDS); |
187 throw new RuntimeException("Unexpected response: " + r.statusCode()); |
190 throw new RuntimeException("Unexpected response: " + r.statusCode()); |
188 } catch (TimeoutException x) { |
191 } catch (TimeoutException x) { |
189 throw new RuntimeException("Unexpected timeout", x); |
192 throw new RuntimeException("Unexpected timeout", x); |
190 } catch (ExecutionException expected) { |
193 } catch (ExecutionException expected) { |
191 err.println("Caught expected: " + expected); |
194 err.println("Caught expected: " + expected); |
192 Throwable t = expected.getCause(); |
195 Throwable t = expected.getCause(); |
193 check(t instanceof IOException, |
196 check(t instanceof IOException, t, |
194 "Expected cause IOException, but got: ", expected.getCause()); |
197 "Expected cause IOException, but got: ", t); |
195 String msg = t.getMessage(); |
198 String msg = t.getMessage(); |
196 check(msg.contains("Too many") || msg.contains("Too few"), |
199 check(msg.contains("Too many") || msg.contains("Too few"), |
197 "Expected Too many|Too few, got: ", t); |
200 t, "Expected Too many|Too few, got: ", t); |
198 } |
201 } |
199 } |
202 } |
200 |
203 |
201 static void failureBlocking(Supplier<HttpClient> clientSupplier, |
204 static void failureBlocking(Supplier<HttpClient> clientSupplier, |
202 URI uri, |
205 URI uri, |
205 { |
208 { |
206 HttpRequest request = HttpRequest.newBuilder(uri) |
209 HttpRequest request = HttpRequest.newBuilder(uri) |
207 .POST(publisher) |
210 .POST(publisher) |
208 .build(); |
211 .build(); |
209 try { |
212 try { |
210 HttpResponse<Void> r = clientSupplier.get().send(request, discard(null)); |
213 HttpResponse<Void> r = clientSupplier.get() |
|
214 .send(request, BodyHandlers.discarding()); |
211 throw new RuntimeException("Unexpected response: " + r.statusCode()); |
215 throw new RuntimeException("Unexpected response: " + r.statusCode()); |
212 } catch (HttpTimeoutException x) { |
216 } catch (HttpTimeoutException x) { |
213 throw new RuntimeException("Unexpected timeout", x); |
217 throw new RuntimeException("Unexpected timeout", x); |
214 } catch (IOException expected) { |
218 } catch (IOException expected) { |
215 err.println("Caught expected: " + expected); |
219 err.println("Caught expected: " + expected); |
216 String msg = expected.getMessage(); |
220 String msg = expected.getMessage(); |
217 check(msg.contains("Too many") || msg.contains("Too few"), |
221 check(msg.contains("Too many") || msg.contains("Too few"), |
218 "Expected Too many|Too few, got: ", expected); |
222 expected,"Expected Too many|Too few, got: ", expected); |
219 } |
223 } |
220 } |
224 } |
221 |
225 |
222 static class Server extends Thread implements AutoCloseable { |
226 static class Server extends Thread implements AutoCloseable { |
223 |
227 |
228 private final ServerSocket ss; |
232 private final ServerSocket ss; |
229 private volatile boolean closed; |
233 private volatile boolean closed; |
230 |
234 |
231 Server() throws IOException { |
235 Server() throws IOException { |
232 super("Test-Server"); |
236 super("Test-Server"); |
233 ss = new ServerSocket(0); this.start(); |
237 ss = new ServerSocket(); |
|
238 ss.setReuseAddress(false); |
|
239 ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); |
|
240 this.start(); |
234 } |
241 } |
235 |
242 |
236 int getPort() { return ss.getLocalPort(); } |
243 int getPort() { return ss.getLocalPort(); } |
237 |
244 |
238 @Override |
245 @Override |
316 static int fileSize(Path p) { |
323 static int fileSize(Path p) { |
317 try { return (int) Files.size(p); } |
324 try { return (int) Files.size(p); } |
318 catch (IOException x) { throw new UncheckedIOException(x); } |
325 catch (IOException x) { throw new UncheckedIOException(x); } |
319 } |
326 } |
320 |
327 |
321 static boolean check(boolean cond, Object... failedArgs) { |
328 static boolean check(boolean cond, Throwable t, Object... failedArgs) { |
322 if (cond) |
329 if (cond) |
323 return true; |
330 return true; |
324 // We are going to fail... |
331 // We are going to fail... |
325 StringBuilder sb = new StringBuilder(); |
332 StringBuilder sb = new StringBuilder(); |
326 for (Object o : failedArgs) |
333 for (Object o : failedArgs) |
327 sb.append(o); |
334 sb.append(o); |
328 throw new RuntimeException(sb.toString()); |
335 throw new RuntimeException(sb.toString(), t); |
329 } |
336 } |
330 } |
337 } |