blob: accdc75f10c5520a1895605701eb68c51dc87cb4 [file] [log] [blame]
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 4527345 6842687
* @summary Unit test for AsynchronousDatagramChannel
*/
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.net.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class Basic {
public static void main(String[] args) throws Exception {
doReceiveTests();
doReadTests();
doSendTests();
doWriteTests();
doCancelTests();
doMulticastTests();
}
// basic receive tests
static void doReceiveTests() throws Exception {
final byte[] msg = "hello".getBytes();
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
.bind(new InetSocketAddress(0));
int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
InetAddress rh = InetAddress.getLocalHost();
final SocketAddress sa = new InetSocketAddress(rh, port);
DatagramChannel sender = DatagramChannel.open();
ByteBuffer dst = ByteBuffer.allocateDirect(100);
// Test: datagram packet received immediately
sender.send(ByteBuffer.wrap(msg), sa);
dst.clear();
ch.receive(dst).get(1, TimeUnit.SECONDS);
if (dst.flip().remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes read");
// Test: datagram packet not received immediately
dst.clear();
final CountDownLatch latch = new CountDownLatch(1);
ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
public void completed(SocketAddress source, Void att) {
latch.countDown();
}
public void failed (Throwable exc, Void att) {
}
});
Thread.sleep(2000);
sender.send(ByteBuffer.wrap(msg), sa);
latch.await(2, TimeUnit.SECONDS); // wait for completion handler
// Test: timeout
dst.clear();
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
ch.receive(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<SocketAddress,Void>() {
public void completed(SocketAddress source, Void att) {
}
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
});
Throwable result;
while ((result = exception.get()) == null) {
Thread.sleep(100);
}
if (!(result instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// AsynchronousCloseException
dst = ByteBuffer.allocateDirect(100);
exception.set(null);
ch.receive(dst, (Void)null, new CompletionHandler<SocketAddress,Void>() {
public void completed(SocketAddress source, Void att) {
}
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
});
ch.close();
while ((result = exception.get()) == null) {
Thread.sleep(100);
}
if (!(result instanceof AsynchronousCloseException))
throw new RuntimeException("AsynchronousCloseException expected");
// done
sender.close();
}
// basic read tests
static void doReadTests() throws Exception {
final byte[] msg = "hello".getBytes();
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open()
.bind(new InetSocketAddress(0));
int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
InetAddress lh = InetAddress.getLocalHost();
final SocketAddress sa = new InetSocketAddress(lh, port);
DatagramChannel sender = DatagramChannel.open();
ByteBuffer dst = ByteBuffer.allocateDirect(100);
// Test: not connected
try {
ch.read(dst);
throw new RuntimeException("NotYetConnectedException expected");
} catch (NotYetConnectedException e) {
}
// connect the channel
sender.bind(new InetSocketAddress(0));
ch.connect(new InetSocketAddress(lh,
((InetSocketAddress)(sender.getLocalAddress())).getPort()));
// Test: datagram packet received immediately
sender.send(ByteBuffer.wrap(msg), sa);
dst.clear();
ch.read(dst).get(1, TimeUnit.SECONDS);
if (dst.flip().remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes read");
// Test: datagram packet not received immediately
dst.clear();
final CountDownLatch l1 = new CountDownLatch(1);
ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesRead, Void att) {
l1.countDown();
}
public void failed (Throwable exc, Void att) {
}
});
Thread.sleep(2000);
sender.send(ByteBuffer.wrap(msg), sa);
l1.await(2, TimeUnit.SECONDS);
// Test: timeout
dst.clear();
final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();
ch.read(dst, 2, TimeUnit.SECONDS, (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesRead, Void att) {
}
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
});
Throwable result;
while ((result = exception.get()) == null) {
Thread.sleep(100);
}
if (!(result instanceof InterruptedByTimeoutException))
throw new RuntimeException("InterruptedByTimeoutException expected");
// AsynchronousCloseException
dst.clear();
exception.set(null);
ch.read(dst, (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesRead, Void att) {
}
public void failed (Throwable exc, Void att) {
exception.set(exc);
}
});
ch.close();
while ((result = exception.get()) == null) {
Thread.sleep(100);
}
if (!(result instanceof AsynchronousCloseException))
throw new RuntimeException("AsynchronousCloseException expected");
// done
sender.close();
}
// basic send tests
static void doSendTests() throws Exception {
final byte[] msg = "hello".getBytes();
DatagramChannel reader = DatagramChannel.open()
.bind(new InetSocketAddress(0));
int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
InetAddress rh = InetAddress.getLocalHost();
SocketAddress sa = new InetSocketAddress(rh, port);
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
// Test: send datagram packet to reader
int bytesSent = ch.send(ByteBuffer.wrap(msg), sa).get();
if (bytesSent != msg.length)
throw new RuntimeException("Unexpected number of bytes sent");
// check received
ByteBuffer dst = ByteBuffer.allocateDirect(100);
reader.receive(dst);
dst.flip();
if (dst.remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
// Test: send datagram packet to reader and check completion handler
// is invoked
final CountDownLatch l2 = new CountDownLatch(1);
ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesSent, Void att) {
if (bytesSent != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
l2.countDown();
}
public void failed (Throwable exc, Void att) {
}
});
l2.await(5, TimeUnit.SECONDS);
// check received
dst.clear();
reader.receive(dst);
dst.flip();
if (dst.remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
// Test: check that failed method is invoked
ch.close();
final CountDownLatch l3 = new CountDownLatch(1);
ch.send(ByteBuffer.wrap(msg), sa, (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesSent, Void att) {
throw new RuntimeException("completed method invoked");
}
public void failed (Throwable exc, Void att) {
if (exc instanceof ClosedChannelException) {
l3.countDown();
} else {
throw new RuntimeException(exc);
}
}
});
l3.await(5, TimeUnit.SECONDS);
// done
reader.close();
}
// basic write tests
static void doWriteTests() throws Exception {
final byte[] msg = "hello".getBytes();
DatagramChannel reader = DatagramChannel.open()
.bind(new InetSocketAddress(0));
int port = ((InetSocketAddress)(reader.getLocalAddress())).getPort();
InetAddress rh = InetAddress.getLocalHost();
SocketAddress sa = new InetSocketAddress(rh, port);
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel.open();
// Test: unconnected
try {
ch.write(ByteBuffer.wrap(msg)).get();
throw new RuntimeException("NotYetConnectedException expected");
} catch (NotYetConnectedException e) {
}
// Test: connect, and write datagram
ch.connect(sa);
int bytesSent = ch.write(ByteBuffer.wrap(msg)).get();
if (bytesSent != msg.length)
throw new RuntimeException("Unexpected number of bytes sent");
// check received
ByteBuffer dst = ByteBuffer.allocateDirect(100);
reader.receive(dst);
dst.flip();
if (dst.remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
// Test: write datagram and check completion handler is invoked
final CountDownLatch l2 = new CountDownLatch(1);
ch.write(ByteBuffer.wrap(msg), (Void)null, new CompletionHandler<Integer,Void>() {
public void completed(Integer bytesSent, Void att) {
if (bytesSent != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
l2.countDown();
}
public void failed (Throwable exc, Void att) {
}
});
l2.await(5, TimeUnit.SECONDS);
// check received
dst.clear();
reader.receive(dst);
dst.flip();
if (dst.remaining() != msg.length)
throw new RuntimeException("Unexpected number of bytes received");
// done
ch.close();
reader.close();
}
static void cancelAndCheck(Future<?> result)
throws InterruptedException
{
boolean cancelled = result.cancel(false);
if (!cancelled)
throw new RuntimeException("Not cancelled");
if (!result.isDone())
throw new RuntimeException("Should be done");
try {
result.get();
throw new RuntimeException("Result not expected");
} catch (CancellationException e) {
// expected
} catch (ExecutionException e) {
throw new RuntimeException("Should not fail");
}
}
// basic cancel tests
static void doCancelTests() throws Exception {
InetAddress lh = InetAddress.getLocalHost();
// receive
for (int i=0; i<2; i++) {
AsynchronousDatagramChannel ch =
AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
Future<SocketAddress> remote = ch.receive(ByteBuffer.allocate(100));
cancelAndCheck(remote);
ch.close();
}
// read
for (int i=0; i<2; i++) {
AsynchronousDatagramChannel ch =
AsynchronousDatagramChannel.open().bind(new InetSocketAddress(0));
ch.connect(new InetSocketAddress(lh,
((InetSocketAddress)(ch.getLocalAddress())).getPort()));
final CountDownLatch latch = new CountDownLatch(1);
long timeout = (i == 0) ? 0L : 60L;
Future<Integer> result = ch.read(ByteBuffer.allocate(100));
cancelAndCheck(result);
ch.close();
}
}
// basic multicast test
static void doMulticastTests() throws Exception {
final byte[] msg = "hello".getBytes();
AsynchronousDatagramChannel ch = AsynchronousDatagramChannel
.open(StandardProtocolFamily.INET, null)
.setOption(StandardSocketOption.SO_REUSEADDR, true)
.bind(new InetSocketAddress(0));
InetAddress lh = InetAddress.getLocalHost();
int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort();
// join group
InetAddress group = InetAddress.getByName("225.4.5.6");
NetworkInterface interf = NetworkInterface.getByInetAddress(lh);
MembershipKey key = ch.join(group, interf);
// check key
if (key.channel() != ch)
throw new RuntimeException("Not the expected channel");
// send message to group
DatagramChannel sender = DatagramChannel.open();
sender.send(ByteBuffer.wrap(msg), new InetSocketAddress(group, port));
sender.close();
// check message received
ByteBuffer dst = ByteBuffer.allocate(200);
SocketAddress source = ch.receive(dst).get(2, TimeUnit.SECONDS);
if (!((InetSocketAddress)source).getAddress().equals(lh))
throw new RuntimeException("Unexpected source");
// done
ch.close();
}
}