Path: blob/master/test/jdk/java/net/SocketOption/OptionsTest.java
41149 views
/*1* Copyright (c) 2014, 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*/2223/*24* @test25* @bug 8036979 8072384 8044773 8225214 8233296 823408326* @library /test/lib27* @requires !vm.graal.enabled28* @run main/othervm -Xcheck:jni OptionsTest29* @run main/othervm -Djdk.net.usePlainSocketImpl OptionsTest30* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl OptionsTest31* @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest32* @run main/othervm --limit-modules=java.base OptionsTest33* @run main/othervm/policy=options.policy OptionsTest34*/3536import java.lang.reflect.Method;37import java.net.*;38import java.util.*;39import jdk.test.lib.net.IPSupport;4041public class OptionsTest {4243static class Test<T> {44final SocketOption<T> option;45final T value;46Test(SocketOption<T> option, T value) {47this.option = option;48this.value = value;49}50static <T> Test<T> create(SocketOption<T> option, T value) {51return new Test<T>(option, value);52}5354}5556// The tests set the option using the new API, read back the set value57// which could be different, and then use the legacy get API to check58// these values are the same5960static Test<?>[] socketTests = new Test<?>[] {61Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE),62Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),63Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),64Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),65Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),66Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(-1)),67Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(0)),68Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),69Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound70Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),71Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound72};7374static Test<?>[] serverSocketTests = new Test<?>[] {75Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),76Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),77Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),78Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound79Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),80Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound81};8283static Test<?>[] datagramSocketTests = new Test<?>[] {84Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),85Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),86Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),87Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),88Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.FALSE),89Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.TRUE),90Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound91Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)),92Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound93};9495static Test<?>[] multicastSocketTests = new Test<?>[] {96Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.FALSE),97Test.create(StandardSocketOptions.SO_BROADCAST, Boolean.TRUE),98Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()),99Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(0)), // lower-bound100Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)),101Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(255)), //upper-bound102Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE)103};104105static NetworkInterface getNetworkInterface() {106try {107Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();108while (nifs.hasMoreElements()) {109NetworkInterface ni = nifs.nextElement();110if (ni.supportsMulticast()) {111return ni;112}113}114} catch (Exception e) {115}116return null;117}118119static boolean okayToTest(Socket s, SocketOption<?> option) {120if (option == StandardSocketOptions.SO_REUSEPORT) {121// skip SO_REUSEPORT if option is not supported122return s.supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT);123}124if (option == StandardSocketOptions.IP_TOS && s.isConnected()) {125// skip IP_TOS if connected126return false;127}128return true;129}130131static <T> void testEqual(SocketOption<T> option, T value1, T value2) {132if (!value1.equals(value2)) {133throw new RuntimeException("Test of " + option.name() + " failed: "134+ value1 + " != " + value2);135}136}137138static <T> void test(Socket s, Test<T> test) throws Exception {139SocketOption<T> option = test.option;140s.setOption(option, test.value);141T value1 = s.getOption(test.option);142T value2 = (T) legacyGetOption(Socket.class, s, test.option);143testEqual(option, value1, value2);144}145146static <T> void test(ServerSocket ss, Test<T> test) throws Exception {147SocketOption<T> option = test.option;148ss.setOption(option, test.value);149T value1 = ss.getOption(test.option);150T value2 = (T) legacyGetOption(ServerSocket.class, ss, test.option);151testEqual(option, value1, value2);152}153154static <T> void test(DatagramSocket ds, Test<T> test) throws Exception {155SocketOption<T> option = test.option;156ds.setOption(option, test.value);157T value1 = ds.getOption(test.option);158T value2 = (T) legacyGetOption(ds.getClass(), ds, test.option);159testEqual(option, value1, value2);160}161162// Tests default and negative values of SO_LINGER. All negative values should163// retrieve as -1.164static void testSoLingerValues() throws Exception {165try (Socket s = new Socket()) {166// retrieve without set167int defaultValue = s.getOption(StandardSocketOptions.SO_LINGER);168testEqual(StandardSocketOptions.SO_LINGER, -1, defaultValue);169170for (int v : List.of(-1, -2, -100, -65534, -65535, -65536, -100000)) {171System.out.println("Testing SO_LINGER with:" + v);172s.setOption(StandardSocketOptions.SO_LINGER, v);173int value = s.getOption(StandardSocketOptions.SO_LINGER);174testEqual(StandardSocketOptions.SO_LINGER, -1, value);175}176}177}178179@SuppressWarnings("try")180static void doSocketTests() throws Exception {181// unconnected socket182try (Socket s = new Socket()) {183for (Test<?> test : socketTests) {184if (okayToTest(s, test.option)) {185test(s, test);186}187}188}189190// connected socket191try (ServerSocket ss = new ServerSocket()) {192var loopback = InetAddress.getLoopbackAddress();193ss.bind(new InetSocketAddress(loopback, 0));194try (Socket s1 = new Socket()) {195s1.connect(ss.getLocalSocketAddress());196try (Socket s2 = ss.accept()) {197for (Test<?> test : socketTests) {198if (okayToTest(s1, test.option)) {199test(s1, test);200}201}202}203}204}205206testSoLingerValues();207}208209static void doServerSocketTests() throws Exception {210try (ServerSocket ss = new ServerSocket(0)) {211Set<SocketOption<?>> options = ss.supportedOptions();212boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);213for (Test<?> test : serverSocketTests) {214if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {215test(ss, test);216}217}218}219}220221static void doDatagramSocketTests() throws Exception {222try (DatagramSocket ds = new DatagramSocket(0)) {223Set<SocketOption<?>> options = ds.supportedOptions();224boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);225for (Test<?> test : datagramSocketTests) {226if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {227test(ds, test);228}229}230}231}232233static void doMulticastSocketTests() throws Exception {234try (MulticastSocket ms = new MulticastSocket(0)) {235for (Test<?> test : multicastSocketTests) {236test(ms, test);237}238}239}240241static Object legacyGetOption(Class<?> type, Object s, Object option) throws Exception {242if (type.equals(Socket.class)) {243Socket socket = (Socket)s;244Set<SocketOption<?>> options = socket.supportedOptions();245boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);246247if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {248return Boolean.valueOf(socket.getKeepAlive());249} else if (option.equals(StandardSocketOptions.SO_SNDBUF)) {250return Integer.valueOf(socket.getSendBufferSize());251} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {252return Integer.valueOf(socket.getReceiveBufferSize());253} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {254return Boolean.valueOf(socket.getReuseAddress());255} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {256return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));257} else if (option.equals(StandardSocketOptions.SO_LINGER)) {258return Integer.valueOf(socket.getSoLinger());259} else if (option.equals(StandardSocketOptions.IP_TOS)) {260return Integer.valueOf(socket.getTrafficClass());261} else if (option.equals(StandardSocketOptions.TCP_NODELAY)) {262return Boolean.valueOf(socket.getTcpNoDelay());263} else {264throw new RuntimeException("unexpected socket option");265}266} else if (type.equals(ServerSocket.class)) {267ServerSocket socket = (ServerSocket)s;268Set<SocketOption<?>> options = socket.supportedOptions();269boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);270271if (option.equals(StandardSocketOptions.SO_RCVBUF)) {272return Integer.valueOf(socket.getReceiveBufferSize());273} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {274return Boolean.valueOf(socket.getReuseAddress());275} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {276return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));277} else if (option.equals(StandardSocketOptions.IP_TOS)) {278return getServerSocketTrafficClass(socket);279} else {280throw new RuntimeException("unexpected socket option");281}282} else if (type.equals(DatagramSocket.class)) {283DatagramSocket socket = (DatagramSocket)s;284Set<SocketOption<?>> options = socket.supportedOptions();285boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);286287if (option.equals(StandardSocketOptions.SO_SNDBUF)) {288return Integer.valueOf(socket.getSendBufferSize());289} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {290return Integer.valueOf(socket.getReceiveBufferSize());291} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {292return Boolean.valueOf(socket.getReuseAddress());293} else if (option.equals(StandardSocketOptions.SO_BROADCAST)) {294return Boolean.valueOf(socket.getBroadcast());295} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {296return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));297} else if (option.equals(StandardSocketOptions.IP_TOS)) {298return Integer.valueOf(socket.getTrafficClass());299} else {300throw new RuntimeException("unexpected socket option");301}302303} else if (type.equals(MulticastSocket.class)) {304MulticastSocket socket = (MulticastSocket)s;305Set<SocketOption<?>> options = socket.supportedOptions();306boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);307308if (option.equals(StandardSocketOptions.SO_SNDBUF)) {309return Integer.valueOf(socket.getSendBufferSize());310} else if (option.equals(StandardSocketOptions.SO_RCVBUF)) {311return Integer.valueOf(socket.getReceiveBufferSize());312} else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {313return Boolean.valueOf(socket.getReuseAddress());314} else if (option.equals(StandardSocketOptions.SO_BROADCAST)) {315return Boolean.valueOf(socket.getBroadcast());316} else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {317return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));318} else if (option.equals(StandardSocketOptions.IP_TOS)) {319return Integer.valueOf(socket.getTrafficClass());320} else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {321return socket.getNetworkInterface();322} else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) {323return Integer.valueOf(socket.getTimeToLive());324} else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) {325return !Boolean.valueOf(socket.getLoopbackMode());326} else {327throw new RuntimeException("unexpected socket option");328}329}330throw new RuntimeException("unexpected socket type");331}332333public static void main(String args[]) throws Exception {334IPSupport.throwSkippedExceptionIfNonOperational();335doSocketTests();336doServerSocketTests();337doDatagramSocketTests();338doMulticastSocketTests();339}340341// Reflectively access jdk.net.Sockets.getOption so that the test can run342// without the jdk.net module.343static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception {344try {345Class<?> c = Class.forName("jdk.net.Sockets");346Method m = c.getMethod("getOption", ServerSocket.class, SocketOption.class);347return m.invoke(null, ss, StandardSocketOptions.IP_TOS);348} catch (ClassNotFoundException e) {349// Ok, jdk.net module not present, just fall back350System.out.println("jdk.net module not present, falling back.");351return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS));352} catch (ReflectiveOperationException e) {353throw new AssertionError(e);354}355}356}357358359