|
1 /* |
|
2 * Copyright (c) 2019, 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 8221481 |
|
27 * @compile/module=java.base java/net/PlatformSocketImpl.java |
|
28 * @run testng/othervm BadUsages |
|
29 * @summary Test the platform SocketImpl when used in unintended ways |
|
30 */ |
|
31 |
|
32 import java.io.IOException; |
|
33 import java.io.InputStream; |
|
34 import java.io.OutputStream; |
|
35 import java.net.InetAddress; |
|
36 import java.net.InetSocketAddress; |
|
37 import java.net.ServerSocket; |
|
38 import java.net.SocketAddress; |
|
39 import java.net.SocketException; |
|
40 import java.net.SocketImpl; |
|
41 import java.net.SocketOption; |
|
42 import java.net.SocketOptions; |
|
43 import java.net.StandardSocketOptions; |
|
44 import java.util.Set; |
|
45 |
|
46 import java.net.PlatformSocketImpl; // test helper |
|
47 |
|
48 import org.testng.annotations.Test; |
|
49 import static org.testng.Assert.*; |
|
50 |
|
51 /** |
|
52 * SocketImpl does not specify how the SocketImpl behaves when used in ways |
|
53 * that are not intended, e.g. invoking socket operations before the socket is |
|
54 * created or trying to establish a connection after the socket is connected or |
|
55 * closed. |
|
56 * |
|
57 * This test exercises the platform SocketImpl to test that it is reliable, and |
|
58 * throws reasonable exceptions, for these scenarios. |
|
59 */ |
|
60 |
|
61 @Test |
|
62 public class BadUsages { |
|
63 |
|
64 /** |
|
65 * Test create when already created. |
|
66 */ |
|
67 public void testCreate1() throws IOException { |
|
68 try (var impl = new PlatformSocketImpl(false)) { |
|
69 impl.create(true); |
|
70 expectThrows(IOException.class, () -> impl.create(true)); |
|
71 } |
|
72 } |
|
73 |
|
74 /** |
|
75 * Test create when closed. |
|
76 */ |
|
77 public void testCreate2() throws IOException { |
|
78 var impl = new PlatformSocketImpl(false); |
|
79 impl.close(); |
|
80 expectThrows(IOException.class, () -> impl.create(true)); |
|
81 } |
|
82 |
|
83 /** |
|
84 * Test connect when not created. |
|
85 */ |
|
86 public void testConnect1() throws IOException { |
|
87 try (var ss = new ServerSocket(0)) { |
|
88 var impl = new PlatformSocketImpl(false); |
|
89 var address = ss.getInetAddress(); |
|
90 int port = ss.getLocalPort(); |
|
91 expectThrows(IOException.class, () -> impl.connect(address, port)); |
|
92 } |
|
93 } |
|
94 |
|
95 /** |
|
96 * Test connect with unsupported address type. |
|
97 */ |
|
98 public void testConnect2() throws IOException { |
|
99 try (var impl = new PlatformSocketImpl(false)) { |
|
100 impl.create(true); |
|
101 var remote = new SocketAddress() { }; |
|
102 expectThrows(IOException.class, () -> impl.connect(remote, 0)); |
|
103 } |
|
104 } |
|
105 |
|
106 /** |
|
107 * Test connect with an unresolved address. |
|
108 */ |
|
109 public void testConnect3() throws IOException { |
|
110 try (var impl = new PlatformSocketImpl(false)) { |
|
111 impl.create(true); |
|
112 var remote = new InetSocketAddress("blah-blah.blah-blah", 80); |
|
113 expectThrows(IOException.class, () -> impl.connect(remote, 0)); |
|
114 } |
|
115 } |
|
116 |
|
117 /** |
|
118 * Test connect when already connected. |
|
119 */ |
|
120 public void testConnect4() throws IOException { |
|
121 try (var ss = new ServerSocket(); |
|
122 var impl = new PlatformSocketImpl(false)) { |
|
123 var loopback = InetAddress.getLoopbackAddress(); |
|
124 ss.bind(new InetSocketAddress(loopback, 0)); |
|
125 impl.create(true); |
|
126 int port = ss.getLocalPort(); |
|
127 impl.connect(loopback, port); |
|
128 expectThrows(IOException.class, () -> impl.connect(loopback, port)); |
|
129 } |
|
130 } |
|
131 |
|
132 /** |
|
133 * Test connect when closed. |
|
134 */ |
|
135 public void testConnect5() throws IOException { |
|
136 try (var ss = new ServerSocket(0)) { |
|
137 var impl = new PlatformSocketImpl(false); |
|
138 impl.close(); |
|
139 String host = ss.getInetAddress().getHostAddress(); |
|
140 int port = ss.getLocalPort(); |
|
141 expectThrows(IOException.class, () -> impl.connect(host, port)); |
|
142 } |
|
143 } |
|
144 |
|
145 /** |
|
146 * Test bind when not created. |
|
147 */ |
|
148 public void testBind1() throws IOException { |
|
149 var impl = new PlatformSocketImpl(false); |
|
150 var loopback = InetAddress.getLoopbackAddress(); |
|
151 expectThrows(IOException.class, () -> impl.bind(loopback, 0)); |
|
152 } |
|
153 |
|
154 /** |
|
155 * Test bind when already bound. |
|
156 */ |
|
157 public void testBind2() throws IOException { |
|
158 try (var impl = new PlatformSocketImpl(false)) { |
|
159 impl.create(true); |
|
160 var loopback = InetAddress.getLoopbackAddress(); |
|
161 impl.bind(loopback, 0); |
|
162 expectThrows(IOException.class, () -> impl.bind(loopback, 0)); |
|
163 } |
|
164 } |
|
165 |
|
166 /** |
|
167 * Test bind when connected. |
|
168 */ |
|
169 public void testBind3() throws IOException { |
|
170 try (var ss = new ServerSocket(); |
|
171 var impl = new PlatformSocketImpl(false)) { |
|
172 var loopback = InetAddress.getLoopbackAddress(); |
|
173 ss.bind(new InetSocketAddress(loopback, 0)); |
|
174 impl.create(true); |
|
175 impl.connect(ss.getLocalSocketAddress(), 0); |
|
176 expectThrows(IOException.class, () -> impl.bind(loopback, 0)); |
|
177 } |
|
178 } |
|
179 |
|
180 /** |
|
181 * Test bind when closed. |
|
182 */ |
|
183 public void testBind4() throws IOException { |
|
184 var impl = new PlatformSocketImpl(false); |
|
185 impl.close(); |
|
186 var loopback = InetAddress.getLoopbackAddress(); |
|
187 expectThrows(IOException.class, () -> impl.bind(loopback, 0)); |
|
188 } |
|
189 |
|
190 |
|
191 /** |
|
192 * Test listen when not created. |
|
193 */ |
|
194 public void testListen1() { |
|
195 var impl = new PlatformSocketImpl(false); |
|
196 expectThrows(IOException.class, () -> impl.listen(16)); |
|
197 } |
|
198 |
|
199 /** |
|
200 * Test listen when not bound. |
|
201 */ |
|
202 public void testListen2() throws IOException { |
|
203 try (var impl = new PlatformSocketImpl(false)) { |
|
204 impl.create(true); |
|
205 expectThrows(IOException.class, () -> impl.listen(16)); |
|
206 } |
|
207 } |
|
208 |
|
209 /** |
|
210 * Test listen when closed. |
|
211 */ |
|
212 public void testListen3() throws IOException { |
|
213 var impl = new PlatformSocketImpl(false); |
|
214 impl.close(); |
|
215 expectThrows(IOException.class, () -> impl.listen(16)); |
|
216 } |
|
217 |
|
218 /** |
|
219 * Test accept when not created. |
|
220 */ |
|
221 public void testAccept1() throws IOException { |
|
222 var impl = new PlatformSocketImpl(true); |
|
223 var si = new PlatformSocketImpl(false); |
|
224 expectThrows(IOException.class, () -> impl.accept(si)); |
|
225 } |
|
226 |
|
227 /** |
|
228 * Test accept when not bound. |
|
229 */ |
|
230 public void testAccept2() throws IOException { |
|
231 try (var impl = new PlatformSocketImpl(true)) { |
|
232 impl.create(true); |
|
233 var si = new PlatformSocketImpl(false); |
|
234 expectThrows(IOException.class, () -> impl.accept(si)); |
|
235 } |
|
236 } |
|
237 |
|
238 /** |
|
239 * Test accept when not a stream socket. |
|
240 */ |
|
241 public void testAccept3() throws IOException { |
|
242 try (var impl = new PlatformSocketImpl(false)) { |
|
243 impl.create(false); |
|
244 impl.bind(InetAddress.getLoopbackAddress(), 0); |
|
245 var si = new PlatformSocketImpl(false); |
|
246 expectThrows(IOException.class, () -> impl.accept(si)); |
|
247 } |
|
248 } |
|
249 |
|
250 /** |
|
251 * Test accept when closed. |
|
252 */ |
|
253 public void testAccept4() throws IOException { |
|
254 var impl = new PlatformSocketImpl(true); |
|
255 impl.close(); |
|
256 var si = new PlatformSocketImpl(false); |
|
257 expectThrows(IOException.class, () -> impl.accept(si)); |
|
258 } |
|
259 |
|
260 /** |
|
261 * Test accept with SocketImpl that is already created. |
|
262 */ |
|
263 public void testAccept5() throws IOException { |
|
264 try (var impl = new PlatformSocketImpl(true); |
|
265 var si = new PlatformSocketImpl(false)) { |
|
266 impl.create(true); |
|
267 impl.bind(InetAddress.getLoopbackAddress(), 0); |
|
268 si.create(true); |
|
269 expectThrows(IOException.class, () -> impl.accept(si)); |
|
270 } |
|
271 } |
|
272 |
|
273 /** |
|
274 * Test accept with SocketImpl that is closed. |
|
275 */ |
|
276 public void testAccept6() throws IOException { |
|
277 try (var impl = new PlatformSocketImpl(true); |
|
278 var si = new PlatformSocketImpl(false)) { |
|
279 impl.create(true); |
|
280 impl.bind(InetAddress.getLoopbackAddress(), 0); |
|
281 si.create(true); |
|
282 si.close(); |
|
283 expectThrows(IOException.class, () -> impl.accept(si)); |
|
284 } |
|
285 } |
|
286 |
|
287 /** |
|
288 * Test available when not created. |
|
289 */ |
|
290 public void testAvailable1() throws IOException { |
|
291 var impl = new PlatformSocketImpl(false); |
|
292 expectThrows(IOException.class, () -> impl.available()); |
|
293 } |
|
294 |
|
295 /** |
|
296 * Test available when created but not connected. |
|
297 */ |
|
298 public void testAvailable2() throws IOException { |
|
299 try (var impl = new PlatformSocketImpl(false)) { |
|
300 impl.create(true); |
|
301 expectThrows(IOException.class, () -> impl.available()); |
|
302 } |
|
303 } |
|
304 |
|
305 /** |
|
306 * Test available when closed. |
|
307 */ |
|
308 public void testAvailable3() throws IOException { |
|
309 var impl = new PlatformSocketImpl(false); |
|
310 impl.close(); |
|
311 expectThrows(IOException.class, () -> impl.available()); |
|
312 } |
|
313 |
|
314 /** |
|
315 * Test setOption when not created. |
|
316 */ |
|
317 public void testSetOption1() throws IOException { |
|
318 var impl = new PlatformSocketImpl(false); |
|
319 expectThrows(IOException.class, |
|
320 () -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true)); |
|
321 // legacy |
|
322 expectThrows(SocketException.class, |
|
323 () -> impl.setOption(SocketOptions.SO_REUSEADDR, true)); |
|
324 } |
|
325 |
|
326 /** |
|
327 * Test setOption when closed. |
|
328 */ |
|
329 public void testSetOption2() throws IOException { |
|
330 var impl = new PlatformSocketImpl(false); |
|
331 impl.close(); |
|
332 expectThrows(IOException.class, |
|
333 () -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true)); |
|
334 // legacy |
|
335 expectThrows(SocketException.class, |
|
336 () -> impl.setOption(SocketOptions.SO_REUSEADDR, true)); |
|
337 } |
|
338 |
|
339 /** |
|
340 * Test setOption with unsupported option. |
|
341 */ |
|
342 public void testSetOption3() throws IOException { |
|
343 try (var impl = new PlatformSocketImpl(false)) { |
|
344 impl.create(true); |
|
345 var opt = new SocketOption<String>() { |
|
346 @Override public String name() { return "birthday"; } |
|
347 @Override public Class<String> type() { return String.class; } |
|
348 }; |
|
349 expectThrows(UnsupportedOperationException.class, () -> impl.setOption(opt, "")); |
|
350 // legacy |
|
351 expectThrows(SocketException.class, () -> impl.setOption(-1, "")); |
|
352 } |
|
353 } |
|
354 |
|
355 /** |
|
356 * Test setOption(int, Object) with invalid values. |
|
357 */ |
|
358 public void testSetOption4() throws IOException { |
|
359 try (var impl = new PlatformSocketImpl(false)) { |
|
360 impl.create(true); |
|
361 expectThrows(SocketException.class, |
|
362 () -> impl.setOption(SocketOptions.SO_REUSEADDR, -1)); |
|
363 expectThrows(SocketException.class, |
|
364 () -> impl.setOption(SocketOptions.SO_TIMEOUT, -1)); |
|
365 expectThrows(SocketException.class, |
|
366 () -> impl.setOption(SocketOptions.SO_SNDBUF, -1)); |
|
367 expectThrows(SocketException.class, |
|
368 () -> impl.setOption(SocketOptions.SO_RCVBUF, -1)); |
|
369 } |
|
370 } |
|
371 |
|
372 /** |
|
373 * Test getOption when not created. |
|
374 */ |
|
375 public void testGetOption1() throws IOException { |
|
376 var impl = new PlatformSocketImpl(false); |
|
377 expectThrows(IOException.class, |
|
378 () -> impl.getOption(StandardSocketOptions.SO_REUSEADDR)); |
|
379 expectThrows(SocketException.class, |
|
380 () -> impl.getOption(-1)); |
|
381 } |
|
382 |
|
383 /** |
|
384 * Test getOption when closed. |
|
385 */ |
|
386 public void testGetOption2() throws IOException { |
|
387 var impl = new PlatformSocketImpl(false); |
|
388 impl.close(); |
|
389 expectThrows(IOException.class, |
|
390 () -> impl.getOption(StandardSocketOptions.SO_REUSEADDR)); |
|
391 expectThrows(SocketException.class, |
|
392 () -> impl.getOption(SocketOptions.SO_REUSEADDR)); |
|
393 } |
|
394 |
|
395 /** |
|
396 * Test getOption with unsupported option. |
|
397 */ |
|
398 public void testGetOption3() throws IOException { |
|
399 try (var impl = new PlatformSocketImpl(false)) { |
|
400 impl.create(true); |
|
401 var opt = new SocketOption<String>() { |
|
402 @Override public String name() { return "birthday"; } |
|
403 @Override public Class<String> type() { return String.class; } |
|
404 }; |
|
405 expectThrows(UnsupportedOperationException.class, () -> impl.getOption(opt)); |
|
406 expectThrows(SocketException.class, () -> impl.getOption(-1)); |
|
407 } |
|
408 } |
|
409 |
|
410 /** |
|
411 * Test shutdownInput when not created. |
|
412 */ |
|
413 public void testShutdownInput1() throws IOException { |
|
414 var impl = new PlatformSocketImpl(false); |
|
415 expectThrows(IOException.class, () -> impl.shutdownInput()); |
|
416 } |
|
417 |
|
418 /** |
|
419 * Test shutdownInput when not connected. |
|
420 */ |
|
421 public void testShutdownInput2() throws IOException { |
|
422 try (var impl = new PlatformSocketImpl(false)) { |
|
423 impl.create(true); |
|
424 expectThrows(IOException.class, () -> impl.shutdownInput()); |
|
425 } |
|
426 } |
|
427 |
|
428 /** |
|
429 * Test shutdownInput when closed. |
|
430 */ |
|
431 public void testShutdownInput3() throws IOException { |
|
432 var impl = new PlatformSocketImpl(false); |
|
433 impl.close(); |
|
434 expectThrows(IOException.class, () -> impl.shutdownInput()); |
|
435 } |
|
436 |
|
437 /** |
|
438 * Test shutdownOutput when not created. |
|
439 */ |
|
440 public void testShutdownOutput1() throws IOException { |
|
441 var impl = new PlatformSocketImpl(false); |
|
442 expectThrows(IOException.class, () -> impl.shutdownOutput()); |
|
443 } |
|
444 |
|
445 /** |
|
446 * Test shutdownOutput when not connected. |
|
447 */ |
|
448 public void testShutdownOutput2() throws IOException { |
|
449 try (var impl = new PlatformSocketImpl(false)) { |
|
450 impl.create(true); |
|
451 expectThrows(IOException.class, () -> impl.shutdownOutput()); |
|
452 } |
|
453 } |
|
454 |
|
455 /** |
|
456 * Test shutdownOutput when closed. |
|
457 */ |
|
458 public void testShutdownOutput3() throws IOException { |
|
459 var impl = new PlatformSocketImpl(false); |
|
460 impl.close(); |
|
461 expectThrows(IOException.class, () -> impl.shutdownOutput()); |
|
462 } |
|
463 |
|
464 /** |
|
465 * Test sendUrgentData when not created. |
|
466 */ |
|
467 public void testSendUrgentData1() throws IOException { |
|
468 var impl = new PlatformSocketImpl(false); |
|
469 expectThrows(IOException.class, () -> impl.sendUrgentData(0)); |
|
470 } |
|
471 |
|
472 /** |
|
473 * Test sendUrgentData when not connected. |
|
474 */ |
|
475 public void testSendUrgentData2() throws IOException { |
|
476 try (var impl = new PlatformSocketImpl(false)) { |
|
477 impl.create(true); |
|
478 expectThrows(IOException.class, () -> impl.sendUrgentData(0)); |
|
479 } |
|
480 } |
|
481 |
|
482 /** |
|
483 * Test sendUrgentData when closed. |
|
484 */ |
|
485 public void testSendUrgentData3() throws IOException { |
|
486 var impl = new PlatformSocketImpl(false); |
|
487 impl.close(); |
|
488 expectThrows(IOException.class, () -> impl.sendUrgentData(0)); |
|
489 } |
|
490 } |