undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
398
test/jdk/java/net/SocketOption/AfterClose.java
Normal file
398
test/jdk/java/net/SocketOption/AfterClose.java
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2021, 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
|
||||
* @bug 8224477
|
||||
* @summary Ensures that IOException is thrown after the socket is closed
|
||||
* @run testng AfterClose
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static java.lang.Boolean.*;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class AfterClose {
|
||||
|
||||
static final Class<IOException> IOE = IOException.class;
|
||||
static final String RO = "READ_ONLY";
|
||||
|
||||
static Map<SocketOption<?>,List<Object>> OPTION_VALUES_MAP = optionValueMap();
|
||||
|
||||
static boolean supportsMulticast(NetworkInterface ni) {
|
||||
try {
|
||||
return ni.supportsMulticast();
|
||||
} catch (SocketException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static List<Object> listNetworkInterfaces() {
|
||||
try {
|
||||
return NetworkInterface.networkInterfaces()
|
||||
.filter(AfterClose::supportsMulticast)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) { }
|
||||
return List.of();
|
||||
}
|
||||
|
||||
static Map<SocketOption<?>,List<Object>> optionValueMap() {
|
||||
Map<SocketOption<?>,List<Object>> map = new HashMap<>();
|
||||
map.put(IP_MULTICAST_IF, listNetworkInterfaces() );
|
||||
map.put(IP_MULTICAST_LOOP, listOf(TRUE, FALSE) );
|
||||
map.put(IP_MULTICAST_TTL, listOf(0, 100, 255) );
|
||||
map.put(IP_TOS, listOf(0, 101, 255) );
|
||||
map.put(SO_BROADCAST, listOf(TRUE, FALSE) );
|
||||
map.put(SO_KEEPALIVE, listOf(TRUE, FALSE) );
|
||||
map.put(SO_LINGER, listOf(0, 5, 15) );
|
||||
map.put(SO_RCVBUF, listOf(1, 100, 1000));
|
||||
map.put(SO_REUSEADDR, listOf(TRUE, FALSE) );
|
||||
map.put(SO_REUSEPORT, listOf(TRUE, FALSE) );
|
||||
map.put(SO_SNDBUF, listOf(1, 100, 1000));
|
||||
map.put(TCP_NODELAY, listOf(TRUE, FALSE) );
|
||||
// extended options
|
||||
try {
|
||||
Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
|
||||
Field field = c.getField("TCP_QUICKACK");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(TRUE, FALSE));
|
||||
field = c.getField("TCP_KEEPIDLE");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(10, 100));
|
||||
field = c.getField("TCP_KEEPINTERVAL");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(10, 100));
|
||||
field = c.getField("TCP_KEEPCOUNT");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(10, 100));
|
||||
field = c.getField("SO_INCOMING_NAPI_ID");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(RO));
|
||||
field = c.getField("IP_DONTFRAGMENT");
|
||||
map.put((SocketOption<?>)field.get(null), listOf(TRUE, FALSE));
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ignore, jdk.net module not present
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// -- Socket
|
||||
|
||||
@DataProvider(name = "socketOptionValues")
|
||||
public Object[][] socketOptionValues() throws Exception {
|
||||
try (Socket s = new Socket()) {
|
||||
return s.supportedOptions().stream()
|
||||
.map(so -> new Object[] {so, OPTION_VALUES_MAP.get(so)})
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "socketOptionValues")
|
||||
public <T> void closedSocketImplUncreated(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = createClosedSocketImplUncreated();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
expectThrows(IOE, () -> socket.setOption(option, value));
|
||||
expectThrows(IOE, () -> socket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "socketOptionValues")
|
||||
public <T> void closedSocketImplCreated(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = createClosedSocketImplCreated();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
expectThrows(IOE, () -> socket.setOption(option, value));
|
||||
expectThrows(IOE, () -> socket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "socketOptionValues")
|
||||
public <T> void closedSocketAdapter(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
Socket socket = createClosedSocketFromAdapter();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> socket.setOption(option, value));
|
||||
expectThrows(IOE, () -> socket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- ServerSocket
|
||||
|
||||
@DataProvider(name = "serverSocketOptionValues")
|
||||
public Object[][] serverSocketOptionValues() throws Exception {
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
return ss.supportedOptions().stream()
|
||||
.map(so -> new Object[] {so, OPTION_VALUES_MAP.get(so)})
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "serverSocketOptionValues")
|
||||
public <T> void closedServerSocketImplUncreated(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
ServerSocket serverSocket = createClosedServerSocketImplUncreated();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
expectThrows(IOE, () -> serverSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> serverSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "serverSocketOptionValues")
|
||||
public <T> void closedServerSocketImplCreated(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
ServerSocket serverSocket = createClosedServerSocketImplCreated();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
expectThrows(IOE, () -> serverSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> serverSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "serverSocketOptionValues")
|
||||
public <T> void closedServerSocketAdapter(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
if (option == IP_TOS)
|
||||
return; // SSC does not support IP_TOS
|
||||
|
||||
ServerSocket serverSocket = createClosedServerSocketFromAdapter();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> serverSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> serverSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- DatagramSocket
|
||||
|
||||
@DataProvider(name = "datagramSocketOptionValues")
|
||||
public Object[][] datagramSocketOptionValues() throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket()) {
|
||||
return ds.supportedOptions().stream()
|
||||
.map(so -> new Object[] {so, OPTION_VALUES_MAP.get(so)})
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "datagramSocketOptionValues")
|
||||
public <T> void closedUnboundDatagramSocket(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
DatagramSocket datagramSocket = createClosedUnboundDatagramSocket();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> datagramSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> datagramSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "datagramSocketOptionValues")
|
||||
public <T> void closedBoundDatagramSocket(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
DatagramSocket datagramSocket = createClosedBoundDatagramSocket();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> datagramSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> datagramSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "datagramSocketOptionValues")
|
||||
public <T> void closedDatagramAdapter(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
DatagramSocket datagramSocket = createClosedBoundDatagramSocket();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> datagramSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> datagramSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -- MulticastSocket
|
||||
|
||||
@DataProvider(name = "multicastSocketOptionValues")
|
||||
public Object[][] multicastSocketOptionValues() throws Exception {
|
||||
try (MulticastSocket ms = new MulticastSocket()) {
|
||||
return ms.supportedOptions().stream()
|
||||
.map(so -> new Object[] {so, OPTION_VALUES_MAP.get(so)})
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "multicastSocketOptionValues")
|
||||
public <T> void closedUnboundMulticastSocket(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
MulticastSocket multicastSocket = createClosedUnboundMulticastSocket();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> multicastSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> multicastSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "multicastSocketOptionValues")
|
||||
public <T> void closedBoundMulticastSocket(SocketOption<T> option, List<T> values)
|
||||
throws IOException
|
||||
{
|
||||
MulticastSocket multicastSocket = createClosedBoundMulticastSocket();
|
||||
for (int i=0; i<3; i++); {
|
||||
for (T value : values) {
|
||||
if (!RO.equals(value)) expectThrows(IOE, () -> multicastSocket.setOption(option, value));
|
||||
expectThrows(IOE, () -> multicastSocket.getOption(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
static List<Object> listOf(Object... objs) {
|
||||
List<Object> l = new ArrayList<>();
|
||||
Arrays.stream(objs).forEachOrdered(l::add);
|
||||
return l;
|
||||
}
|
||||
|
||||
// Returns a closed Socket that has an impl whose `create` method has NOT been invoked.
|
||||
static Socket createClosedSocketImplUncreated() throws IOException {
|
||||
Socket s = new Socket();
|
||||
s.close();
|
||||
return s;
|
||||
}
|
||||
|
||||
// Returns a closed Socket that has an impl whose `create` method has been invoked.
|
||||
static Socket createClosedSocketImplCreated() throws IOException {
|
||||
Socket s = new Socket();
|
||||
s.bind(null); // binding causes impl::create to be invoked
|
||||
s.close();
|
||||
return s;
|
||||
}
|
||||
|
||||
// Returns a closed Socket created from a SocketChannel's adapter.
|
||||
static Socket createClosedSocketFromAdapter() throws IOException {
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.close();
|
||||
return sc.socket();
|
||||
}
|
||||
|
||||
// Returns a closed ServerSocket that has an impl whose `create` method has NOT been invoked.
|
||||
static ServerSocket createClosedServerSocketImplUncreated() throws IOException {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.close();
|
||||
return ss;
|
||||
}
|
||||
|
||||
// Returns a closed ServerSocket that has an impl whose `create` method has been invoked.
|
||||
static ServerSocket createClosedServerSocketImplCreated() throws IOException {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.bind(null); // binding causes impl::create to be invoked
|
||||
ss.close();
|
||||
return ss;
|
||||
}
|
||||
|
||||
// Returns a closed ServerSocket created from a ServerSocketChannel's adapter.
|
||||
static ServerSocket createClosedServerSocketFromAdapter() throws IOException {
|
||||
ServerSocketChannel ssc = ServerSocketChannel.open();
|
||||
ssc.close();
|
||||
return ssc.socket();
|
||||
}
|
||||
|
||||
// Returns a closed unbound DatagramSocket.
|
||||
static DatagramSocket createClosedUnboundDatagramSocket() throws IOException {
|
||||
DatagramSocket ds = new DatagramSocket(null);
|
||||
assert ds.isBound() == false;
|
||||
ds.close();
|
||||
return ds;
|
||||
}
|
||||
|
||||
// Returns a closed bound DatagramSocket.
|
||||
static DatagramSocket createClosedBoundDatagramSocket() throws IOException {
|
||||
DatagramSocket ds = new DatagramSocket();
|
||||
assert ds.isBound() == true;
|
||||
ds.close();
|
||||
return ds;
|
||||
}
|
||||
|
||||
// Returns a closed DatagramSocket that created from a DatagramChannel's adapter.
|
||||
static DatagramSocket createClosedDatagramSocketFromAdapter() throws IOException {
|
||||
DatagramChannel dc = DatagramChannel.open();
|
||||
dc.close();
|
||||
return dc.socket();
|
||||
}
|
||||
|
||||
// Returns a closed unbound MulticastSocket.
|
||||
static MulticastSocket createClosedUnboundMulticastSocket() throws IOException {
|
||||
MulticastSocket ms = new MulticastSocket(null);
|
||||
assert ms.isBound() == false;
|
||||
ms.close();
|
||||
return ms;
|
||||
}
|
||||
|
||||
// Returns a closed bound MulticastSocket.
|
||||
static MulticastSocket createClosedBoundMulticastSocket() throws IOException {
|
||||
MulticastSocket ms = new MulticastSocket();
|
||||
assert ms.isBound() == true;
|
||||
ms.close();
|
||||
return ms;
|
||||
}
|
||||
}
|
||||
229
test/jdk/java/net/SocketOption/CachedImplOptions.java
Normal file
229
test/jdk/java/net/SocketOption/CachedImplOptions.java
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (c) 2020, 2025, 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
|
||||
* @bug 8241988
|
||||
* @summary Checks that the caching of options does not affect other impls
|
||||
* @run testng/othervm CachedImplOptions
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true CachedImplOptions
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.DatagramSocketImpl;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
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.*;
|
||||
|
||||
public class CachedImplOptions {
|
||||
|
||||
@Test
|
||||
public void testDatagramSocket() throws IOException {
|
||||
try (var impl = new DatagramSocket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
}
|
||||
try (var impl = new DatagramSocket(new FooDatagramSocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(FooDatagramSocketImpl.FOO_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(FooDatagramSocketImpl.FOO_OPTION));
|
||||
}
|
||||
try (var impl = new DatagramSocket(new BarDatagramSocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(BarDatagramSocketImpl.BAR_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(BarDatagramSocketImpl.BAR_OPTION));
|
||||
}
|
||||
try (var impl = new DatagramSocket(new BazDatagramSocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(BazDatagramSocketImpl.BAZ_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(BazDatagramSocketImpl.BAZ_OPTION));
|
||||
}
|
||||
try (var impl = new DatagramSocket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMulticastSocket() throws IOException {
|
||||
try (var impl = new MulticastSocket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
}
|
||||
|
||||
// Use the factory to inject an alternative impl
|
||||
DatagramSocket.setDatagramSocketImplFactory(() -> new FooDatagramSocketImpl());
|
||||
|
||||
try (var impl = new MulticastSocket()) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(FooDatagramSocketImpl.FOO_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(FooDatagramSocketImpl.FOO_OPTION));
|
||||
}
|
||||
}
|
||||
|
||||
static class FooDatagramSocketImpl extends AbstractDatagramSocketImpl {
|
||||
public static final SocketOption<Boolean> FOO_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "FOO_OPTION"; }
|
||||
@Override public Class<Boolean> type() { return Boolean.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(FOO_OPTION); }
|
||||
}
|
||||
|
||||
static class BarDatagramSocketImpl extends AbstractDatagramSocketImpl {
|
||||
public static final SocketOption<Integer> BAR_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "BAR_OPTION"; }
|
||||
@Override public Class<Integer> type() { return Integer.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(BAR_OPTION); }
|
||||
}
|
||||
|
||||
static class BazDatagramSocketImpl extends AbstractDatagramSocketImpl {
|
||||
public static final SocketOption<Long> BAZ_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "BAZ_OPTION"; }
|
||||
@Override public Class<Long> type() { return Long.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(BAZ_OPTION); }
|
||||
}
|
||||
|
||||
static abstract class AbstractDatagramSocketImpl extends DatagramSocketImpl {
|
||||
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return null; }
|
||||
@Override protected void create() throws SocketException { }
|
||||
@Override protected void bind(int lport, InetAddress laddr){ }
|
||||
@Override protected void send(DatagramPacket p) { }
|
||||
@Override protected int peek(InetAddress i) { return 0; }
|
||||
@Override protected int peekData(DatagramPacket p) { return 0; }
|
||||
@Override protected void receive(DatagramPacket p) { }
|
||||
@Override protected void setTimeToLive(int ttl) { }
|
||||
@Override protected int getTimeToLive() { return 0; }
|
||||
@Override protected void join(InetAddress inetaddr) { }
|
||||
@Override protected void leave(InetAddress inetaddr) { }
|
||||
@Override protected void joinGroup(SocketAddress x, NetworkInterface y) { }
|
||||
@Override protected void leaveGroup(SocketAddress x, NetworkInterface y) { }
|
||||
@Override protected void close() { }
|
||||
@Override public void setOption(int optID, Object value) { }
|
||||
@Override public Object getOption(int optID) { return null; }
|
||||
}
|
||||
|
||||
// -- socket
|
||||
|
||||
@Test
|
||||
public void testSocket() throws IOException {
|
||||
try (var impl = new Socket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
}
|
||||
try (var impl = new Socket(new LarrySocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(LarrySocketImpl.LARRY_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(LarrySocketImpl.LARRY_OPTION));
|
||||
}
|
||||
try (var impl = new Socket(new CurlySocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(CurlySocketImpl.CURLY_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(CurlySocketImpl.CURLY_OPTION));
|
||||
}
|
||||
try (var impl = new Socket(new MoeSocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(MoeSocketImpl.MOE_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(MoeSocketImpl.MOE_OPTION));
|
||||
}
|
||||
try (var impl = new Socket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_SNDBUF));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerSocket() throws IOException {
|
||||
try (var impl = new ServerSocket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_RCVBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_RCVBUF));
|
||||
}
|
||||
try (var impl = new ServerSocket(new LarrySocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(LarrySocketImpl.LARRY_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(LarrySocketImpl.LARRY_OPTION));
|
||||
}
|
||||
try (var impl = new ServerSocket(new CurlySocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(CurlySocketImpl.CURLY_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(CurlySocketImpl.CURLY_OPTION));
|
||||
}
|
||||
try (var impl = new ServerSocket(new MoeSocketImpl()) {}) {
|
||||
assertEquals(impl.supportedOptions(), Set.of(MoeSocketImpl.MOE_OPTION));
|
||||
assertEquals(impl.supportedOptions(), Set.of(MoeSocketImpl.MOE_OPTION));
|
||||
}
|
||||
try (var impl = new ServerSocket()) {
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_RCVBUF));
|
||||
assertTrue(impl.supportedOptions().contains(StandardSocketOptions.SO_RCVBUF));
|
||||
}
|
||||
}
|
||||
|
||||
static class LarrySocketImpl extends AbstractSocketImpl {
|
||||
public static final SocketOption<Boolean> LARRY_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "LARRY_OPTION"; }
|
||||
@Override public Class<Boolean> type() { return Boolean.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(LARRY_OPTION); }
|
||||
}
|
||||
|
||||
static class CurlySocketImpl extends AbstractSocketImpl {
|
||||
public static final SocketOption<Integer> CURLY_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "CURLY_OPTION"; }
|
||||
@Override public Class<Integer> type() { return Integer.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(CURLY_OPTION); }
|
||||
}
|
||||
|
||||
static class MoeSocketImpl extends AbstractSocketImpl {
|
||||
public static final SocketOption<Long> MOE_OPTION = new SocketOption<>() {
|
||||
@Override public String name() { return "MOE_OPTION"; }
|
||||
@Override public Class<Long> type() { return Long.class; }
|
||||
};
|
||||
@Override public Set<SocketOption<?>> supportedOptions() { return Set.of(MOE_OPTION); }
|
||||
}
|
||||
|
||||
static abstract class AbstractSocketImpl extends SocketImpl {
|
||||
|
||||
@Override protected void create(boolean stream) { }
|
||||
@Override protected void connect(String host, int port) { }
|
||||
@Override protected void connect(InetAddress address, int port) { }
|
||||
@Override protected void connect(SocketAddress address, int timeout) { }
|
||||
@Override protected void bind(InetAddress host, int port) { }
|
||||
@Override protected void listen(int backlog) { }
|
||||
@Override protected void accept(SocketImpl s) { }
|
||||
@Override protected InputStream getInputStream() { return null; }
|
||||
@Override protected OutputStream getOutputStream() { return null; }
|
||||
@Override protected int available() { return 0; }
|
||||
@Override protected void close() { }
|
||||
@Override protected void sendUrgentData(int data) { }
|
||||
@Override public void setOption(int optID, Object value) { }
|
||||
@Override public Object getOption(int optID) { return null; }
|
||||
}
|
||||
}
|
||||
185
test/jdk/java/net/SocketOption/ImmutableOptions.java
Normal file
185
test/jdk/java/net/SocketOption/ImmutableOptions.java
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2025, 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
|
||||
* @bug 8148609
|
||||
* @library /test/lib
|
||||
* @summary Assert that the set of socket options are immutable
|
||||
* @run testng/othervm ImmutableOptions
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true ImmutableOptions
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.*;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ImmutableOptions {
|
||||
|
||||
@BeforeTest
|
||||
void setupServerSocketFactory() throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
ServerSocket.setSocketFactory(new ServerSocketImplFactory());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void socketThrows() throws IOException {
|
||||
CustomSocketImpl impl = new CustomSocketImpl();
|
||||
Socket socket = new CustomSocket(impl);
|
||||
socket.supportedOptions().clear();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void socketImplThrows() throws IOException {
|
||||
CustomSocketImpl impl = new CustomSocketImpl();
|
||||
impl.supportedOptions().clear();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void serverSocketThrows() throws IOException {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ss.supportedOptions().clear();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void serverSocketImplThrows() throws IOException {
|
||||
ServerSocket ss = new ServerSocket();
|
||||
ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void datagramSocketThrows() throws IOException {
|
||||
CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
|
||||
DatagramSocket socket = new CustomDatagramSocket(impl);
|
||||
socket.supportedOptions().clear();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
public void datagramSocketImplThrows() throws IOException {
|
||||
CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl();
|
||||
impl.supportedOptions().clear();
|
||||
}
|
||||
|
||||
|
||||
// Socket descendants
|
||||
static class CustomSocket extends Socket {
|
||||
public CustomSocket(SocketImpl impl) throws IOException {
|
||||
super(impl);
|
||||
}
|
||||
}
|
||||
|
||||
static class CustomDatagramSocket extends DatagramSocket {
|
||||
public CustomDatagramSocket(DatagramSocketImpl impl) {
|
||||
super(impl);
|
||||
}
|
||||
}
|
||||
|
||||
static class ServerSocketImplFactory implements SocketImplFactory {
|
||||
static volatile CustomSocketImpl mostRecentlyCreated;
|
||||
|
||||
@Override public SocketImpl createSocketImpl() {
|
||||
return mostRecentlyCreated = new CustomSocketImpl();
|
||||
}
|
||||
}
|
||||
|
||||
// Custom impl's
|
||||
static class CustomSocketImpl extends SocketImpl {
|
||||
// The only method interesting to this test.
|
||||
@Override public Set<SocketOption<?>> supportedOptions() {
|
||||
return super.supportedOptions();
|
||||
}
|
||||
|
||||
public void create(boolean stream) throws IOException { }
|
||||
|
||||
public void connect(String host, int port) throws IOException { }
|
||||
|
||||
public void connect(InetAddress addr, int port) throws IOException { }
|
||||
|
||||
public void connect(SocketAddress addr, int timeout) throws IOException { }
|
||||
|
||||
public void bind(InetAddress host, int port) throws IOException { }
|
||||
|
||||
public void listen(int backlog) throws IOException { }
|
||||
|
||||
public void accept(SocketImpl s) throws IOException { }
|
||||
|
||||
public InputStream getInputStream() throws IOException { return null; }
|
||||
|
||||
public OutputStream getOutputStream() throws IOException { return null; }
|
||||
|
||||
public int available() throws IOException { return 0; }
|
||||
|
||||
public void close() throws IOException { }
|
||||
|
||||
public void sendUrgentData(int data) throws IOException { }
|
||||
|
||||
public Object getOption(int i) throws SocketException { return null; }
|
||||
|
||||
public void setOption(int i, Object o) throws SocketException { }
|
||||
}
|
||||
|
||||
static class CustomDatagramSocketImpl extends DatagramSocketImpl {
|
||||
// The only method interesting to this test.
|
||||
@Override public Set<SocketOption<?>> supportedOptions() {
|
||||
return super.supportedOptions();
|
||||
}
|
||||
|
||||
protected void create() throws SocketException { }
|
||||
|
||||
protected void bind(int lport, InetAddress laddr) throws SocketException { }
|
||||
|
||||
protected void send(DatagramPacket p) throws IOException { }
|
||||
|
||||
protected int peek(InetAddress i) throws IOException { return 0; }
|
||||
|
||||
protected int peekData(DatagramPacket p) throws IOException { return 0; }
|
||||
|
||||
protected void receive(DatagramPacket p) throws IOException { }
|
||||
|
||||
protected void setTimeToLive(int ttl) throws IOException { }
|
||||
|
||||
protected int getTimeToLive() throws IOException { return 0; }
|
||||
|
||||
protected void join(InetAddress inetaddr) throws IOException { }
|
||||
|
||||
protected void leave(InetAddress inetaddr) throws IOException { }
|
||||
|
||||
protected void joinGroup(SocketAddress x, NetworkInterface y)
|
||||
throws IOException { }
|
||||
|
||||
protected void leaveGroup(SocketAddress x, NetworkInterface y)
|
||||
throws IOException { }
|
||||
|
||||
protected void close() { }
|
||||
|
||||
public void setOption(int optID, Object value) throws SocketException { }
|
||||
|
||||
public Object getOption(int optID) throws SocketException { return null; }
|
||||
}
|
||||
}
|
||||
62
test/jdk/java/net/SocketOption/MinimumRcvBufferSize.java
Normal file
62
test/jdk/java/net/SocketOption/MinimumRcvBufferSize.java
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2018, 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
|
||||
* @library /test/lib
|
||||
* @bug 8170920
|
||||
* @run main MinimumRcvBufferSize
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true MinimumRcvBufferSize
|
||||
*/
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.net.*;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class MinimumRcvBufferSize {
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
boolean error = false;
|
||||
ServerSocketChannel channel = ServerSocketChannel.open();
|
||||
int before = channel.getOption(StandardSocketOptions.SO_RCVBUF);
|
||||
channel.setOption(StandardSocketOptions.SO_RCVBUF, Integer.MAX_VALUE);
|
||||
int after = channel.getOption(StandardSocketOptions.SO_RCVBUF);
|
||||
if (before > after) {
|
||||
System.err.println("Test failed: SO_RCVBUF");
|
||||
error = true;
|
||||
}
|
||||
|
||||
SocketChannel channel1 = SocketChannel.open();
|
||||
before = channel1.getOption(StandardSocketOptions.SO_SNDBUF);
|
||||
channel1.setOption(StandardSocketOptions.SO_SNDBUF, Integer.MAX_VALUE);
|
||||
after = channel1.getOption(StandardSocketOptions.SO_SNDBUF);
|
||||
if (before > after) {
|
||||
System.err.println("Test failed: SO_SNDBUF");
|
||||
error = true;
|
||||
}
|
||||
if (error)
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
331
test/jdk/java/net/SocketOption/NullsAndBadValues.java
Normal file
331
test/jdk/java/net/SocketOption/NullsAndBadValues.java
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2021, 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
|
||||
* @bug 8224477
|
||||
* @summary Basic test for NPE, UOE, and IAE for get/setOption
|
||||
* @run testng NullsAndBadValues
|
||||
* @run testng/othervm -Dsun.net.useExclusiveBind=false NullsAndBadValues
|
||||
*/
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketOption;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static java.lang.Boolean.*;
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
public class NullsAndBadValues {
|
||||
|
||||
static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||
static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
||||
static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
|
||||
|
||||
@Test
|
||||
public void nulls() throws Exception {
|
||||
try (Socket s = new Socket()) {
|
||||
expectThrows(NPE, () -> s.setOption(null, null));
|
||||
expectThrows(NPE, () -> s.setOption(null, ""));
|
||||
expectThrows(NPE, () -> s.setOption(null, 1));
|
||||
expectThrows(NPE, () -> s.getOption(null));
|
||||
}
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
expectThrows(NPE, () -> ss.setOption(null, null));
|
||||
expectThrows(NPE, () -> ss.setOption(null, ""));
|
||||
expectThrows(NPE, () -> ss.setOption(null, 1));
|
||||
expectThrows(NPE, () -> ss.getOption(null));
|
||||
}
|
||||
try (DatagramSocket ds = new DatagramSocket()) {
|
||||
expectThrows(NPE, () -> ds.setOption(null, null));
|
||||
expectThrows(NPE, () -> ds.setOption(null, ""));
|
||||
expectThrows(NPE, () -> ds.setOption(null, 1));
|
||||
expectThrows(NPE, () -> ds.getOption(null));
|
||||
}
|
||||
try (MulticastSocket ms = new MulticastSocket()) {
|
||||
expectThrows(NPE, () -> ms.setOption(null, null));
|
||||
expectThrows(NPE, () -> ms.setOption(null, ""));
|
||||
expectThrows(NPE, () -> ms.setOption(null, 1));
|
||||
expectThrows(NPE, () -> ms.getOption(null));
|
||||
}
|
||||
try (Socket sa = SocketChannel.open().socket()) {
|
||||
expectThrows(NPE, () -> sa.setOption(null, null));
|
||||
expectThrows(NPE, () -> sa.setOption(null, ""));
|
||||
expectThrows(NPE, () -> sa.setOption(null, 1));
|
||||
expectThrows(NPE, () -> sa.getOption(null));
|
||||
}
|
||||
try (ServerSocket ssa = ServerSocketChannel.open().socket()) {
|
||||
expectThrows(NPE, () -> ssa.setOption(null, null));
|
||||
expectThrows(NPE, () -> ssa.setOption(null, ""));
|
||||
expectThrows(NPE, () -> ssa.setOption(null, 1));
|
||||
expectThrows(NPE, () -> ssa.getOption(null));
|
||||
}
|
||||
try (DatagramSocket dsa = DatagramChannel.open().socket()) {
|
||||
expectThrows(NPE, () -> dsa.setOption(null, null));
|
||||
expectThrows(NPE, () -> dsa.setOption(null, ""));
|
||||
expectThrows(NPE, () -> dsa.setOption(null, 1));
|
||||
expectThrows(NPE, () -> dsa.getOption(null));
|
||||
}
|
||||
}
|
||||
|
||||
static final SocketOption<Boolean> FAKE_SOCK_OPT = new SocketOption<>() {
|
||||
@Override public String name() { return "FAKE_SOCK_OPT"; }
|
||||
@Override public Class<Boolean> type() { return Boolean.class; }
|
||||
};
|
||||
|
||||
static final SocketOption RAW_SOCK_OPT = new SocketOption() {
|
||||
@Override public String name() { return "RAW_SOCK_OPT"; }
|
||||
@Override public Class type() { return Boolean.class; }
|
||||
};
|
||||
|
||||
@Test
|
||||
public void uoe() throws Exception {
|
||||
try (Socket s = new Socket()) {
|
||||
expectThrows(UOE, () -> s.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> s.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> s.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> s.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> s.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> s.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> s.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
expectThrows(UOE, () -> ss.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> ss.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> ss.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> ss.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> ss.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> ss.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> ss.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (DatagramSocket ds = new DatagramSocket()) {
|
||||
expectThrows(UOE, () -> ds.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> ds.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> ds.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> ds.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> ds.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> ds.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> ds.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (MulticastSocket ms = new MulticastSocket()) {
|
||||
expectThrows(UOE, () -> ms.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> ms.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> ms.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> ms.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> ms.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> ms.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> ms.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (Socket sa = SocketChannel.open().socket()) {
|
||||
expectThrows(UOE, () -> sa.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> sa.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> sa.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> sa.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> sa.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> sa.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> sa.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (ServerSocket ssa = ServerSocketChannel.open().socket()) {
|
||||
expectThrows(UOE, () -> ssa.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> ssa.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> ssa.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> ssa.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> ssa.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> ssa.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> ssa.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
try (DatagramSocket dsa = DatagramChannel.open().socket()) {
|
||||
expectThrows(UOE, () -> dsa.setOption(FAKE_SOCK_OPT, null));
|
||||
expectThrows(UOE, () -> dsa.setOption(FAKE_SOCK_OPT, TRUE));
|
||||
expectThrows(UOE, () -> dsa.setOption(FAKE_SOCK_OPT, FALSE));
|
||||
expectThrows(UOE, () -> dsa.setOption(RAW_SOCK_OPT, ""));
|
||||
expectThrows(UOE, () -> dsa.setOption(RAW_SOCK_OPT, 1));
|
||||
expectThrows(UOE, () -> dsa.getOption(FAKE_SOCK_OPT));
|
||||
expectThrows(UOE, () -> dsa.getOption(RAW_SOCK_OPT));
|
||||
}
|
||||
}
|
||||
|
||||
static Map<SocketOption<?>,List<Object>> BAD_OPTION_VALUES = badOptionValues();
|
||||
|
||||
static Map<SocketOption<?>,List<Object>> badOptionValues() {
|
||||
Map<SocketOption<?>,List<Object>> map = new HashMap<>();
|
||||
map.put(IP_MULTICAST_IF, listOf(null) );
|
||||
map.put(IP_MULTICAST_LOOP, listOf(null) );
|
||||
map.put(IP_MULTICAST_TTL, listOf(null, -1, 256));
|
||||
map.put(IP_TOS, listOf(null, -1, 256));
|
||||
map.put(SO_BROADCAST, listOf(null) );
|
||||
map.put(SO_KEEPALIVE, listOf(null) );
|
||||
map.put(SO_LINGER, listOf(null) );
|
||||
map.put(SO_RCVBUF, listOf(null, -1) );
|
||||
map.put(SO_REUSEADDR, listOf(null) );
|
||||
map.put(SO_REUSEPORT, listOf(null) );
|
||||
map.put(SO_SNDBUF, listOf(null, -1) );
|
||||
map.put(TCP_NODELAY, listOf(null) );
|
||||
// extended options, not in the map, will get a null value
|
||||
return map;
|
||||
}
|
||||
|
||||
// -- Socket
|
||||
|
||||
@DataProvider(name = "socketBadOptionValues")
|
||||
public Object[][] socketBadOptionValues() throws Exception {
|
||||
try (Socket s = new Socket()) {
|
||||
return s.supportedOptions().stream()
|
||||
.flatMap(NullsAndBadValues::socketOptionToBadValues)
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "socketBadOptionValues")
|
||||
public <T> void socket(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (Socket s = new Socket()) {
|
||||
expectThrows(IAE, () -> s.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "socketBadOptionValues")
|
||||
public <T> void socketAdapter(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (Socket s = SocketChannel.open().socket()) {
|
||||
expectThrows(IAE, () -> s.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
// -- ServerSocket
|
||||
|
||||
@DataProvider(name = "serverSocketBadOptionValues")
|
||||
public Object[][] serverSocketBadOptionValues() throws Exception {
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
return ss.supportedOptions().stream()
|
||||
.flatMap(NullsAndBadValues::socketOptionToBadValues)
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "serverSocketBadOptionValues")
|
||||
public <T> void serverSocket(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
expectThrows(IAE, () -> ss.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "serverSocketBadOptionValues")
|
||||
public <T> void serverSocketAdapter(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
if (option == IP_TOS)
|
||||
return; // SSC does not support IP_TOS
|
||||
|
||||
try (ServerSocket ss = ServerSocketChannel.open().socket()) {
|
||||
expectThrows(IAE, () -> ss.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
// -- DatagramSocket
|
||||
|
||||
@DataProvider(name = "datagramSocketBadOptionValues")
|
||||
public Object[][] datagramSocketBadOptionValues() throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket()) {
|
||||
return ds.supportedOptions().stream()
|
||||
.flatMap(NullsAndBadValues::socketOptionToBadValues)
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "datagramSocketBadOptionValues")
|
||||
public <T> void datagramSocket(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (DatagramSocket ds = new DatagramSocket()) {
|
||||
expectThrows(IAE, () -> ds.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "datagramSocketBadOptionValues")
|
||||
public <T> void datagramSocketAdapter(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (DatagramSocket ds = DatagramChannel.open().socket()) {
|
||||
expectThrows(IAE, () -> ds.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
// -- MulticastSocket
|
||||
|
||||
@DataProvider(name = "multicastSocketBadOptionValues")
|
||||
public Object[][] multicastSocketBadOptionValues() throws Exception {
|
||||
try (MulticastSocket ms = new MulticastSocket()) {
|
||||
return ms.supportedOptions().stream()
|
||||
.flatMap(NullsAndBadValues::socketOptionToBadValues)
|
||||
.toArray(Object[][]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "multicastSocketBadOptionValues")
|
||||
public <T> void multicastSocket(SocketOption<T> option, T value)
|
||||
throws Exception
|
||||
{
|
||||
try (MulticastSocket ms = new MulticastSocket()) {
|
||||
expectThrows(IAE, () -> ms.setOption(option, value));
|
||||
}
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
static List<Object> listOf(Object... objs) {
|
||||
List<Object> l = new ArrayList<>();
|
||||
if (objs == null)
|
||||
l.add(null);
|
||||
else
|
||||
Arrays.stream(objs).forEachOrdered(l::add);
|
||||
return l;
|
||||
}
|
||||
|
||||
static Stream<Object[]> socketOptionToBadValues(SocketOption<?> socketOption) {
|
||||
List<Object> values = BAD_OPTION_VALUES.get(socketOption);
|
||||
if (values == null) {
|
||||
Object[][] a = new Object[][] { new Object[] { socketOption, null } };
|
||||
return Stream.of(a);
|
||||
}
|
||||
return values.stream()
|
||||
.flatMap(v -> Stream.of(new Object[][] { new Object[] { socketOption, v } }) );
|
||||
}
|
||||
}
|
||||
351
test/jdk/java/net/SocketOption/OptionsTest.java
Normal file
351
test/jdk/java/net/SocketOption/OptionsTest.java
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8036979 8072384 8044773 8225214 8233296 8234083
|
||||
* @library /test/lib
|
||||
* @requires !vm.graal.enabled
|
||||
* @run main/othervm -Xcheck:jni OptionsTest
|
||||
* @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
|
||||
* @run main/othervm --limit-modules=java.base OptionsTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
public class OptionsTest {
|
||||
|
||||
static class Test<T> {
|
||||
final SocketOption<T> option;
|
||||
final T value;
|
||||
Test(SocketOption<T> option, T value) {
|
||||
this.option = option;
|
||||
this.value = value;
|
||||
}
|
||||
static <T> Test<T> create(SocketOption<T> option, T value) {
|
||||
return new Test<T>(option, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The tests set the option using the new API, read back the set value
|
||||
// which could be different, and then use the legacy get API to check
|
||||
// these values are the same
|
||||
|
||||
static Test<?>[] socketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(-1)),
|
||||
Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(0)),
|
||||
Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test<?>[] serverSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test<?>[] datagramSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
|
||||
Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.TRUE),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),
|
||||
Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound
|
||||
};
|
||||
|
||||
static Test<?>[] multicastSocketTests = new Test<?>[] {
|
||||
Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.FALSE),
|
||||
Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.TRUE),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(0)), // lower-bound
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(255)), //upper-bound
|
||||
Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE)
|
||||
};
|
||||
|
||||
static NetworkInterface getNetworkInterface() {
|
||||
try {
|
||||
NetworkConfiguration nc = NetworkConfiguration.probe();
|
||||
return nc.multicastInterfaces(true).findAny().orElse(null);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean okayToTest(Socket s, SocketOption<?> option) {
|
||||
if (option == StandardSocketOptions.SO_REUSEPORT) {
|
||||
// skip SO_REUSEPORT if option is not supported
|
||||
return s.supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
}
|
||||
if (option == StandardSocketOptions.IP_TOS && s.isConnected()) {
|
||||
// skip IP_TOS if connected
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static <T> void testEqual(SocketOption<T> option, T value1, T value2) {
|
||||
if (!value1.equals(value2)) {
|
||||
throw new RuntimeException("Test of " + option.name() + " failed: "
|
||||
+ value1 + " != " + value2);
|
||||
}
|
||||
}
|
||||
|
||||
static <T> void test(Socket s, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
s.setOption(option, test.value);
|
||||
T value1 = s.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(Socket.class, s, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
static <T> void test(ServerSocket ss, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
ss.setOption(option, test.value);
|
||||
T value1 = ss.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(ServerSocket.class, ss, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
static <T> void test(DatagramSocket ds, Test<T> test) throws Exception {
|
||||
SocketOption<T> option = test.option;
|
||||
ds.setOption(option, test.value);
|
||||
T value1 = ds.getOption(test.option);
|
||||
T value2 = (T) legacyGetOption(ds.getClass(), ds, test.option);
|
||||
testEqual(option, value1, value2);
|
||||
}
|
||||
|
||||
// Tests default and negative values of SO_LINGER. All negative values should
|
||||
// retrieve as -1.
|
||||
static void testSoLingerValues() throws Exception {
|
||||
try (Socket s = new Socket()) {
|
||||
// retrieve without set
|
||||
int defaultValue = s.getOption(StandardSocketOptions.SO_LINGER);
|
||||
testEqual(StandardSocketOptions.SO_LINGER, -1, defaultValue);
|
||||
|
||||
for (int v : List.of(-1, -2, -100, -65534, -65535, -65536, -100000)) {
|
||||
System.out.println("Testing SO_LINGER with:" + v);
|
||||
s.setOption(StandardSocketOptions.SO_LINGER, v);
|
||||
int value = s.getOption(StandardSocketOptions.SO_LINGER);
|
||||
testEqual(StandardSocketOptions.SO_LINGER, -1, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
static void doSocketTests() throws Exception {
|
||||
// unconnected socket
|
||||
try (Socket s = new Socket()) {
|
||||
for (Test<?> test : socketTests) {
|
||||
if (okayToTest(s, test.option)) {
|
||||
test(s, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// connected socket
|
||||
try (ServerSocket ss = new ServerSocket()) {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
ss.bind(new InetSocketAddress(loopback, 0));
|
||||
try (Socket s1 = new Socket()) {
|
||||
s1.connect(ss.getLocalSocketAddress());
|
||||
try (Socket s2 = ss.accept()) {
|
||||
for (Test<?> test : socketTests) {
|
||||
if (okayToTest(s1, test.option)) {
|
||||
test(s1, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testSoLingerValues();
|
||||
}
|
||||
|
||||
static void doServerSocketTests() throws Exception {
|
||||
try (ServerSocket ss = new ServerSocket(0)) {
|
||||
Set<SocketOption<?>> options = ss.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (Test<?> test : serverSocketTests) {
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
test(ss, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doDatagramSocketTests() throws Exception {
|
||||
try (DatagramSocket ds = new DatagramSocket(0)) {
|
||||
Set<SocketOption<?>> options = ds.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
for (Test<?> test : datagramSocketTests) {
|
||||
if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
|
||||
test(ds, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doMulticastSocketTests() throws Exception {
|
||||
try (MulticastSocket ms = new MulticastSocket(0)) {
|
||||
for (Test<?> test : multicastSocketTests) {
|
||||
test(ms, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object legacyGetOption(Class<?> type, Object s, Object option) throws Exception {
|
||||
if (type.equals(Socket.class)) {
|
||||
Socket socket = (Socket)s;
|
||||
Set<SocketOption<?>> options = socket.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {
|
||||
return Boolean.valueOf(socket.getKeepAlive());
|
||||
} else if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
||||
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
||||
} else if (option.equals(StandardSocketOptions.SO_LINGER)) {
|
||||
return Integer.valueOf(socket.getSoLinger());
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {
|
||||
return Boolean.valueOf(socket.getTcpNoDelay());
|
||||
} else {
|
||||
throw new RuntimeException("unexpected socket option");
|
||||
}
|
||||
} else if (type.equals(ServerSocket.class)) {
|
||||
ServerSocket socket = (ServerSocket)s;
|
||||
Set<SocketOption<?>> options = socket.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
||||
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return getServerSocketTrafficClass(socket);
|
||||
} else {
|
||||
throw new RuntimeException("unexpected socket option");
|
||||
}
|
||||
} else if (type.equals(DatagramSocket.class)) {
|
||||
DatagramSocket socket = (DatagramSocket)s;
|
||||
Set<SocketOption<?>> options = socket.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.SO_BROADCAST)) {
|
||||
return Boolean.valueOf(socket.getBroadcast());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
||||
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else {
|
||||
throw new RuntimeException("unexpected socket option");
|
||||
}
|
||||
|
||||
} else if (type.equals(MulticastSocket.class)) {
|
||||
MulticastSocket socket = (MulticastSocket)s;
|
||||
Set<SocketOption<?>> options = socket.supportedOptions();
|
||||
boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
|
||||
|
||||
if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
|
||||
return Integer.valueOf(socket.getSendBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
|
||||
return Integer.valueOf(socket.getReceiveBufferSize());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
|
||||
return Boolean.valueOf(socket.getReuseAddress());
|
||||
} else if (option.equals(StandardSocketOptions.SO_BROADCAST)) {
|
||||
return Boolean.valueOf(socket.getBroadcast());
|
||||
} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
|
||||
return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
|
||||
} else if (option.equals(StandardSocketOptions.IP_TOS)) {
|
||||
return Integer.valueOf(socket.getTrafficClass());
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {
|
||||
return socket.getNetworkInterface();
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) {
|
||||
return Integer.valueOf(socket.getTimeToLive());
|
||||
} else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) {
|
||||
return !Boolean.valueOf(socket.getLoopbackMode());
|
||||
} else {
|
||||
throw new RuntimeException("unexpected socket option");
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("unexpected socket type");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
doSocketTests();
|
||||
doServerSocketTests();
|
||||
doDatagramSocketTests();
|
||||
doMulticastSocketTests();
|
||||
}
|
||||
|
||||
// Reflectively access jdk.net.Sockets.getOption so that the test can run
|
||||
// without the jdk.net module.
|
||||
static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception {
|
||||
try {
|
||||
Class<?> c = Class.forName("jdk.net.Sockets");
|
||||
Method m = c.getMethod("getOption", ServerSocket.class, SocketOption.class);
|
||||
return m.invoke(null, ss, StandardSocketOptions.IP_TOS);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Ok, jdk.net module not present, just fall back
|
||||
System.out.println("jdk.net module not present, falling back.");
|
||||
return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
174
test/jdk/java/net/SocketOption/RequiredOptions.java
Normal file
174
test/jdk/java/net/SocketOption/RequiredOptions.java
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2019, 2021, 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.DatagramSocket;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketOption;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.NetworkChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import static java.net.StandardSocketOptions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8235141
|
||||
* @summary verifies that our implementation supports the set
|
||||
* of SocketOptions that are required by the API documentation.
|
||||
* @run testng/othervm RequiredOptions
|
||||
*/
|
||||
public class RequiredOptions {
|
||||
|
||||
static final Set<SocketOption<?>> DATAGRAM_OPTIONS =
|
||||
Set.of(SO_BROADCAST, SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, IP_TOS);
|
||||
static final Set<SocketOption<?>> MULTICAST_OPTIONS =
|
||||
concat(DATAGRAM_OPTIONS, Set.of(IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL));
|
||||
static final Set<SocketOption<?>> SOCKET_OPTIONS =
|
||||
Set.of(SO_KEEPALIVE, SO_LINGER, SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, TCP_NODELAY);
|
||||
static final Set<SocketOption<?>> SERVER_OPTIONS =
|
||||
Set.of(SO_RCVBUF, SO_REUSEADDR);
|
||||
|
||||
static Set<SocketOption<?>> concat(Set<SocketOption<?>> ...options) {
|
||||
return Set.of(Stream.of(options).flatMap(Set::stream).distinct().toArray(SocketOption[]::new));
|
||||
}
|
||||
|
||||
@DataProvider(name = "sockets")
|
||||
static Object[][] provider() throws IOException {
|
||||
return new Object[][] {
|
||||
// UDP
|
||||
{ Configurable.of(new DatagramSocket(null)), DATAGRAM_OPTIONS },
|
||||
{ Configurable.of(new MulticastSocket(null)), MULTICAST_OPTIONS },
|
||||
// TCP
|
||||
{ Configurable.of(new Socket()), SOCKET_OPTIONS },
|
||||
{ Configurable.of(new ServerSocket()), SERVER_OPTIONS },
|
||||
// Adaptors
|
||||
{ Configurable.of(DatagramChannel.open().socket()), MULTICAST_OPTIONS },
|
||||
{ Configurable.of(SocketChannel.open().socket()), SOCKET_OPTIONS },
|
||||
{ Configurable.of(ServerSocketChannel.open().socket()), SERVER_OPTIONS },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "sockets")
|
||||
public <R, E extends Exception>
|
||||
void test(Configurable<R,E> socket, Set<SocketOption<?>> options) throws E {
|
||||
try (var s = socket) {
|
||||
var impl = socket.socket().getClass();
|
||||
System.out.println("Testing " + impl + " with " + options);
|
||||
Set<SocketOption<?>> supported = socket.supportedOptions();
|
||||
if (!supported.containsAll(options)) {
|
||||
for (var option : options) {
|
||||
if (!supported.contains(option)) {
|
||||
System.err.println("Option " + option + " not supported by " + impl);
|
||||
}
|
||||
}
|
||||
throw new AssertionError("Not all documented options are supported by " + impl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static interface Configurable<R, E extends Exception> extends AutoCloseable {
|
||||
<T> R setOption(SocketOption<T> name, T value) throws E;
|
||||
<T> T getOption(SocketOption<T> name) throws E;
|
||||
Set<SocketOption<?>> supportedOptions() throws E;
|
||||
R socket();
|
||||
void close() throws E;
|
||||
|
||||
static Configurable<DatagramSocket, IOException> of(DatagramSocket socket) {
|
||||
return new ConfigurableImpl<>(socket, socket::setOption,
|
||||
socket::getOption, socket::supportedOptions, socket::close);
|
||||
}
|
||||
static Configurable<Socket, IOException> of(Socket socket) {
|
||||
return new ConfigurableImpl<>(socket, socket::setOption,
|
||||
socket::getOption, socket::supportedOptions, socket::close);
|
||||
}
|
||||
static Configurable<ServerSocket, IOException> of(ServerSocket socket) {
|
||||
return new ConfigurableImpl<>(socket, socket::setOption,
|
||||
socket::getOption, socket::supportedOptions, socket::close);
|
||||
}
|
||||
}
|
||||
|
||||
static final class ConfigurableImpl<R, E extends Exception> implements Configurable<R, E> {
|
||||
@FunctionalInterface
|
||||
interface SetOption<R, E extends Exception> {
|
||||
<T> R setOption(SocketOption<T> name, T value) throws E;
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface GetOption<E extends Exception> {
|
||||
<T> T getOption(SocketOption<T> name) throws E;
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface SupportedOption<E extends Exception> {
|
||||
Set<SocketOption<?>> supportedOptions() throws E;
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface Closer<E extends Exception> {
|
||||
void close() throws E;
|
||||
}
|
||||
|
||||
private final R socket;
|
||||
private final SetOption<R, E> setter;
|
||||
private final GetOption<E> getter;
|
||||
private final SupportedOption<E> support;
|
||||
private final Closer<E> closer;
|
||||
|
||||
public ConfigurableImpl(R socket, SetOption<R, E> setter, GetOption<E> getter,
|
||||
SupportedOption<E> support, Closer<E> closer) {
|
||||
this.socket = socket;
|
||||
this.setter = setter;
|
||||
this.getter = getter;
|
||||
this.support = support;
|
||||
this.closer = closer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> R setOption(SocketOption<T> name, T value) throws E {
|
||||
return setter.setOption(name, value);
|
||||
}
|
||||
@Override
|
||||
public <T> T getOption(SocketOption<T> name) throws E {
|
||||
return getter.getOption(name);
|
||||
}
|
||||
@Override
|
||||
public Set<SocketOption<?>> supportedOptions() throws E {
|
||||
return support.supportedOptions();
|
||||
}
|
||||
@Override
|
||||
public R socket() {
|
||||
return socket;
|
||||
}
|
||||
@Override
|
||||
public void close() throws E {
|
||||
closer.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
86
test/jdk/java/net/SocketOption/SupportedOptionsSet.java
Normal file
86
test/jdk/java/net/SocketOption/SupportedOptionsSet.java
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Set;
|
||||
import static java.lang.System.out;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8143923
|
||||
* @library /test/lib
|
||||
* @summary java.net socket supportedOptions set depends on call order
|
||||
* @run main/othervm SupportedOptionsSet first
|
||||
* @run main/othervm SupportedOptionsSet second
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true SupportedOptionsSet first
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true SupportedOptionsSet second
|
||||
*/
|
||||
|
||||
// Run with othervm as the implementation of the supported options sets, once
|
||||
// calculated, stores them in a private static fields.
|
||||
|
||||
public class SupportedOptionsSet {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
if (args[0].equals("first"))
|
||||
first();
|
||||
else if (args[0].equals("second"))
|
||||
second();
|
||||
}
|
||||
|
||||
static void first() throws IOException {
|
||||
try (Socket s = new Socket();
|
||||
ServerSocket ss = new ServerSocket())
|
||||
{
|
||||
Set<?> first = s.supportedOptions();
|
||||
Set<?> second = ss.supportedOptions();
|
||||
assertNotEqual(first, second,
|
||||
"Socket and ServerSocket should have different options.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Tests with the order of access to supportedOptions reversed. */
|
||||
static void second() throws IOException {
|
||||
try (ServerSocket ss = new ServerSocket();
|
||||
Socket s = new Socket())
|
||||
{
|
||||
Set<?> first = ss.supportedOptions();
|
||||
Set<?> second = s.supportedOptions();
|
||||
assertNotEqual(first, second,
|
||||
"ServerSocket and Socket should have different options.");
|
||||
}
|
||||
}
|
||||
|
||||
static void assertNotEqual(Set<?> s1, Set<?> s2, String message) {
|
||||
if (s1.equals(s2)) {
|
||||
out.println("s1: " + s1);
|
||||
out.println("s2: " + s2);
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
121
test/jdk/java/net/SocketOption/TcpKeepAliveTest.java
Normal file
121
test/jdk/java/net/SocketOption/TcpKeepAliveTest.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2018, 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
|
||||
* @bug 8194298
|
||||
* @summary Add support for per Socket configuration of TCP keepalive
|
||||
* @modules jdk.net
|
||||
* @run main TcpKeepAliveTest
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import jdk.net.ExtendedSocketOptions;
|
||||
|
||||
public class TcpKeepAliveTest {
|
||||
|
||||
private static final int DEFAULT_KEEP_ALIVE_PROBES = 7;
|
||||
private static final int DEFAULT_KEEP_ALIVE_TIME = 1973;
|
||||
private static final int DEFAULT_KEEP_ALIVE_INTVL = 53;
|
||||
|
||||
public static void main(String args[]) throws IOException {
|
||||
var loopback = InetAddress.getLoopbackAddress();
|
||||
try (ServerSocket ss = boundServer(loopback);
|
||||
Socket s = new Socket(loopback, ss.getLocalPort());
|
||||
DatagramSocket ds = new DatagramSocket(0);
|
||||
MulticastSocket mc = new MulticastSocket(0)) {
|
||||
if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
|
||||
ss.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME);
|
||||
if (ss.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME);
|
||||
}
|
||||
}
|
||||
if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
|
||||
ss.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES);
|
||||
if (ss.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES);
|
||||
}
|
||||
}
|
||||
if (ss.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
|
||||
ss.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL);
|
||||
if (ss.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL);
|
||||
}
|
||||
}
|
||||
if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
|
||||
s.setOption(ExtendedSocketOptions.TCP_KEEPIDLE, DEFAULT_KEEP_ALIVE_TIME);
|
||||
if (s.getOption(ExtendedSocketOptions.TCP_KEEPIDLE) != DEFAULT_KEEP_ALIVE_TIME) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPIDLE should have been " + DEFAULT_KEEP_ALIVE_TIME);
|
||||
}
|
||||
}
|
||||
if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
|
||||
s.setOption(ExtendedSocketOptions.TCP_KEEPCOUNT, DEFAULT_KEEP_ALIVE_PROBES);
|
||||
if (s.getOption(ExtendedSocketOptions.TCP_KEEPCOUNT) != DEFAULT_KEEP_ALIVE_PROBES) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPCOUNT should have been " + DEFAULT_KEEP_ALIVE_PROBES);
|
||||
}
|
||||
}
|
||||
if (s.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
|
||||
s.setOption(ExtendedSocketOptions.TCP_KEEPINTERVAL, DEFAULT_KEEP_ALIVE_INTVL);
|
||||
if (s.getOption(ExtendedSocketOptions.TCP_KEEPINTERVAL) != DEFAULT_KEEP_ALIVE_INTVL) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPINTERVAL should have been " + DEFAULT_KEEP_ALIVE_INTVL);
|
||||
}
|
||||
}
|
||||
if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable"
|
||||
+ " for TCP Sockets only.");
|
||||
}
|
||||
if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable"
|
||||
+ " for TCP Sockets only.");
|
||||
}
|
||||
if (ds.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable"
|
||||
+ " for TCP Sockets only.");
|
||||
}
|
||||
if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPCOUNT)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPCOUNT is applicable"
|
||||
+ " for TCP Sockets only");
|
||||
}
|
||||
if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPIDLE)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPIDLE is applicable"
|
||||
+ " for TCP Sockets only");
|
||||
}
|
||||
if (mc.supportedOptions().contains(ExtendedSocketOptions.TCP_KEEPINTERVAL)) {
|
||||
throw new RuntimeException("Test failed, TCP_KEEPINTERVAL is applicable"
|
||||
+ " for TCP Sockets only");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ServerSocket boundServer(InetAddress address) throws IOException {
|
||||
var socketAddress = new InetSocketAddress(address, 0);
|
||||
var server = new ServerSocket();
|
||||
server.bind(socketAddress);
|
||||
return server;
|
||||
}
|
||||
}
|
||||
169
test/jdk/java/net/SocketOption/UnsupportedOptionsTest.java
Normal file
169
test/jdk/java/net/SocketOption/UnsupportedOptionsTest.java
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2020, 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.lang.reflect.Field;
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8143554 8044773
|
||||
* @library /test/lib
|
||||
* @summary Test checks that UnsupportedOperationException for unsupported
|
||||
* SOCKET_OPTIONS is thrown by both getOption() and setOption() methods.
|
||||
* @requires !vm.graal.enabled
|
||||
* @run main UnsupportedOptionsTest
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true UnsupportedOptionsTest
|
||||
* @run main/othervm --limit-modules=java.base UnsupportedOptionsTest
|
||||
*/
|
||||
|
||||
public class UnsupportedOptionsTest {
|
||||
|
||||
private static final List<SocketOption<?>> socketOptions = new ArrayList<>();
|
||||
|
||||
static {
|
||||
socketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
|
||||
socketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
socketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
|
||||
socketOptions.add(StandardSocketOptions.IP_TOS);
|
||||
socketOptions.add(StandardSocketOptions.SO_BROADCAST);
|
||||
socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
|
||||
socketOptions.add(StandardSocketOptions.SO_LINGER);
|
||||
socketOptions.add(StandardSocketOptions.SO_RCVBUF);
|
||||
socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
socketOptions.add(StandardSocketOptions.SO_SNDBUF);
|
||||
socketOptions.add(StandardSocketOptions.TCP_NODELAY);
|
||||
|
||||
try {
|
||||
Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
|
||||
Field field = c.getField("TCP_QUICKACK");
|
||||
socketOptions.add((SocketOption<?>)field.get(null));
|
||||
field = c.getField("TCP_KEEPIDLE");
|
||||
socketOptions.add((SocketOption<?>)field.get(null));
|
||||
field = c.getField("TCP_KEEPINTERVAL");
|
||||
socketOptions.add((SocketOption<?>)field.get(null));
|
||||
field = c.getField("TCP_KEEPCOUNT");
|
||||
socketOptions.add((SocketOption<?>)field.get(null));
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
// ignore, jdk.net module not present
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
IPSupport.throwSkippedExceptionIfNonOperational();
|
||||
|
||||
Socket s = new Socket();
|
||||
ServerSocket ss = new ServerSocket();
|
||||
DatagramSocket ds = new DatagramSocket();
|
||||
MulticastSocket ms = new MulticastSocket();
|
||||
|
||||
for (SocketOption option : socketOptions) {
|
||||
if (!s.supportedOptions().contains(option)) {
|
||||
testUnsupportedSocketOption(s, option);
|
||||
}
|
||||
|
||||
if (!ss.supportedOptions().contains(option)) {
|
||||
testUnsupportedSocketOption(ss, option);
|
||||
}
|
||||
|
||||
if (!ms.supportedOptions().contains(option)) {
|
||||
testUnsupportedSocketOption(ms, option);
|
||||
}
|
||||
|
||||
if (!ds.supportedOptions().contains(option)) {
|
||||
testUnsupportedSocketOption(ds, option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that UnsupportedOperationException for unsupported option is
|
||||
* thrown from both getOption() and setOption() methods.
|
||||
*/
|
||||
private static void testUnsupportedSocketOption(Object socket,
|
||||
SocketOption option) {
|
||||
testSet(socket, option);
|
||||
testGet(socket, option);
|
||||
}
|
||||
|
||||
private static void testSet(Object socket, SocketOption option) {
|
||||
try {
|
||||
setOption(socket, option);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
System.out.println("UnsupportedOperationException was throw " +
|
||||
"as expected. Socket: " + socket + " Option: " + option);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("FAIL. Unexpected exception.", e);
|
||||
}
|
||||
throw new RuntimeException("FAIL. UnsupportedOperationException " +
|
||||
"hasn't been thrown. Socket: " + socket + " Option: " + option);
|
||||
}
|
||||
|
||||
private static void testGet(Object socket, SocketOption option) {
|
||||
try {
|
||||
getOption(socket, option);
|
||||
} catch (UnsupportedOperationException e) {
|
||||
System.out.println("UnsupportedOperationException was throw " +
|
||||
"as expected. Socket: " + socket + " Option: " + option);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("FAIL. Unexpected exception.", e);
|
||||
}
|
||||
throw new RuntimeException("FAIL. UnsupportedOperationException " +
|
||||
"hasn't been thrown. Socket: " + socket + " Option: " + option);
|
||||
}
|
||||
|
||||
private static void getOption(Object socket,
|
||||
SocketOption option) throws IOException {
|
||||
if (socket instanceof Socket) {
|
||||
((Socket) socket).getOption(option);
|
||||
} else if (socket instanceof ServerSocket) {
|
||||
((ServerSocket) socket).getOption(option);
|
||||
} else if (socket instanceof DatagramSocket) {
|
||||
((DatagramSocket) socket).getOption(option);
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported socket type");
|
||||
}
|
||||
}
|
||||
|
||||
private static void setOption(Object socket,
|
||||
SocketOption option) throws IOException {
|
||||
if (socket instanceof Socket) {
|
||||
((Socket) socket).setOption(option, null);
|
||||
} else if (socket instanceof ServerSocket) {
|
||||
((ServerSocket) socket).setOption(option, null);
|
||||
} else if (socket instanceof DatagramSocket) {
|
||||
((DatagramSocket) socket).setOption(option, null);
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported socket type");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue