# HG changeset patch # User alanb # Date 1554716855 -3600 # Node ID 6d80c72b7484e5a9b536ad508875b3844c470f0a # Parent c1fad761a86e760459461781e13322b3adeae9e4 Cleanup of test for bad usages of SocketImpl diff -r c1fad761a86e -r 6d80c72b7484 test/jdk/java/net/SocketImpl/BadClient.java --- a/test/jdk/java/net/SocketImpl/BadClient.java Sun Apr 07 18:40:55 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,643 +0,0 @@ -/* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @modules java.base/java.net:+open java.base/sun.nio.ch:+open - * @run testng/othervm BadClient - * @summary Test the SocketImpl for scenarios that do not arise with Socket or - * ServerSocket - */ - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketAddress; -import java.net.SocketException; -import java.net.SocketImpl; -import java.net.SocketOption; -import java.net.StandardSocketOptions; -import java.util.Set; - -import org.testng.annotations.Test; -import static org.testng.Assert.*; - -@Test -public class BadClient { - - /** - * Test create when already created - */ - public void testCreate1() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.create(true)); - } - } - - /** - * Test create when closed - */ - public void testCreate2() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.create(true)); - } - - /** - * Test connect when not created - */ - public void testConnect1() throws IOException { - try (var ss = new ServerSocket(0)) { - var impl = new PlatformSocketImpl(false); - var remote = ss.getLocalSocketAddress(); - expectThrows(IOException.class, () -> impl.connect(remote, 0)); - } - } - - /** - * Test connect with unsupported address type - */ - public void testConnect2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - var remote = new SocketAddress() { }; - expectThrows(IOException.class, () -> impl.connect(remote, 0)); - } - } - - /** - * Test connect with an unresolved address - */ - public void testConnect3() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - var remote = new InetSocketAddress("blah-blah.blah-blah", 80); - expectThrows(IOException.class, () -> impl.connect(remote, 0)); - } - } - - /** - * Test connect when already connected - */ - public void testConnect4() throws IOException { - try (var ss = new ServerSocket(0); - var impl = new PlatformSocketImpl(false)) { - impl.create(true); - impl.connect(ss.getLocalSocketAddress(), 0); - var remote = ss.getLocalSocketAddress(); - expectThrows(IOException.class, () -> impl.connect(remote, 0)); - } - } - - /** - * Test connect when impl is closed - */ - public void testConnect5() throws IOException { - try (var ss = new ServerSocket(0)) { - var impl = new PlatformSocketImpl(false); - impl.close(); - var remote = ss.getLocalSocketAddress(); - expectThrows(IOException.class, () -> impl.connect(remote, 0)); - } - } - - /** - * Test connect(String host, int port) - */ - public void testConnect6() throws IOException { - try (var ss = new ServerSocket(0); - var impl = new PlatformSocketImpl(false)) { - impl.create(true); - impl.connect(ss.getInetAddress().getHostAddress(), ss.getLocalPort()); - } - } - - /** - * Test connect(InetAddress address, int port) - */ - public void testConnect7() throws IOException { - try (var ss = new ServerSocket(0); - var impl = new PlatformSocketImpl(false)) { - impl.create(true); - impl.connect(ss.getInetAddress(), ss.getLocalPort()); - } - } - - /** - * Test bind when not created - */ - public void testBind1() throws IOException { - var impl = new PlatformSocketImpl(false); - var loopback = InetAddress.getLoopbackAddress(); - expectThrows(IOException.class, () -> impl.bind(loopback, 0)); - } - - /** - * Test bind when already bound - */ - public void testBind2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - var loopback = InetAddress.getLoopbackAddress(); - impl.bind(loopback, 0); - expectThrows(IOException.class, () -> impl.bind(loopback, 0)); - } - } - - /** - * Test bind when connected - */ - public void testBind3() throws IOException { - try (var ss = new ServerSocket(0); - var impl = new PlatformSocketImpl(false)) { - impl.create(true); - impl.connect(ss.getLocalSocketAddress(), 0); - var loopback = InetAddress.getLoopbackAddress(); - expectThrows(IOException.class, () -> impl.bind(loopback, 0)); - } - } - - /** - * Test bind when closed - */ - public void testBind4() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - var loopback = InetAddress.getLoopbackAddress(); - expectThrows(IOException.class, () -> impl.bind(loopback, 0)); - } - - - /** - * Test listen when not created - */ - public void testListen1() { - var impl = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.listen(16)); - } - - /** - * Test listen when not bound - */ - public void testListen2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.listen(16)); - } - } - - /** - * Test listen when closed - */ - public void testListen3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.listen(16)); - } - - /** - * Test accept when not created - */ - public void testAccept1() throws IOException { - var impl = new PlatformSocketImpl(true); - var si = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.accept(si)); - } - - /** - * Test accept when not bound - */ - public void testAccept2() throws IOException { - try (var impl = new PlatformSocketImpl(true)) { - impl.create(true); - var si = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.accept(si)); - } - } - - /** - * Test accept when not a stream socket - */ - public void testAccept3() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(false); - impl.bind(InetAddress.getLoopbackAddress(), 0); - var si = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.accept(si)); - } - } - - /** - * Test accept when closed - */ - public void testAccept4() throws IOException { - var impl = new PlatformSocketImpl(true); - impl.close(); - var si = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.accept(si)); - } - - /** - * Test accept with SocketImpl that is already created - */ - public void testAccept5() throws IOException { - try (var impl = new PlatformSocketImpl(true); - var si = new PlatformSocketImpl(false)) { - impl.create(true); - impl.bind(InetAddress.getLoopbackAddress(), 0); - si.create(true); - expectThrows(IOException.class, () -> impl.accept(si)); - } - } - - /** - * Test accept with SocketImpl that is closed - */ - public void testAccept6() throws IOException { - try (var impl = new PlatformSocketImpl(true); - var si = new PlatformSocketImpl(false)) { - impl.create(true); - impl.bind(InetAddress.getLoopbackAddress(), 0); - si.create(true); - si.close(); - expectThrows(IOException.class, () -> impl.accept(si)); - } - } - - /** - * Test available when not created - */ - public void testAvailable1() throws IOException { - var impl = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.available()); - } - - /** - * Test available when created but not connected - */ - public void testAvailable2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.available()); - } - } - - /** - * Test available when closed - */ - public void testAvailable3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.available()); - } - - - /** - * Test setOption with unsupported option - */ - public void testSetOption1() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - var opt = new SocketOption() { - @Override public String name() { return "birthday"; } - @Override public Class type() { return String.class; } - }; - expectThrows(UnsupportedOperationException.class, () -> impl.setOption(opt, "today")); - } - } - - /** - * Test setOption when not created - */ - public void testSetOption2() throws IOException { - var impl = new PlatformSocketImpl(false); - var opt = StandardSocketOptions.SO_REUSEADDR; - expectThrows(IOException.class, () -> impl.setOption(opt, true)); - } - - /** - * Test setOption when closed - */ - public void testSetOption3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - var opt = StandardSocketOptions.SO_REUSEADDR; - expectThrows(IOException.class, () -> impl.setOption(opt, true)); - } - - /** - * Test getOption with unsupported option - */ - public void testGetOption1() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - var opt = new SocketOption() { - @Override public String name() { return "birthday"; } - @Override public Class type() { return String.class; } - }; - expectThrows(UnsupportedOperationException.class, () -> impl.getOption(opt)); - } - } - - /** - * Test getOption when not created - */ - public void testGetOption2() throws IOException { - var impl = new PlatformSocketImpl(false); - var opt = StandardSocketOptions.SO_REUSEADDR; - expectThrows(IOException.class, () -> impl.getOption(opt)); - } - - /** - * Test getOption when closed - */ - public void testGetOption3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - var opt = StandardSocketOptions.SO_REUSEADDR; - expectThrows(IOException.class, () -> impl.getOption(opt)); - } - - /** - * Test shutdownInput when not created - */ - public void testShutdownInput1() throws IOException { - var impl = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.shutdownInput()); - } - - /** - * Test shutdownInput when not connected - */ - public void testShutdownInput2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.shutdownInput()); - } - } - - /** - * Test shutdownInput when closed - */ - public void testShutdownInput3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.shutdownInput()); - } - - /** - * Test shutdownOutput when not created - */ - public void testShutdownOutput1() throws IOException { - var impl = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.shutdownOutput()); - } - - /** - * Test shutdownOutput when not connected - */ - public void testShutdownOutput2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.shutdownOutput()); - } - } - - /** - * Test shutdownOutput when closed - */ - public void testShutdownOutput3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.shutdownOutput()); - } - - /** - * Test sendUrgentData when not created - */ - public void testSendUrgentData1() throws IOException { - var impl = new PlatformSocketImpl(false); - expectThrows(IOException.class, () -> impl.sendUrgentData(0)); - } - - /** - * Test sendUrgentData when not connected - */ - public void testSendUrgentData2() throws IOException { - try (var impl = new PlatformSocketImpl(false)) { - impl.create(true); - expectThrows(IOException.class, () -> impl.sendUrgentData(0)); - } - } - - /** - * Test sendUrgentData when closed - */ - public void testSendUrgentData3() throws IOException { - var impl = new PlatformSocketImpl(false); - impl.close(); - expectThrows(IOException.class, () -> impl.sendUrgentData(0)); - } - - - /** - * A SocketImpl that delegates all operations to a NioSocketImpl. - */ - static class PlatformSocketImpl extends SocketImpl implements AutoCloseable { - private final SocketImpl impl; - - PlatformSocketImpl(boolean server) { - try { - Class clazz = Class.forName("sun.nio.ch.NioSocketImpl"); - Constructor ctor = clazz.getConstructor(boolean.class); - this.impl = (SocketImpl) ctor.newInstance(server); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public void close() throws IOException { - find("close").invoke(impl); - } - - @Override - protected void create(boolean stream) throws IOException { - find("create", boolean.class).invoke(impl, stream); - } - - @Override - protected void connect(SocketAddress remote, int millis) throws IOException { - find("connect", SocketAddress.class, int.class).invoke(impl, remote, millis); - } - - @Override - protected void connect(String host, int port) throws IOException { - find("connect", String.class, int.class).invoke(impl, host, port); - } - - @Override - protected void connect(InetAddress address, int port) throws IOException { - find("connect", InetAddress.class, int.class).invoke(impl, address, port); - } - - @Override - protected void bind(InetAddress address, int port) throws IOException { - find("bind", InetAddress.class, int.class).invoke(impl, address, port); - } - - @Override - protected void listen(int backlog) throws IOException { - find("listen", int.class).invoke(impl, backlog); - } - - @Override - protected void accept(SocketImpl si) throws IOException { - find("accept", SocketImpl.class).invoke(this.impl, ((PlatformSocketImpl) si).impl); - } - - @Override - protected InputStream getInputStream() throws IOException { - return (InputStream) find("getInputStream").invoke(impl); - } - - @Override - protected OutputStream getOutputStream() throws IOException { - return (OutputStream) find("getOutputStream").invoke(impl); - } - - @Override - protected int available() throws IOException { - return (int) find("available").invoke(impl); - } - - @Override - protected Set> supportedOptions() { - try { - return (Set>) find("supportedOptions").invoke(impl); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - @Override - protected void setOption(SocketOption opt, T value) throws IOException { - find("setOption", SocketOption.class, Object.class).invoke(impl, opt, value); - } - - @Override - protected T getOption(SocketOption opt) throws IOException { - return (T) find("getOption", SocketOption.class).invoke(impl, opt); - } - - @Override - public void setOption(int opt, Object value) throws SocketException { - try { - find("setOption", int.class, Object.class).invoke(impl, opt, value); - } catch (SocketException e) { - throw e; - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - @Override - public Object getOption(int opt) throws SocketException { - try { - return find("getOption", int.class).invoke(impl, opt); - } catch (SocketException e) { - throw e; - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - @Override - protected void shutdownInput() throws IOException { - find("shutdownInput").invoke(impl); - } - - @Override - protected void shutdownOutput() throws IOException { - find("shutdownOutput").invoke(impl); - } - - @Override - protected boolean supportsUrgentData() { - try { - return (boolean) find("supportsUrgentData").invoke(impl); - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - @Override - protected void sendUrgentData(int data) throws IOException { - find("sendUrgentData", int.class).invoke(impl, data); - } - - private MethodInvoker find(String name, Class... paramTypes) { - try { - Method m = SocketImpl.class.getDeclaredMethod(name, paramTypes); - m.setAccessible(true); - return new MethodInvoker(m); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - static class MethodInvoker { - private final Method method; - - MethodInvoker(Method method) { - this.method = method; - } - - Object invoke(Object target, Object... args) throws IOException { - try { - return method.invoke(target, args); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof IOException) { - throw (IOException) cause; - } else if (cause instanceof RuntimeException) { - throw (RuntimeException) cause; - } else if (cause instanceof Error) { - throw (Error) cause; - } else { - throw new RuntimeException(e); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } -} diff -r c1fad761a86e -r 6d80c72b7484 test/jdk/java/net/SocketImpl/BadUsages.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/net/SocketImpl/BadUsages.java Mon Apr 08 10:47:35 2019 +0100 @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @compile/module=java.base java/net/PlatformSocketImpl.java + * @run testng/othervm BadUsages + * @summary Test the platform SocketImpl in illegal state/bad input scenarios + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketImpl; +import java.net.SocketOption; +import java.net.SocketOptions; +import java.net.StandardSocketOptions; +import java.util.Set; + +import java.net.PlatformSocketImpl; // test helper + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +/** + * SocketImpl does not specify how the SocketImpl behaves when used in ways + * that are not intended, e.g. invoking socket operations before the socket is + * created or trying to establish a connection after the socket is connected or + * closed. + * + * This test exercises the platform SocketImpl to test that it is reliable, and + * throws reasonable exceptions, for these scenarios. + */ + +@Test +public class BadUsages { + + /** + * Test create when already created. + */ + public void testCreate1() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.create(true)); + } + } + + /** + * Test create when closed. + */ + public void testCreate2() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.create(true)); + } + + /** + * Test connect when not created. + */ + public void testConnect1() throws IOException { + try (var ss = new ServerSocket(0)) { + var impl = new PlatformSocketImpl(false); + var address = ss.getInetAddress(); + int port = ss.getLocalPort(); + expectThrows(IOException.class, () -> impl.connect(address, port)); + } + } + + /** + * Test connect with unsupported address type. + */ + public void testConnect2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + var remote = new SocketAddress() { }; + expectThrows(IOException.class, () -> impl.connect(remote, 0)); + } + } + + /** + * Test connect with an unresolved address. + */ + public void testConnect3() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + var remote = new InetSocketAddress("blah-blah.blah-blah", 80); + expectThrows(IOException.class, () -> impl.connect(remote, 0)); + } + } + + /** + * Test connect when already connected. + */ + public void testConnect4() throws IOException { + try (var ss = new ServerSocket(0); + var impl = new PlatformSocketImpl(false)) { + impl.create(true); + String host = ss.getInetAddress().getHostAddress(); + int port = ss.getLocalPort(); + impl.connect(host, port); + expectThrows(IOException.class, () -> impl.connect(host, port)); + } + } + + /** + * Test connect when closed. + */ + public void testConnect5() throws IOException { + try (var ss = new ServerSocket(0)) { + var impl = new PlatformSocketImpl(false); + impl.close(); + String host = ss.getInetAddress().getHostAddress(); + int port = ss.getLocalPort(); + expectThrows(IOException.class, () -> impl.connect(host, port)); + } + } + + /** + * Test bind when not created. + */ + public void testBind1() throws IOException { + var impl = new PlatformSocketImpl(false); + var loopback = InetAddress.getLoopbackAddress(); + expectThrows(IOException.class, () -> impl.bind(loopback, 0)); + } + + /** + * Test bind when already bound. + */ + public void testBind2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + var loopback = InetAddress.getLoopbackAddress(); + impl.bind(loopback, 0); + expectThrows(IOException.class, () -> impl.bind(loopback, 0)); + } + } + + /** + * Test bind when connected. + */ + public void testBind3() throws IOException { + try (var ss = new ServerSocket(0); + var impl = new PlatformSocketImpl(false)) { + impl.create(true); + impl.connect(ss.getLocalSocketAddress(), 0); + var loopback = InetAddress.getLoopbackAddress(); + expectThrows(IOException.class, () -> impl.bind(loopback, 0)); + } + } + + /** + * Test bind when closed. + */ + public void testBind4() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + var loopback = InetAddress.getLoopbackAddress(); + expectThrows(IOException.class, () -> impl.bind(loopback, 0)); + } + + + /** + * Test listen when not created. + */ + public void testListen1() { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.listen(16)); + } + + /** + * Test listen when not bound. + */ + public void testListen2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.listen(16)); + } + } + + /** + * Test listen when closed. + */ + public void testListen3() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.listen(16)); + } + + /** + * Test accept when not created. + */ + public void testAccept1() throws IOException { + var impl = new PlatformSocketImpl(true); + var si = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.accept(si)); + } + + /** + * Test accept when not bound. + */ + public void testAccept2() throws IOException { + try (var impl = new PlatformSocketImpl(true)) { + impl.create(true); + var si = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.accept(si)); + } + } + + /** + * Test accept when not a stream socket. + */ + public void testAccept3() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(false); + impl.bind(InetAddress.getLoopbackAddress(), 0); + var si = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.accept(si)); + } + } + + /** + * Test accept when closed. + */ + public void testAccept4() throws IOException { + var impl = new PlatformSocketImpl(true); + impl.close(); + var si = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.accept(si)); + } + + /** + * Test accept with SocketImpl that is already created. + */ + public void testAccept5() throws IOException { + try (var impl = new PlatformSocketImpl(true); + var si = new PlatformSocketImpl(false)) { + impl.create(true); + impl.bind(InetAddress.getLoopbackAddress(), 0); + si.create(true); + expectThrows(IOException.class, () -> impl.accept(si)); + } + } + + /** + * Test accept with SocketImpl that is closed. + */ + public void testAccept6() throws IOException { + try (var impl = new PlatformSocketImpl(true); + var si = new PlatformSocketImpl(false)) { + impl.create(true); + impl.bind(InetAddress.getLoopbackAddress(), 0); + si.create(true); + si.close(); + expectThrows(IOException.class, () -> impl.accept(si)); + } + } + + /** + * Test available when not created. + */ + public void testAvailable1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.available()); + } + + /** + * Test available when created but not connected. + */ + public void testAvailable2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.available()); + } + } + + /** + * Test available when closed. + */ + public void testAvailable3() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.available()); + } + + /** + * Test setOption when not created. + */ + public void testSetOption1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, + () -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true)); + // legacy + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_REUSEADDR, true)); + } + + /** + * Test setOption when closed. + */ + public void testSetOption2() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, + () -> impl.setOption(StandardSocketOptions.SO_REUSEADDR, true)); + // legacy + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_REUSEADDR, true)); + } + + /** + * Test setOption with unsupported option. + */ + public void testSetOption3() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + var opt = new SocketOption() { + @Override public String name() { return "birthday"; } + @Override public Class type() { return String.class; } + }; + expectThrows(UnsupportedOperationException.class, () -> impl.setOption(opt, "")); + // legacy + expectThrows(SocketException.class, () -> impl.setOption(-1, "")); + } + } + + /** + * Test setOption(int, Object) with invalid values. + */ + public void testSetOption4() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_REUSEADDR, -1)); + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_TIMEOUT, -1)); + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_SNDBUF, -1)); + expectThrows(SocketException.class, + () -> impl.setOption(SocketOptions.SO_RCVBUF, -1)); + } + } + + /** + * Test getOption when not created. + */ + public void testGetOption1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, + () -> impl.getOption(StandardSocketOptions.SO_REUSEADDR)); + expectThrows(SocketException.class, + () -> impl.getOption(-1)); + } + + /** + * Test getOption when closed. + */ + public void testGetOption2() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, + () -> impl.getOption(StandardSocketOptions.SO_REUSEADDR)); + expectThrows(SocketException.class, + () -> impl.getOption(SocketOptions.SO_REUSEADDR)); + } + + /** + * Test getOption with unsupported option. + */ + public void testGetOption3() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + var opt = new SocketOption() { + @Override public String name() { return "birthday"; } + @Override public Class type() { return String.class; } + }; + expectThrows(UnsupportedOperationException.class, () -> impl.getOption(opt)); + expectThrows(SocketException.class, () -> impl.getOption(-1)); + } + } + + /** + * Test shutdownInput when not created. + */ + public void testShutdownInput1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.shutdownInput()); + } + + /** + * Test shutdownInput when not connected. + */ + public void testShutdownInput2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.shutdownInput()); + } + } + + /** + * Test shutdownInput when closed. + */ + public void testShutdownInput3() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.shutdownInput()); + } + + /** + * Test shutdownOutput when not created. + */ + public void testShutdownOutput1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.shutdownOutput()); + } + + /** + * Test shutdownOutput when not connected. + */ + public void testShutdownOutput2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.shutdownOutput()); + } + } + + /** + * Test shutdownOutput when closed. + */ + public void testShutdownOutput3() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.shutdownOutput()); + } + + /** + * Test sendUrgentData when not created. + */ + public void testSendUrgentData1() throws IOException { + var impl = new PlatformSocketImpl(false); + expectThrows(IOException.class, () -> impl.sendUrgentData(0)); + } + + /** + * Test sendUrgentData when not connected. + */ + public void testSendUrgentData2() throws IOException { + try (var impl = new PlatformSocketImpl(false)) { + impl.create(true); + expectThrows(IOException.class, () -> impl.sendUrgentData(0)); + } + } + + /** + * Test sendUrgentData when closed. + */ + public void testSendUrgentData3() throws IOException { + var impl = new PlatformSocketImpl(false); + impl.close(); + expectThrows(IOException.class, () -> impl.sendUrgentData(0)); + } +} diff -r c1fad761a86e -r 6d80c72b7484 test/jdk/java/net/SocketImpl/java.base/java/net/PlatformSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/net/SocketImpl/java.base/java/net/PlatformSocketImpl.java Mon Apr 08 10:47:35 2019 +0100 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Set; + +/** + * A SocketImpl that delegates all operations to a platform SocketImpl. It also + * overrides all methods with public methods and implements AutoCloseable to make + * it easy to write tests. + */ + +public class PlatformSocketImpl extends SocketImpl implements AutoCloseable { + private final SocketImpl impl; + + public PlatformSocketImpl(boolean server) { + impl = new sun.nio.ch.NioSocketImpl(server); + } + + @Override + public void close() throws IOException { + impl.close(); + } + + @Override + public void create(boolean stream) throws IOException { + impl.create(stream); + } + + @Override + public void connect(SocketAddress remote, int millis) throws IOException { + impl.connect(remote, millis); + } + + @Override + public void connect(String host, int port) throws IOException { + impl.connect(host, port); + } + + @Override + public void connect(InetAddress address, int port) throws IOException { + impl.connect(address, port); + } + + @Override + public void bind(InetAddress address, int port) throws IOException { + impl.bind(address, port); + } + + @Override + public void listen(int backlog) throws IOException { + impl.listen(backlog); + } + + @Override + public void accept(SocketImpl si) throws IOException { + impl.accept(((PlatformSocketImpl) si).impl); + } + + @Override + public InputStream getInputStream() throws IOException { + return impl.getInputStream(); + } + + @Override + public OutputStream getOutputStream() throws IOException { + return impl.getOutputStream(); + } + + @Override + public int available() throws IOException { + return impl.available(); + } + + @Override + public Set> supportedOptions() { + return impl.supportedOptions(); + } + + @Override + public void setOption(SocketOption opt, T value) throws IOException { + impl.setOption(opt, value); + } + + @Override + public T getOption(SocketOption opt) throws IOException { + return impl.getOption(opt); + } + + @Override + public void setOption(int opt, Object value) throws SocketException { + impl.setOption(opt, value); + } + + @Override + public Object getOption(int opt) throws SocketException { + return impl.getOption(opt); + } + + @Override + public void shutdownInput() throws IOException { + impl.shutdownInput(); + } + + @Override + public void shutdownOutput() throws IOException { + impl.shutdownOutput(); + } + + @Override + public boolean supportsUrgentData() { + return impl.supportsUrgentData(); + } + + @Override + public void sendUrgentData(int data) throws IOException { + impl.sendUrgentData(data); + } +}