1 2 3 /* 4 * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * @test 28 * @bug 8036979 8072384 8044773 29 * @requires !vm.graal.enabled 30 * @run main/othervm -Xcheck:jni OptionsTest 31 * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest 32 * @run main/othervm --limit-modules=java.base OptionsTest 33 */ 34 package test.java.net.SocketOptions; 35 36 import java.lang.reflect.Method; 37 import java.net.*; 38 import java.util.*; 39 40 import org.testng.annotations.Test; 41 42 public class OptionsTest { 43 44 static class TestClass { TestClass(SocketOption<?> option, Object testValue)45 TestClass(SocketOption<?> option, Object testValue) { 46 this.option = option; 47 this.testValue = testValue; 48 } create(SocketOption<?> option, Object testValue)49 static TestClass create(SocketOption<?> option, Object testValue) { 50 return new TestClass(option, testValue); 51 } 52 Object option; 53 Object testValue; 54 } 55 56 // The tests set the option using the new API, read back the set value 57 // which could be diferent, and then use the legacy get API to check 58 // these values are the same 59 60 static TestClass[] socketTests = new TestClass[] { 61 TestClass.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE), 62 TestClass.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), 63 TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), 64 TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), 65 TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), 66 TestClass.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), 67 TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) 68 }; 69 70 static TestClass[] serverSocketTests = new TestClass[] { 71 TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), 72 TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), 73 TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), 74 TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) 75 }; 76 77 static TestClass[] dgSocketTests = new TestClass[] { 78 TestClass.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), 79 TestClass.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), 80 TestClass.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), 81 TestClass.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), 82 TestClass.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) 83 }; 84 85 static TestClass[] mcSocketTests = new TestClass[] { 86 // Android-removed: unused in Android 87 // TestClass.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()), 88 TestClass.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)), 89 TestClass.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE) 90 }; 91 doSocketTests()92 static void doSocketTests() throws Exception { 93 try ( 94 ServerSocket srv = new ServerSocket(0); 95 Socket c = new Socket("127.0.0.1", srv.getLocalPort()); 96 Socket s = srv.accept(); 97 ) { 98 Set<SocketOption<?>> options = c.supportedOptions(); 99 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 100 for (int i=0; i<socketTests.length; i++) { 101 TestClass test = socketTests[i]; 102 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { 103 c.setOption((SocketOption)test.option, test.testValue); 104 Object getval = c.getOption((SocketOption)test.option); 105 Object legacyget = legacyGetOption(Socket.class, c,test.option); 106 if (!getval.equals(legacyget)) { 107 Formatter f = new Formatter(); 108 f.format("S Err %d: %s/%s", i, getval, legacyget); 109 throw new RuntimeException(f.toString()); 110 } 111 } 112 } 113 } 114 } 115 doDgSocketTests()116 static void doDgSocketTests() throws Exception { 117 try ( 118 DatagramSocket c = new DatagramSocket(0); 119 ) { 120 Set<SocketOption<?>> options = c.supportedOptions(); 121 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 122 for (int i=0; i<dgSocketTests.length; i++) { 123 TestClass test = dgSocketTests[i]; 124 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { 125 c.setOption((SocketOption)test.option, test.testValue); 126 Object getval = c.getOption((SocketOption)test.option); 127 Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option); 128 if (!getval.equals(legacyget)) { 129 Formatter f = new Formatter(); 130 f.format("DG Err %d: %s/%s", i, getval, legacyget); 131 throw new RuntimeException(f.toString()); 132 } 133 } 134 } 135 } 136 } 137 doMcSocketTests()138 static void doMcSocketTests() throws Exception { 139 try ( 140 MulticastSocket c = new MulticastSocket(0); 141 ) { 142 for (int i=0; i<mcSocketTests.length; i++) { 143 TestClass test = mcSocketTests[i]; 144 c.setOption((SocketOption)test.option, test.testValue); 145 Object getval = c.getOption((SocketOption)test.option); 146 Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option); 147 if (!getval.equals(legacyget)) { 148 Formatter f = new Formatter(); 149 f.format("MC Err %d: %s/%s", i, getval, legacyget); 150 throw new RuntimeException(f.toString()); 151 } 152 } 153 } 154 } 155 doServerSocketTests()156 static void doServerSocketTests() throws Exception { 157 try ( 158 ServerSocket c = new ServerSocket(0); 159 ) { 160 Set<SocketOption<?>> options = c.supportedOptions(); 161 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 162 for (int i=0; i<serverSocketTests.length; i++) { 163 TestClass test = serverSocketTests[i]; 164 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { 165 c.setOption((SocketOption)test.option, test.testValue); 166 Object getval = c.getOption((SocketOption)test.option); 167 Object legacyget = legacyGetOption( 168 ServerSocket.class, c, test.option 169 ); 170 if (!getval.equals(legacyget)) { 171 Formatter f = new Formatter(); 172 f.format("SS Err %d: %s/%s", i, getval, legacyget); 173 throw new RuntimeException(f.toString()); 174 } 175 } 176 } 177 } 178 } 179 legacyGetOption( Class<?> type, Object s, Object option)180 static Object legacyGetOption( 181 Class<?> type, Object s, Object option) 182 183 throws Exception 184 { 185 if (type.equals(Socket.class)) { 186 Socket socket = (Socket)s; 187 Set<SocketOption<?>> options = socket.supportedOptions(); 188 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 189 190 if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) { 191 return Boolean.valueOf(socket.getKeepAlive()); 192 } else if (option.equals(StandardSocketOptions.SO_SNDBUF)) { 193 return Integer.valueOf(socket.getSendBufferSize()); 194 } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { 195 return Integer.valueOf(socket.getReceiveBufferSize()); 196 } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { 197 return Boolean.valueOf(socket.getReuseAddress()); 198 } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { 199 return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); 200 } else if (option.equals(StandardSocketOptions.SO_LINGER)) { 201 return Integer.valueOf(socket.getSoLinger()); 202 } else if (option.equals(StandardSocketOptions.IP_TOS)) { 203 return Integer.valueOf(socket.getTrafficClass()); 204 } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) { 205 return Boolean.valueOf(socket.getTcpNoDelay()); 206 } else { 207 throw new RuntimeException("unexecpted socket option"); 208 } 209 } else if (type.equals(ServerSocket.class)) { 210 ServerSocket socket = (ServerSocket)s; 211 Set<SocketOption<?>> options = socket.supportedOptions(); 212 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 213 214 if (option.equals(StandardSocketOptions.SO_RCVBUF)) { 215 return Integer.valueOf(socket.getReceiveBufferSize()); 216 } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { 217 return Boolean.valueOf(socket.getReuseAddress()); 218 } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { 219 return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); 220 } else if (option.equals(StandardSocketOptions.IP_TOS)) { 221 return getServerSocketTrafficClass(socket); 222 } else { 223 throw new RuntimeException("unexecpted socket option"); 224 } 225 } else if (type.equals(DatagramSocket.class)) { 226 DatagramSocket socket = (DatagramSocket)s; 227 Set<SocketOption<?>> options = socket.supportedOptions(); 228 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 229 230 if (option.equals(StandardSocketOptions.SO_SNDBUF)) { 231 return Integer.valueOf(socket.getSendBufferSize()); 232 } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { 233 return Integer.valueOf(socket.getReceiveBufferSize()); 234 } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { 235 return Boolean.valueOf(socket.getReuseAddress()); 236 } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { 237 return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); 238 } else if (option.equals(StandardSocketOptions.IP_TOS)) { 239 return Integer.valueOf(socket.getTrafficClass()); 240 } else { 241 throw new RuntimeException("unexecpted socket option"); 242 } 243 244 } else if (type.equals(MulticastSocket.class)) { 245 MulticastSocket socket = (MulticastSocket)s; 246 Set<SocketOption<?>> options = socket.supportedOptions(); 247 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); 248 249 if (option.equals(StandardSocketOptions.SO_SNDBUF)) { 250 return Integer.valueOf(socket.getSendBufferSize()); 251 } else if (option.equals(StandardSocketOptions.SO_RCVBUF)) { 252 return Integer.valueOf(socket.getReceiveBufferSize()); 253 } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { 254 return Boolean.valueOf(socket.getReuseAddress()); 255 } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { 256 return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); 257 } else if (option.equals(StandardSocketOptions.IP_TOS)) { 258 return Integer.valueOf(socket.getTrafficClass()); 259 } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) { 260 return socket.getNetworkInterface(); 261 } else if (option.equals(StandardSocketOptions.IP_MULTICAST_TTL)) { 262 return Integer.valueOf(socket.getTimeToLive()); 263 } else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) { 264 return Boolean.valueOf(socket.getLoopbackMode()); 265 } else { 266 throw new RuntimeException("unexecpted socket option"); 267 } 268 } 269 throw new RuntimeException("unexecpted socket type"); 270 } 271 272 @Test testOptions()273 public void testOptions() throws Exception { 274 doSocketTests(); 275 doServerSocketTests(); 276 doDgSocketTests(); 277 doMcSocketTests(); 278 } 279 280 // Reflectively access jdk.net.Sockets.getOption so that the test can run 281 // without the jdk.net module. getServerSocketTrafficClass(ServerSocket ss)282 static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception { 283 try { 284 Class<?> c = Class.forName("jdk.net.Sockets"); 285 Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class); 286 return m.invoke(null, ss, StandardSocketOptions.IP_TOS); 287 } catch (ClassNotFoundException e) { 288 // Ok, jdk.net module not present, just fall back 289 System.out.println("jdk.net module not present, falling back."); 290 return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS)); 291 } catch (ReflectiveOperationException e) { 292 throw new AssertionError(e); 293 } 294 } 295 }