• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }