1 /* |
|
2 * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 /* @test |
|
25 * @bug 4527345 6842687 |
|
26 * @summary Unit test for AsynchronousDatagramChannel |
|
27 */ |
|
28 |
|
29 import java.nio.ByteBuffer; |
|
30 import java.nio.channels.*; |
|
31 import java.net.*; |
|
32 import java.util.concurrent.*; |
|
33 import java.util.concurrent.atomic.*; |
|
34 |
|
35 public class Basic { |
|
36 |
|
37 public static void main(String[] args) throws Exception { |
|
38 doReceiveTests(); |
|
39 doReadTests(); |
|
40 doSendTests(); |
|
41 doWriteTests(); |
|
42 doCancelTests(); |
|
43 doMulticastTests(); |
|
44 } |
|
45 |
|
46 // basic receive tests |
|
47 static void doReceiveTests() throws Exception { |
|
48 final byte[] msg = "hello".getBytes(); |
|
49 |
|
50 AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open() |
|
51 .bind(new InetSocketAddress(0)); |
|
52 int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); |
|
53 InetAddress rh = InetAddress.getLocalHost(); |
|
54 final SocketAddress sa = new InetSocketAddress(rh, port); |
|
55 |
|
56 DatagramChannel sender = DatagramChannel.open(); |
|
57 ByteBuffer dst = ByteBuffer.allocateDirect(100); |
|
58 |
|
59 // Test: datagram packet received immediately |
|
60 sender.send(ByteBuffer.wrap(msg), sa); |
|
61 dst.clear(); |
|
62 ch.receive(dst).get(1, TimeUnit.SECONDS); |
|
63 if (dst.flip().remaining() != msg.length) |
|
64 throw new RuntimeException("Unexpected number of bytes read"); |
|
65 |
|
66 // Test: datagram packet not received immediately |
|
67 dst.clear(); |
|
68 final CountDownLatch latch = new CountDownLatch(1); |
|
69 ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() { |
|
70 public void completed(SocketAddress source, Void att) { |
|
71 latch.countDown(); |
|
72 } |
|
73 public void failed (Throwable exc, Void att) { |
|
74 } |
|
75 }); |
|
76 Thread.sleep(2000); |
|
77 sender.send(ByteBuffer.wrap(msg), sa); |
|
78 latch.await(2, TimeUnit.SECONDS); // wait for completion handler |
|
79 |
|
80 // Test: timeout |
|
81 dst.clear(); |
|
82 final AtomicReference<Throwable> exception = new AtomicReference<Throwable>(); |
|
83 ch.receive(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<SocketAddress,Void>() { |
|
84 public void completed(SocketAddress source, Void att) { |
|
85 } |
|
86 public void failed (Throwable exc, Void att) { |
|
87 exception.set(exc); |
|
88 } |
|
89 }); |
|
90 Throwable result; |
|
91 while ((result = exception.get()) == null) { |
|
92 Thread.sleep(100); |
|
93 } |
|
94 if (!(result instanceof InterruptedByTimeoutException)) |
|
95 throw new RuntimeException("InterruptedByTimeoutException expected"); |
|
96 |
|
97 // AsynchronousCloseException |
|
98 dst = ByteBuffer.allocateDirect(100); |
|
99 exception.set(null); |
|
100 ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() { |
|
101 public void completed(SocketAddress source, Void att) { |
|
102 } |
|
103 public void failed (Throwable exc, Void att) { |
|
104 exception.set(exc); |
|
105 } |
|
106 }); |
|
107 ch.close(); |
|
108 while ((result = exception.get()) == null) { |
|
109 Thread.sleep(100); |
|
110 } |
|
111 if (!(result instanceof AsynchronousCloseException)) |
|
112 throw new RuntimeException("AsynchronousCloseException expected"); |
|
113 |
|
114 // done |
|
115 sender.close(); |
|
116 } |
|
117 |
|
118 // basic read tests |
|
119 static void doReadTests() throws Exception { |
|
120 final byte[] msg = "hello".getBytes(); |
|
121 |
|
122 AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open() |
|
123 .bind(new InetSocketAddress(0)); |
|
124 int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); |
|
125 InetAddress lh = InetAddress.getLocalHost(); |
|
126 final SocketAddress sa = new InetSocketAddress(lh, port); |
|
127 |
|
128 DatagramChannel sender = DatagramChannel.open(); |
|
129 ByteBuffer dst = ByteBuffer.allocateDirect(100); |
|
130 |
|
131 // Test: not connected |
|
132 try { |
|
133 ch.read(dst); |
|
134 throw new RuntimeException("NotYetConnectedException expected"); |
|
135 } catch (NotYetConnectedException e) { |
|
136 } |
|
137 |
|
138 // connect the channel |
|
139 sender.bind(new InetSocketAddress(0)); |
|
140 ch.connect(new InetSocketAddress(lh, |
|
141 ((InetSocketAddress)(sender.getLocalAddress())).getPort())); |
|
142 |
|
143 // Test: datagram packet received immediately |
|
144 sender.send(ByteBuffer.wrap(msg), sa); |
|
145 dst.clear(); |
|
146 ch.read(dst).get(1, TimeUnit.SECONDS); |
|
147 if (dst.flip().remaining() != msg.length) |
|
148 throw new RuntimeException("Unexpected number of bytes read"); |
|
149 |
|
150 // Test: datagram packet not received immediately |
|
151 dst.clear(); |
|
152 final CountDownLatch l1 = new CountDownLatch(1); |
|
153 ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() { |
|
154 public void completed(Integer bytesRead, Void att) { |
|
155 l1.countDown(); |
|
156 } |
|
157 public void failed (Throwable exc, Void att) { |
|
158 } |
|
159 }); |
|
160 Thread.sleep(2000); |
|
161 sender.send(ByteBuffer.wrap(msg), sa); |
|
162 l1.await(2, TimeUnit.SECONDS); |
|
163 |
|
164 // Test: timeout |
|
165 dst.clear(); |
|
166 final AtomicReference<Throwable> exception = new AtomicReference<Throwable>(); |
|
167 ch.read(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<Integer,Void>() { |
|
168 public void completed(Integer bytesRead, Void att) { |
|
169 } |
|
170 public void failed (Throwable exc, Void att) { |
|
171 exception.set(exc); |
|
172 } |
|
173 }); |
|
174 Throwable result; |
|
175 while ((result = exception.get()) == null) { |
|
176 Thread.sleep(100); |
|
177 } |
|
178 if (!(result instanceof InterruptedByTimeoutException)) |
|
179 throw new RuntimeException("InterruptedByTimeoutException expected"); |
|
180 |
|
181 // AsynchronousCloseException |
|
182 dst.clear(); |
|
183 exception.set(null); |
|
184 ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() { |
|
185 public void completed(Integer bytesRead, Void att) { |
|
186 } |
|
187 public void failed (Throwable exc, Void att) { |
|
188 exception.set(exc); |
|
189 } |
|
190 }); |
|
191 ch.close(); |
|
192 while ((result = exception.get()) == null) { |
|
193 Thread.sleep(100); |
|
194 } |
|
195 if (!(result instanceof AsynchronousCloseException)) |
|
196 throw new RuntimeException("AsynchronousCloseException expected"); |
|
197 |
|
198 // done |
|
199 sender.close(); |
|
200 } |
|
201 |
|
202 // basic send tests |
|
203 static void doSendTests() throws Exception { |
|
204 final byte[] msg = "hello".getBytes(); |
|
205 |
|
206 DatagramChannel reader = DatagramChannel.open() |
|
207 .bind(new InetSocketAddress(0)); |
|
208 int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort(); |
|
209 InetAddress rh = InetAddress.getLocalHost(); |
|
210 SocketAddress sa = new InetSocketAddress(rh, port); |
|
211 |
|
212 AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open(); |
|
213 |
|
214 // Test: send datagram packet to reader |
|
215 int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get(); |
|
216 if (bytesSent != msg.length) |
|
217 throw new RuntimeException("Unexpected number of bytes sent"); |
|
218 |
|
219 // check received |
|
220 ByteBuffer dst = ByteBuffer.allocateDirect(100); |
|
221 reader.receive(dst); |
|
222 dst.flip(); |
|
223 if (dst.remaining() != msg.length) |
|
224 throw new RuntimeException("Unexpected number of bytes received"); |
|
225 |
|
226 // Test: send datagram packet to reader and check completion handler |
|
227 // is invoked |
|
228 final CountDownLatch l2 = new CountDownLatch(1); |
|
229 ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() { |
|
230 public void completed(Integer bytesSent, Void att) { |
|
231 if (bytesSent != msg.length) |
|
232 throw new RuntimeException("Unexpected number of bytes received"); |
|
233 l2.countDown(); |
|
234 } |
|
235 public void failed (Throwable exc, Void att) { |
|
236 } |
|
237 }); |
|
238 l2.await(5, TimeUnit.SECONDS); |
|
239 |
|
240 // check received |
|
241 dst.clear(); |
|
242 reader.receive(dst); |
|
243 dst.flip(); |
|
244 if (dst.remaining() != msg.length) |
|
245 throw new RuntimeException("Unexpected number of bytes received"); |
|
246 |
|
247 // Test: check that failed method is invoked |
|
248 ch.close(); |
|
249 final CountDownLatch l3 = new CountDownLatch(1); |
|
250 ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() { |
|
251 public void completed(Integer bytesSent, Void att) { |
|
252 throw new RuntimeException("completed method invoked"); |
|
253 } |
|
254 public void failed (Throwable exc, Void att) { |
|
255 if (exc instanceof ClosedChannelException) { |
|
256 l3.countDown(); |
|
257 } else { |
|
258 throw new RuntimeException(exc); |
|
259 } |
|
260 } |
|
261 }); |
|
262 l3.await(5, TimeUnit.SECONDS); |
|
263 |
|
264 // done |
|
265 reader.close(); |
|
266 } |
|
267 |
|
268 // basic write tests |
|
269 static void doWriteTests() throws Exception { |
|
270 final byte[] msg = "hello".getBytes(); |
|
271 |
|
272 DatagramChannel reader = DatagramChannel.open() |
|
273 .bind(new InetSocketAddress(0)); |
|
274 int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort(); |
|
275 InetAddress rh = InetAddress.getLocalHost(); |
|
276 SocketAddress sa = new InetSocketAddress(rh, port); |
|
277 |
|
278 AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open(); |
|
279 |
|
280 // Test: unconnected |
|
281 try { |
|
282 ch.write(ByteBuffer.wrap(msg)).get(); |
|
283 throw new RuntimeException("NotYetConnectedException expected"); |
|
284 } catch (NotYetConnectedException e) { |
|
285 } |
|
286 |
|
287 // Test: connect, and write datagram |
|
288 ch.connect(sa); |
|
289 int bytesSent = ch.write(ByteBuffer.wrap(msg)).get(); |
|
290 if (bytesSent != msg.length) |
|
291 throw new RuntimeException("Unexpected number of bytes sent"); |
|
292 |
|
293 // check received |
|
294 ByteBuffer dst = ByteBuffer.allocateDirect(100); |
|
295 reader.receive(dst); |
|
296 dst.flip(); |
|
297 if (dst.remaining() != msg.length) |
|
298 throw new RuntimeException("Unexpected number of bytes received"); |
|
299 |
|
300 // Test: write datagram and check completion handler is invoked |
|
301 final CountDownLatch l2 = new CountDownLatch(1); |
|
302 ch.write(ByteBuffer.wrap(msg), (Void)null, new CompletionHandler<Integer,Void>() { |
|
303 public void completed(Integer bytesSent, Void att) { |
|
304 if (bytesSent != msg.length) |
|
305 throw new RuntimeException("Unexpected number of bytes received"); |
|
306 l2.countDown(); |
|
307 } |
|
308 public void failed (Throwable exc, Void att) { |
|
309 } |
|
310 }); |
|
311 l2.await(5, TimeUnit.SECONDS); |
|
312 |
|
313 // check received |
|
314 dst.clear(); |
|
315 reader.receive(dst); |
|
316 dst.flip(); |
|
317 if (dst.remaining() != msg.length) |
|
318 throw new RuntimeException("Unexpected number of bytes received"); |
|
319 |
|
320 // done |
|
321 ch.close(); |
|
322 reader.close(); |
|
323 } |
|
324 |
|
325 static void cancelAndCheck(Future<?> result) |
|
326 throws InterruptedException |
|
327 { |
|
328 boolean cancelled = result.cancel(false); |
|
329 if (!cancelled) |
|
330 throw new RuntimeException("Not cancelled"); |
|
331 if (!result.isDone()) |
|
332 throw new RuntimeException("Should be done"); |
|
333 try { |
|
334 result.get(); |
|
335 throw new RuntimeException("Result not expected"); |
|
336 } catch (CancellationException e) { |
|
337 // expected |
|
338 } catch (ExecutionException e) { |
|
339 throw new RuntimeException("Should not fail"); |
|
340 } |
|
341 } |
|
342 |
|
343 // basic cancel tests |
|
344 static void doCancelTests() throws Exception { |
|
345 InetAddress lh = InetAddress.getLocalHost(); |
|
346 |
|
347 // receive |
|
348 for (int i=0; i<2; i++) { |
|
349 AsynchronousDatagramChannel ch = |
|
350 AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0)); |
|
351 Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100)); |
|
352 cancelAndCheck(remote); |
|
353 ch.close(); |
|
354 } |
|
355 |
|
356 // read |
|
357 for (int i=0; i<2; i++) { |
|
358 AsynchronousDatagramChannel ch = |
|
359 AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0)); |
|
360 ch.connect(new InetSocketAddress(lh, |
|
361 ((InetSocketAddress)(ch.getLocalAddress())).getPort())); |
|
362 final CountDownLatch latch = new CountDownLatch(1); |
|
363 long timeout = (i == 0) ? 0L : 60L; |
|
364 Future<Integer> result = ch.read(ByteBuffer.allocate(100)); |
|
365 cancelAndCheck(result); |
|
366 ch.close(); |
|
367 } |
|
368 } |
|
369 |
|
370 // basic multicast test |
|
371 static void doMulticastTests() throws Exception { |
|
372 final byte[] msg = "hello".getBytes(); |
|
373 |
|
374 InetAddress lh = InetAddress.getLocalHost(); |
|
375 NetworkInterface interf = NetworkInterface.getByInetAddress(lh); |
|
376 if (interf.isLoopback() || !interf.supportsMulticast()) { |
|
377 System.out.println("Multicasting not tested"); |
|
378 return; |
|
379 } |
|
380 |
|
381 AsynchronousDatagramChannel ch = AsynchronousDatagramChannel |
|
382 .open(StandardProtocolFamily.INET, null) |
|
383 .setOption(StandardSocketOption.SO_REUSEADDR, true) |
|
384 .bind(new InetSocketAddress(0)); |
|
385 |
|
386 int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); |
|
387 |
|
388 // join group |
|
389 InetAddress group = InetAddress.getByName("225.4.5.6"); |
|
390 MembershipKey key = ch.join(group, interf); |
|
391 |
|
392 // check key |
|
393 if (key.channel() != ch) |
|
394 throw new RuntimeException("Not the expected channel"); |
|
395 |
|
396 // send message to group |
|
397 DatagramChannel sender = DatagramChannel.open(); |
|
398 sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port)); |
|
399 sender.close(); |
|
400 |
|
401 // check message received |
|
402 ByteBuffer dst = ByteBuffer.allocate(200); |
|
403 SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS); |
|
404 if (!((InetSocketAddress)source).getAddress().equals(lh)) |
|
405 throw new RuntimeException("Unexpected source"); |
|
406 |
|
407 // done |
|
408 ch.close(); |
|
409 } |
|
410 } |
|