Path: blob/master/test/jdk/java/net/SocketOption/RequiredOptions.java
41149 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.net.DatagramSocket;25import java.net.MulticastSocket;26import java.net.ServerSocket;27import java.net.Socket;28import java.net.SocketOption;29import java.nio.channels.DatagramChannel;30import java.nio.channels.NetworkChannel;31import java.nio.channels.ServerSocketChannel;32import java.nio.channels.SocketChannel;33import java.util.Set;34import java.util.stream.Stream;35import org.testng.annotations.Test;36import org.testng.annotations.DataProvider;3738import static java.net.StandardSocketOptions.*;3940/*41* @test42* @bug 823514143* @summary verifies that our implementation supports the set44* of SocketOptions that are required by the API documentation.45* @run testng/othervm -Djdk.net.usePlainSocketImpl RequiredOptions46* @run testng/othervm RequiredOptions47*/48public class RequiredOptions {4950static final Set<SocketOption<?>> DATAGRAM_OPTIONS =51Set.of(SO_BROADCAST, SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, IP_TOS);52static final Set<SocketOption<?>> MULTICAST_OPTIONS =53concat(DATAGRAM_OPTIONS, Set.of(IP_MULTICAST_IF, IP_MULTICAST_LOOP, IP_MULTICAST_TTL));54static final Set<SocketOption<?>> SOCKET_OPTIONS =55Set.of(SO_KEEPALIVE, SO_LINGER, SO_SNDBUF, SO_RCVBUF, SO_REUSEADDR, TCP_NODELAY);56static final Set<SocketOption<?>> SERVER_OPTIONS =57Set.of(SO_RCVBUF, SO_REUSEADDR);5859static Set<SocketOption<?>> concat(Set<SocketOption<?>> ...options) {60return Set.of(Stream.of(options).flatMap(Set::stream).distinct().toArray(SocketOption[]::new));61}6263@DataProvider(name = "sockets")64static Object[][] provider() throws IOException {65return new Object[][] {66// UDP67{ Configurable.of(new DatagramSocket(null)), DATAGRAM_OPTIONS },68{ Configurable.of(new MulticastSocket(null)), MULTICAST_OPTIONS },69// TCP70{ Configurable.of(new Socket()), SOCKET_OPTIONS },71{ Configurable.of(new ServerSocket()), SERVER_OPTIONS },72// Adaptors73{ Configurable.of(DatagramChannel.open().socket()), MULTICAST_OPTIONS },74{ Configurable.of(SocketChannel.open().socket()), SOCKET_OPTIONS },75{ Configurable.of(ServerSocketChannel.open().socket()), SERVER_OPTIONS },76};77}7879@Test(dataProvider = "sockets")80public <R, E extends Exception>81void test(Configurable<R,E> socket, Set<SocketOption<?>> options) throws E {82try (var s = socket) {83var impl = socket.socket().getClass();84System.out.println("Testing " + impl + " with " + options);85Set<SocketOption<?>> supported = socket.supportedOptions();86if (!supported.containsAll(options)) {87for (var option : options) {88if (!supported.contains(option)) {89System.err.println("Option " + option + " not supported by " + impl);90}91}92throw new AssertionError("Not all documented options are supported by " + impl);93}94}95}9697static interface Configurable<R, E extends Exception> extends AutoCloseable {98<T> R setOption(SocketOption<T> name, T value) throws E;99<T> T getOption(SocketOption<T> name) throws E;100Set<SocketOption<?>> supportedOptions() throws E;101R socket();102void close() throws E;103104static Configurable<DatagramSocket, IOException> of(DatagramSocket socket) {105return new ConfigurableImpl<>(socket, socket::setOption,106socket::getOption, socket::supportedOptions, socket::close);107}108static Configurable<Socket, IOException> of(Socket socket) {109return new ConfigurableImpl<>(socket, socket::setOption,110socket::getOption, socket::supportedOptions, socket::close);111}112static Configurable<ServerSocket, IOException> of(ServerSocket socket) {113return new ConfigurableImpl<>(socket, socket::setOption,114socket::getOption, socket::supportedOptions, socket::close);115}116}117118static final class ConfigurableImpl<R, E extends Exception> implements Configurable<R, E> {119@FunctionalInterface120interface SetOption<R, E extends Exception> {121<T> R setOption(SocketOption<T> name, T value) throws E;122}123@FunctionalInterface124interface GetOption<E extends Exception> {125<T> T getOption(SocketOption<T> name) throws E;126}127@FunctionalInterface128interface SupportedOption<E extends Exception> {129Set<SocketOption<?>> supportedOptions() throws E;130}131@FunctionalInterface132interface Closer<E extends Exception> {133void close() throws E;134}135136private final R socket;137private final SetOption<R, E> setter;138private final GetOption<E> getter;139private final SupportedOption<E> support;140private final Closer<E> closer;141142public ConfigurableImpl(R socket, SetOption<R, E> setter, GetOption<E> getter,143SupportedOption<E> support, Closer<E> closer) {144this.socket = socket;145this.setter = setter;146this.getter = getter;147this.support = support;148this.closer = closer;149}150151@Override152public <T> R setOption(SocketOption<T> name, T value) throws E {153return setter.setOption(name, value);154}155@Override156public <T> T getOption(SocketOption<T> name) throws E {157return getter.getOption(name);158}159@Override160public Set<SocketOption<?>> supportedOptions() throws E {161return support.supportedOptions();162}163@Override164public R socket() {165return socket;166}167@Override168public void close() throws E {169closer.close();170}171}172173174}175176177