36 import java.util.*; |
36 import java.util.*; |
37 import jdk.test.lib.net.IPSupport; |
37 import jdk.test.lib.net.IPSupport; |
38 |
38 |
39 public class OptionsTest { |
39 public class OptionsTest { |
40 |
40 |
41 static class Test { |
41 static class Test<T> { |
42 Test(SocketOption<?> option, Object testValue) { |
42 final SocketOption<T> option; |
|
43 final T value; |
|
44 Test(SocketOption<T> option, T value) { |
43 this.option = option; |
45 this.option = option; |
44 this.testValue = testValue; |
46 this.value = value; |
45 } |
47 } |
46 static Test create (SocketOption<?> option, Object testValue) { |
48 static <T> Test<T> create(SocketOption<T> option, T value) { |
47 return new Test(option, testValue); |
49 return new Test<T>(option, value); |
48 } |
50 } |
49 Object option; |
51 |
50 Object testValue; |
|
51 } |
52 } |
52 |
53 |
53 // The tests set the option using the new API, read back the set value |
54 // The tests set the option using the new API, read back the set value |
54 // which could be diferent, and then use the legacy get API to check |
55 // which could be diferent, and then use the legacy get API to check |
55 // these values are the same |
56 // these values are the same |
56 |
57 |
57 static Test[] socketTests = new Test[] { |
58 static Test<?>[] socketTests = new Test<?>[] { |
58 Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE), |
59 Test.create(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE), |
59 Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), |
60 Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), |
60 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
61 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
61 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
62 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
62 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
63 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
64 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
65 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
65 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
66 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
66 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
67 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
67 }; |
68 }; |
68 |
69 |
69 static Test[] serverSocketTests = new Test[] { |
70 static Test<?>[] serverSocketTests = new Test<?>[] { |
70 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
71 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
71 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
72 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
72 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
73 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
73 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
74 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
74 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
75 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
75 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
76 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
76 }; |
77 }; |
77 |
78 |
78 static Test[] dgSocketTests = new Test[] { |
79 static Test<?>[] datagramSocketTests = new Test<?>[] { |
79 Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), |
80 Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), |
80 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
81 Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), |
81 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
82 Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), |
82 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
83 Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), |
83 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
84 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound |
84 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
85 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), |
85 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
86 Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(255)) //upper-bound |
86 }; |
87 }; |
87 |
88 |
88 static Test[] mcSocketTests = new Test[] { |
89 static Test<?>[] multicastSocketTests = new Test<?>[] { |
89 Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()), |
90 Test.create(StandardSocketOptions.IP_MULTICAST_IF, getNetworkInterface()), |
90 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(0)), // lower-bound |
91 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(0)), // lower-bound |
91 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)), |
92 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(10)), |
92 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(255)), //upper-bound |
93 Test.create(StandardSocketOptions.IP_MULTICAST_TTL, Integer.valueOf(255)), //upper-bound |
93 Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE) |
94 Test.create(StandardSocketOptions.IP_MULTICAST_LOOP, Boolean.TRUE) |
95 |
96 |
96 static NetworkInterface getNetworkInterface() { |
97 static NetworkInterface getNetworkInterface() { |
97 try { |
98 try { |
98 Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); |
99 Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces(); |
99 while (nifs.hasMoreElements()) { |
100 while (nifs.hasMoreElements()) { |
100 NetworkInterface ni = (NetworkInterface)nifs.nextElement(); |
101 NetworkInterface ni = nifs.nextElement(); |
101 if (ni.supportsMulticast()) { |
102 if (ni.supportsMulticast()) { |
102 return ni; |
103 return ni; |
103 } |
104 } |
104 } |
105 } |
105 } catch (Exception e) { |
106 } catch (Exception e) { |
106 } |
107 } |
107 return null; |
108 return null; |
108 } |
109 } |
109 |
110 |
|
111 static boolean okayToTest(Socket s, SocketOption<?> option) { |
|
112 if (option == StandardSocketOptions.SO_REUSEPORT) { |
|
113 // skip SO_REUSEPORT if option is not supported |
|
114 return s.supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT); |
|
115 } |
|
116 if (option == StandardSocketOptions.IP_TOS && s.isConnected()) { |
|
117 // skip IP_TOS if connected |
|
118 return false; |
|
119 } |
|
120 return true; |
|
121 } |
|
122 |
|
123 static <T> void testEqual(SocketOption<T> option, T value1, T value2) { |
|
124 if (!value1.equals(value2)) { |
|
125 throw new RuntimeException("Test of " + option.name() + " failed: " |
|
126 + value1 + " != " + value2); |
|
127 } |
|
128 } |
|
129 |
|
130 static <T> void test(Socket s, Test<T> test) throws Exception { |
|
131 SocketOption<T> option = test.option; |
|
132 s.setOption(option, test.value); |
|
133 T value1 = s.getOption(test.option); |
|
134 T value2 = (T) legacyGetOption(Socket.class, s, test.option); |
|
135 testEqual(option, value1, value2); |
|
136 } |
|
137 |
|
138 static <T> void test(ServerSocket ss, Test<T> test) throws Exception { |
|
139 SocketOption<T> option = test.option; |
|
140 ss.setOption(option, test.value); |
|
141 T value1 = ss.getOption(test.option); |
|
142 T value2 = (T) legacyGetOption(ServerSocket.class, ss, test.option); |
|
143 testEqual(option, value1, value2); |
|
144 } |
|
145 |
|
146 static <T> void test(DatagramSocket ds, Test<T> test) throws Exception { |
|
147 SocketOption<T> option = test.option; |
|
148 ds.setOption(option, test.value); |
|
149 T value1 = ds.getOption(test.option); |
|
150 T value2 = (T) legacyGetOption(ds.getClass(), ds, test.option); |
|
151 testEqual(option, value1, value2); |
|
152 } |
|
153 |
|
154 @SuppressWarnings("try") |
110 static void doSocketTests() throws Exception { |
155 static void doSocketTests() throws Exception { |
111 try ( |
156 // unconnected socket |
112 ServerSocket srv = new ServerSocket(0, 50, InetAddress.getLoopbackAddress()); |
157 try (Socket s = new Socket()) { |
113 Socket c = new Socket(InetAddress.getLoopbackAddress(), srv.getLocalPort()); |
158 for (Test<?> test : socketTests) { |
114 Socket s = srv.accept(); |
159 if (okayToTest(s, test.option)) { |
115 ) { |
160 test(s, test); |
116 Set<SocketOption<?>> options = c.supportedOptions(); |
161 } |
117 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
162 } |
118 for (int i=0; i<socketTests.length; i++) { |
163 } |
119 Test test = socketTests[i]; |
164 |
|
165 // connected socket |
|
166 try (ServerSocket ss = new ServerSocket()) { |
|
167 var loopback = InetAddress.getLoopbackAddress(); |
|
168 ss.bind(new InetSocketAddress(loopback, 0)); |
|
169 try (Socket s1 = new Socket()) { |
|
170 s1.connect(ss.getLocalSocketAddress()); |
|
171 try (Socket s2 = ss.accept()) { |
|
172 for (Test<?> test : socketTests) { |
|
173 if (okayToTest(s1, test.option)) { |
|
174 test(s1, test); |
|
175 } |
|
176 } |
|
177 } |
|
178 } |
|
179 } |
|
180 } |
|
181 |
|
182 static void doServerSocketTests() throws Exception { |
|
183 try (ServerSocket ss = new ServerSocket(0)) { |
|
184 Set<SocketOption<?>> options = ss.supportedOptions(); |
|
185 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
|
186 for (Test<?> test : serverSocketTests) { |
120 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { |
187 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { |
121 c.setOption((SocketOption)test.option, test.testValue); |
188 test(ss, test); |
122 Object getval = c.getOption((SocketOption)test.option); |
189 } |
123 Object legacyget = legacyGetOption(Socket.class, c,test.option); |
190 } |
124 if (!getval.equals(legacyget)) { |
191 } |
125 Formatter f = new Formatter(); |
192 } |
126 f.format("S Err %d: %s/%s", i, getval, legacyget); |
193 |
127 throw new RuntimeException(f.toString()); |
194 static void doDatagramSocketTests() throws Exception { |
128 } |
195 try (DatagramSocket ds = new DatagramSocket(0)) { |
129 } |
196 Set<SocketOption<?>> options = ds.supportedOptions(); |
130 } |
197 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
131 } |
198 for (Test<?> test : datagramSocketTests) { |
132 } |
|
133 |
|
134 static void doDgSocketTests() throws Exception { |
|
135 try ( |
|
136 DatagramSocket c = new DatagramSocket(0); |
|
137 ) { |
|
138 Set<SocketOption<?>> options = c.supportedOptions(); |
|
139 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
|
140 for (int i=0; i<dgSocketTests.length; i++) { |
|
141 Test test = dgSocketTests[i]; |
|
142 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { |
199 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { |
143 c.setOption((SocketOption)test.option, test.testValue); |
200 test(ds, test); |
144 Object getval = c.getOption((SocketOption)test.option); |
201 } |
145 Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option); |
202 } |
146 if (!getval.equals(legacyget)) { |
203 } |
147 Formatter f = new Formatter(); |
204 } |
148 f.format("DG Err %d: %s/%s", i, getval, legacyget); |
205 |
149 throw new RuntimeException(f.toString()); |
206 static void doMulticastSocketTests() throws Exception { |
150 } |
207 try (MulticastSocket ms = new MulticastSocket(0)) { |
151 } |
208 for (Test<?> test : multicastSocketTests) { |
152 } |
209 test(ms, test); |
153 } |
210 } |
154 } |
211 } |
155 |
212 } |
156 static void doMcSocketTests() throws Exception { |
213 |
157 try ( |
214 static Object legacyGetOption(Class<?> type, Object s, Object option) throws Exception { |
158 MulticastSocket c = new MulticastSocket(0); |
|
159 ) { |
|
160 for (int i=0; i<mcSocketTests.length; i++) { |
|
161 Test test = mcSocketTests[i]; |
|
162 c.setOption((SocketOption)test.option, test.testValue); |
|
163 Object getval = c.getOption((SocketOption)test.option); |
|
164 Object legacyget = legacyGetOption(MulticastSocket.class, c,test.option); |
|
165 if (!getval.equals(legacyget)) { |
|
166 Formatter f = new Formatter(); |
|
167 f.format("MC Err %d: %s/%s", i, getval, legacyget); |
|
168 throw new RuntimeException(f.toString()); |
|
169 } |
|
170 } |
|
171 } |
|
172 } |
|
173 |
|
174 static void doServerSocketTests() throws Exception { |
|
175 try ( |
|
176 ServerSocket c = new ServerSocket(0); |
|
177 ) { |
|
178 Set<SocketOption<?>> options = c.supportedOptions(); |
|
179 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
|
180 for (int i=0; i<serverSocketTests.length; i++) { |
|
181 Test test = serverSocketTests[i]; |
|
182 if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) { |
|
183 c.setOption((SocketOption)test.option, test.testValue); |
|
184 Object getval = c.getOption((SocketOption)test.option); |
|
185 Object legacyget = legacyGetOption( |
|
186 ServerSocket.class, c, test.option |
|
187 ); |
|
188 if (!getval.equals(legacyget)) { |
|
189 Formatter f = new Formatter(); |
|
190 f.format("SS Err %d: %s/%s", i, getval, legacyget); |
|
191 throw new RuntimeException(f.toString()); |
|
192 } |
|
193 } |
|
194 } |
|
195 } |
|
196 } |
|
197 |
|
198 static Object legacyGetOption( |
|
199 Class<?> type, Object s, Object option) |
|
200 |
|
201 throws Exception |
|
202 { |
|
203 if (type.equals(Socket.class)) { |
215 if (type.equals(Socket.class)) { |
204 Socket socket = (Socket)s; |
216 Socket socket = (Socket)s; |
205 Set<SocketOption<?>> options = socket.supportedOptions(); |
217 Set<SocketOption<?>> options = socket.supportedOptions(); |
206 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
218 boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); |
207 |
219 |