8336815: Several methods in java.net.Socket and ServerSocket do not specify behavior when already bound, connected or closed

Reviewed-by: alanb
This commit is contained in:
Jaikiran Pai 2024-07-24 15:43:53 +00:00
parent b2599f8b0e
commit 04e8cb8641
4 changed files with 367 additions and 64 deletions
src/java.base/share/classes/java/net
test/jdk/java/net

@ -328,8 +328,8 @@ public class ServerSocket implements java.io.Closeable {
* an ephemeral port and a valid local address to bind the socket.
*
* @param endpoint The IP address and port number to bind to.
* @throws IOException if the bind operation fails, or if the socket
* is already bound.
* @throws IOException if the bind operation fails, the socket
* is already bound or the socket is closed.
* @throws SecurityException if a {@code SecurityManager} is present and
* its {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if endpoint is a
@ -357,8 +357,8 @@ public class ServerSocket implements java.io.Closeable {
* @param endpoint The IP address and port number to bind to.
* @param backlog requested maximum length of the queue of
* incoming connections.
* @throws IOException if the bind operation fails, or if the socket
* is already bound.
* @throws IOException if the bind operation fails, the socket
* is already bound or the socket is closed.
* @throws SecurityException if a {@code SecurityManager} is present and
* its {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if endpoint is a
@ -518,7 +518,7 @@ public class ServerSocket implements java.io.Closeable {
* client socket implementation factory}, if one has been set.
*
* @throws IOException if an I/O error occurs when waiting for a
* connection.
* connection, the socket is not bound or the socket is closed.
* @throws SecurityException if a security manager exists and its
* {@code checkAccept} method doesn't allow the operation.
* @throws SocketTimeoutException if a timeout was previously set with setSoTimeout and
@ -736,6 +736,9 @@ public class ServerSocket implements java.io.Closeable {
* <p> If this socket has an associated channel then the channel is closed
* as well.
*
* <p> Once closed, several of the methods defined by this class will throw
* an exception if invoked on the closed socket.
*
* @throws IOException if an I/O error occurs when closing the socket.
*/
public void close() throws IOException {
@ -806,8 +809,8 @@ public class ServerSocket implements java.io.Closeable {
* operation to have effect.
*
* @param timeout the specified timeout, in milliseconds
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
@ -824,7 +827,7 @@ public class ServerSocket implements java.io.Closeable {
* Retrieve setting for {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}.
* 0 returns implies that the option is disabled (i.e., timeout of infinity).
* @return the {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} value
* @throws IOException if an I/O error occurs
* @throws IOException if an I/O error occurs or the socket is closed.
* @since 1.1
* @see #setSoTimeout(int)
*/
@ -887,8 +890,8 @@ public class ServerSocket implements java.io.Closeable {
*
* @return a {@code boolean} indicating whether or not
* {@code SO_REUSEADDR} is enabled.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol, such as a TCP error,
* or the socket is closed.
* @since 1.4
* @see #setReuseAddress(boolean)
*/
@ -1001,8 +1004,8 @@ public class ServerSocket implements java.io.Closeable {
* requested value but the TCP receive window in sockets accepted from
* this ServerSocket will be no larger than 64K bytes.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @param size the size to which to set the receive buffer
* size. This value must be greater than 0.
@ -1029,8 +1032,8 @@ public class ServerSocket implements java.io.Closeable {
* <p>Note, the value actually set in the accepted socket is determined by
* calling {@link Socket#getReceiveBufferSize()}.
* @return the value of the {@code SO_RCVBUF} option for this {@code Socket}.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @see #setReceiveBufferSize(int)
* @since 1.4
*/

@ -683,7 +683,8 @@ public class Socket implements java.io.Closeable {
* </ol>
*
* @param endpoint the {@code SocketAddress}
* @throws IOException if an error occurs during the connection
* @throws IOException if an error occurs during the connection, the socket
* is already connected or the socket is closed
* @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel,
* and the channel is in non-blocking mode
@ -717,7 +718,8 @@ public class Socket implements java.io.Closeable {
*
* @param endpoint the {@code SocketAddress}
* @param timeout the timeout value to be used in milliseconds.
* @throws IOException if an error occurs during the connection
* @throws IOException if an error occurs during the connection, the socket
* is already connected or the socket is closed
* @throws SocketTimeoutException if timeout expires before connecting
* @throws java.nio.channels.IllegalBlockingModeException
* if this socket has an associated channel,
@ -780,8 +782,8 @@ public class Socket implements java.io.Closeable {
* an ephemeral port and a valid local address to bind the socket.
*
* @param bindpoint the {@code SocketAddress} to bind to
* @throws IOException if the bind operation fails, or if the socket
* is already bound.
* @throws IOException if the bind operation fails, the socket
* is already bound or the socket is closed.
* @throws IllegalArgumentException if bindpoint is a
* SocketAddress subclass not supported by this socket
* @throws SecurityException if a security manager exists and its
@ -1174,8 +1176,8 @@ public class Socket implements java.io.Closeable {
* will close the associated socket.
*
* @return an output stream for writing bytes to this socket.
* @throws IOException if an I/O error occurs when creating the
* output stream or if the socket is not connected.
* @throws IOException if an I/O error occurs when creating the
* output stream, the socket is not connected or the socket is closed.
*/
public OutputStream getOutputStream() throws IOException {
int s = state;
@ -1251,8 +1253,8 @@ public class Socket implements java.io.Closeable {
* @param on {@code true} to enable {@code TCP_NODELAY},
* {@code false} to disable.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @since 1.1
*
@ -1269,8 +1271,8 @@ public class Socket implements java.io.Closeable {
*
* @return a {@code boolean} indicating whether or not
* {@code TCP_NODELAY} is enabled.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.1
* @see #setTcpNoDelay(boolean)
*/
@ -1289,9 +1291,9 @@ public class Socket implements java.io.Closeable {
*
* @param on whether or not to linger on.
* @param linger how long to linger for, if on is true.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws IllegalArgumentException if the linger value is negative.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @throws IllegalArgumentException if the linger value is negative.
* @since 1.1
* @see #getSoLinger()
*/
@ -1318,8 +1320,8 @@ public class Socket implements java.io.Closeable {
* The setting only affects socket close.
*
* @return the setting for {@code SO_LINGER}.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.1
* @see #setSoLinger(boolean, int)
*/
@ -1368,8 +1370,8 @@ public class Socket implements java.io.Closeable {
* @param on {@code true} to enable {@code SO_OOBINLINE},
* {@code false} to disable.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @since 1.4
*
@ -1387,8 +1389,8 @@ public class Socket implements java.io.Closeable {
* @return a {@code boolean} indicating whether or not
* {@code SO_OOBINLINE} is enabled.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.4
* @see #setOOBInline(boolean)
*/
@ -1409,8 +1411,8 @@ public class Socket implements java.io.Closeable {
* to have effect.
*
* @param timeout the specified timeout, in milliseconds.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @throws IllegalArgumentException if {@code timeout} is negative
* @since 1.1
* @see #getSoTimeout()
@ -1428,8 +1430,8 @@ public class Socket implements java.io.Closeable {
* 0 returns implies that the option is disabled (i.e., timeout of infinity).
*
* @return the setting for {@code SO_TIMEOUT}
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @since 1.1
* @see #setSoTimeout(int)
@ -1455,14 +1457,12 @@ public class Socket implements java.io.Closeable {
* <p>Because {@code SO_SNDBUF} is a hint, applications that want to verify
* what size the buffers were set to should call {@link #getSendBufferSize()}.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
*
* @param size the size to which to set the send buffer
* size. This value must be greater than 0.
*
* @throws IllegalArgumentException if the
* value is 0 or is negative.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @throws IllegalArgumentException if the value is 0 or is negative.
*
* @see #getSendBufferSize()
* @since 1.2
@ -1481,8 +1481,8 @@ public class Socket implements java.io.Closeable {
* for output on this {@code Socket}.
* @return the value of the {@code SO_SNDBUF} option for this {@code Socket}.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @see #setSendBufferSize(int)
* @since 1.2
@ -1529,8 +1529,8 @@ public class Socket implements java.io.Closeable {
* @throws IllegalArgumentException if the value is 0 or is
* negative.
*
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
*
* @see #getReceiveBufferSize()
* @see ServerSocket#setReceiveBufferSize(int)
@ -1550,8 +1550,8 @@ public class Socket implements java.io.Closeable {
* for input on this {@code Socket}.
*
* @return the value of the {@code SO_RCVBUF} option for this {@code Socket}.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @see #setReceiveBufferSize(int)
* @since 1.2
*/
@ -1570,8 +1570,8 @@ public class Socket implements java.io.Closeable {
* Enable/disable {@link StandardSocketOptions#SO_KEEPALIVE SO_KEEPALIVE}.
*
* @param on whether or not to have socket keep alive turned on.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.3
* @see #getKeepAlive()
*/
@ -1586,8 +1586,8 @@ public class Socket implements java.io.Closeable {
*
* @return a {@code boolean} indicating whether or not
* {@code SO_KEEPALIVE} is enabled.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.3
* @see #setKeepAlive(boolean)
*/
@ -1637,8 +1637,8 @@ public class Socket implements java.io.Closeable {
* would be placed into the sin6_flowinfo field of the IP header.
*
* @param tc an {@code int} value for the bitset.
* @throws SocketException if there is an error setting the
* traffic class or type-of-service
* @throws SocketException if there is an error setting the traffic class or type-of-service,
* or the socket is closed.
* @since 1.4
* @see #getTrafficClass
* @see StandardSocketOptions#IP_TOS
@ -1661,8 +1661,8 @@ public class Socket implements java.io.Closeable {
* set using the {@link #setTrafficClass(int)} method on this Socket.
*
* @return the traffic class or type-of-service already set
* @throws SocketException if there is an error obtaining the
* traffic class or type-of-service value.
* @throws SocketException if there is an error obtaining the traffic class
* or type-of-service value, or the socket is closed.
* @since 1.4
* @see #setTrafficClass(int)
* @see StandardSocketOptions#IP_TOS
@ -1715,8 +1715,8 @@ public class Socket implements java.io.Closeable {
*
* @return a {@code boolean} indicating whether or not
* {@code SO_REUSEADDR} is enabled.
* @throws SocketException if there is an error
* in the underlying protocol, such as a TCP error.
* @throws SocketException if there is an error in the underlying protocol,
* such as a TCP error, or the socket is closed.
* @since 1.4
* @see #setReuseAddress(boolean)
*/
@ -1733,8 +1733,9 @@ public class Socket implements java.io.Closeable {
* will throw a {@link SocketException}.
* <p>
* Once a socket has been closed, it is not available for further networking
* use (i.e. can't be reconnected or rebound). A new socket needs to be
* created.
* use (i.e. can't be reconnected or rebound) and several of the methods defined
* by this class will throw an exception if invoked on the closed socket. A new
* socket needs to be created.
*
* <p> Closing this socket will also close the socket's
* {@link java.io.InputStream InputStream} and
@ -1767,8 +1768,8 @@ public class Socket implements java.io.Closeable {
* socket, the stream's {@code available} method will return 0, and its
* {@code read} methods will return {@code -1} (end of stream).
*
* @throws IOException if an I/O error occurs when shutting down this
* socket.
* @throws IOException if an I/O error occurs when shutting down this socket, the
* socket is not connected or the socket is closed.
*
* @since 1.3
* @see java.net.Socket#shutdownOutput()
@ -1797,8 +1798,8 @@ public class Socket implements java.io.Closeable {
* shutdownOutput() on the socket, the stream will throw
* an IOException.
*
* @throws IOException if an I/O error occurs when shutting down this
* socket.
* @throws IOException if an I/O error occurs when shutting down this socket, the socket
* is not connected or the socket is closed.
*
* @since 1.3
* @see java.net.Socket#shutdownInput()

@ -0,0 +1,123 @@
/*
* Copyright (c) 2024, 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.
*/
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.StandardSocketOptions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*
* @test
* @summary verifies that the APIs on java.net.ServerSocket throw expected exceptions
* when invoked on a closed ServerSocket
* @run junit ClosedServerSocketTest
*/
public class ClosedServerSocketTest {
private static final InetAddress loopback = InetAddress.getLoopbackAddress();
private static final InetSocketAddress loopbackEphemeral = new InetSocketAddress(loopback, 0);
/**
* Verifies that various operations that specify to throw an IOException on a
* closed ServerSocket, do indeed throw it.
*/
@Test
public void testIOExceptionThrown() throws Exception {
try (final ServerSocket ss = new ServerSocket()) {
// close and then invoke the operations on the ServerSocket
ss.close();
assertTrue(ss.isClosed(), "ServerSocket isn't closed");
assertThrows(IOException.class,
ss::accept,
"accept() when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> ss.bind(loopbackEphemeral),
"bind() when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> ss.bind(loopbackEphemeral, 10),
"bind(SocketAddress, int) when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> ss.getOption(StandardSocketOptions.SO_RCVBUF),
"getOption() when already closed didn't throw IOException");
assertThrows(IOException.class,
ss::getSoTimeout,
"getSoTimeout() when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> ss.setOption(StandardSocketOptions.SO_RCVBUF, 1024),
"setOption() when already closed didn't throw IOException");
}
}
/**
* Verifies that various operations that specify to throw a SocketOperation on a
* closed ServerSocket, do indeed throw it.
*/
@Test
public void testSocketExceptionThrown() throws Exception {
try (final ServerSocket ss = new ServerSocket()) {
// close and then invoke the operations on the ServerSocket
ss.close();
assertTrue(ss.isClosed(), "ServerSocket isn't closed");
assertThrowsExactly(SocketException.class,
ss::getReceiveBufferSize,
"getReceiveBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
ss::getReuseAddress,
"getReuseAddress() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> ss.setReceiveBufferSize(1024),
"setReceiveBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> ss.setReuseAddress(false),
"setReuseAddress() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> ss.setSoTimeout(1000),
"setSoTimeout() when already closed didn't throw SocketException");
}
}
/**
* Verifies that various operations that aren't expected to throw an exception on a
* closed ServerSocket, complete normally.
*/
@Test
public void testNoExceptionThrown() throws Exception {
try (final ServerSocket ss = new ServerSocket()) {
// close and then invoke the operations on the ServerSocket
ss.close();
assertTrue(ss.isClosed(), "ServerSocket isn't closed");
ss.getInetAddress();
ss.getLocalPort();
ss.getLocalSocketAddress();
ss.isBound();
ss.supportedOptions();
}
}
}

@ -0,0 +1,176 @@
/*
* Copyright (c) 2024, 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.
*/
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.StandardSocketOptions;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
/*
* @test
* @summary verifies that the APIs on java.net.Socket throw expected exceptions
* when invoked on a closed socket
* @run junit ClosedSocketTest
*/
public class ClosedSocketTest {
private static final InetAddress loopback = InetAddress.getLoopbackAddress();
private static final InetSocketAddress loopbackEphemeral = new InetSocketAddress(loopback, 0);
/**
* Verifies that various operations that specify to throw an IOException on a closed socket,
* do indeed throw it.
*/
@Test
public void testIOExceptionThrown() throws Exception {
try (final Socket s = new Socket()) {
// close and then invoke the operation on the socket
s.close();
assertTrue(s.isClosed(), "socket isn't closed");
assertThrows(IOException.class, () -> s.bind(loopbackEphemeral),
"bind() when already closed didn't throw IOException");
// connect() will never get to the stage of attempting
// a connection against this port
final int dummyPort = 12345;
assertThrows(IOException.class,
() -> s.connect(new InetSocketAddress(loopback, dummyPort)),
"connect() when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> s.connect(new InetSocketAddress(loopback, dummyPort), 10),
"connect(SocketAddress, int) when already closed didn't throw IOException");
assertThrows(IOException.class,
() -> s.getOption(StandardSocketOptions.SO_RCVBUF),
"getOption() when already closed didn't throw IOException");
assertThrows(IOException.class,
s::getOutputStream,
"getOutputStream() when already closed didn't throw IOException");
assertThrows(IOException.class,
s::shutdownInput,
"shutdownInput() when already closed didn't throw IOException");
assertThrows(IOException.class,
s::shutdownOutput,
"shutdownOutput() when already closed didn't throw IOException");
}
}
/**
* Verifies that various operations that specify to throw a SocketOperation on a closed socket,
* do indeed throw it.
*/
@Test
public void testSocketExceptionThrown() throws Exception {
try (final Socket s = new Socket()) {
// close and then invoke the operations on the socket
s.close();
assertTrue(s.isClosed(), "socket isn't closed");
assertThrowsExactly(SocketException.class,
s::getKeepAlive,
"getKeepAlive() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getOOBInline,
"getOOBInline() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getReceiveBufferSize,
"getReceiveBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getReuseAddress,
"getReuseAddress() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getSendBufferSize,
"getSendBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getSoLinger,
"getSoLinger() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getSoTimeout,
"getSoTimeout() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getTcpNoDelay,
"getTcpNoDelay() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
s::getTrafficClass,
"getTrafficClass() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setKeepAlive(false),
"setKeepAlive() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setOOBInline(false),
"setOOBInline() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setOption(StandardSocketOptions.SO_RCVBUF, 1024),
"setOption() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setReceiveBufferSize(1024),
"setReceiveBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setReuseAddress(false),
"setReuseAddress() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setSendBufferSize(1024),
"setSendBufferSize() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setSoLinger(false, 0),
"setSoLinger() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setSoTimeout(1000),
"setSoTimeout() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setTcpNoDelay(false),
"setTcpNoDelay() when already closed didn't throw SocketException");
assertThrowsExactly(SocketException.class,
() -> s.setTrafficClass(123),
"setTrafficClass() when already closed didn't throw SocketException");
}
}
/**
* Verifies that various operations that aren't expected to throw an exception on a
* closed socket, complete normally.
*/
@Test
public void testNoExceptionThrown() throws Exception {
try (final Socket s = new Socket()) {
// close and then invoke various operation on the socket and don't expect an exception
s.close();
assertTrue(s.isClosed(), "socket isn't closed");
s.getInetAddress();
s.getLocalAddress();
s.getLocalPort();
s.getLocalSocketAddress();
s.getPort();
s.getRemoteSocketAddress();
s.isBound();
s.isConnected();
s.isInputShutdown();
s.isOutputShutdown();
s.supportedOptions();
}
}
}