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:
parent
b2599f8b0e
commit
04e8cb8641
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()
|
||||
|
123
test/jdk/java/net/ServerSocket/ClosedServerSocketTest.java
Normal file
123
test/jdk/java/net/ServerSocket/ClosedServerSocketTest.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
176
test/jdk/java/net/Socket/ClosedSocketTest.java
Normal file
176
test/jdk/java/net/Socket/ClosedSocketTest.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user