view overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java @ 1719:ab30fa9f3e55

Move NIO2 tests to right directory. 2009-03-06 Andrew John Hughes <ahughes@redhat.com> * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/io/Inputs/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Attack.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Identity.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Restart.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/Unbounded.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/Lock.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousSocketChannel/Leaky.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/Channels/Basic2.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/Filters.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/DirectoryStream/SecureDS.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileStore/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/FileSystem/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ContentType.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/CreateFileTree.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/ForceLoad.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/Misc.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/PrintFileTree.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SimpleFileTypeDetector.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/SkipSiblings.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/TerminateWalk.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/content_type.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Files/walk_file_tree.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/CopyAndMove.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/DeleteOnClose.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Links.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/Misc.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/PathOps.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/SBC.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/TemporaryFiles.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/UriImportExport.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/delete_on_close.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/temporary_files.sh, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/PathMatcher/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/TestUtil.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/FileTreeModifier.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/denyAll.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndOneLevel.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirAndTree.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/WatchService/grantDirOnly.policy, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/AclFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/Attributes/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/BasicFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/DosFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/FileStoreAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/PosixFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/SetDefaultProvider.java, * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/spi/TestProvider.java: Moved to... * overlays/nio2/openjdk/jdk/test/java/io/Inputs/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/AsExecutor.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/Attack.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/PrivilegedThreadFactory.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/Restart.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousChannelGroup/run_any_task.sh, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousFileChannel/CustomThreadPool.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousFileChannel/MyThreadFactory.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.allow, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/java.policy.deny, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/AsynchronousSocketChannel/Leaky.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/Channels/Basic2.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/CheckProvider.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/META-INF/services/java.nio.channels.spi.AsynchronousChannelProvider, * overlays/nio2/openjdk/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider1.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/Provider2.java, * overlays/nio2/openjdk/jdk/test/java/nio/channels/spi/AsynchronousChannelProvider/custom_provider.sh, * overlays/nio2/openjdk/jdk/test/java/nio/file/DirectoryStream/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/DirectoryStream/Filters.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/DirectoryStream/SecureDS.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/FileStore/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/FileSystem/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/ContentType.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/CreateFileTree.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/ForceLoad.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/META-INF/services/java.nio.file.spi.FileTypeDetector, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/Misc.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/PrintFileTree.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/SimpleFileTypeDetector.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/SkipSiblings.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/TerminateWalk.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/content_type.sh, * overlays/nio2/openjdk/jdk/test/java/nio/file/Files/walk_file_tree.sh, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/CopyAndMove.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/DeleteOnClose.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/InterruptCopy.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/Links.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/Misc.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/PathOps.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/SBC.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/TemporaryFiles.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/UriImportExport.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/delete_on_close.sh, * overlays/nio2/openjdk/jdk/test/java/nio/file/Path/temporary_files.sh, * overlays/nio2/openjdk/jdk/test/java/nio/file/PathMatcher/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/TestUtil.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/FileTreeModifier.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/WithSecurityManager.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/denyAll.policy, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/grantDirAndOneLevel.policy, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/grantDirAndTree.policy, * overlays/nio2/openjdk/jdk/test/java/nio/file/WatchService/grantDirOnly.policy, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/AclFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/Attributes/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/BasicFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/DosFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/FileStoreAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/NamedAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/attribute/PosixFileAttributeView/Basic.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/spi/SetDefaultProvider.java, * overlays/nio2/openjdk/jdk/test/java/nio/file/spi/TestProvider.java: here.
author Andrew John Hughes <ahughes@redhat.com>
date Fri, 06 Mar 2009 12:26:40 +0000
parents overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/channels/AsynchronousDatagramChannel/Basic.java@2257885742d0
children
line wrap: on
line source

/*
 * Copyright 2007-2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/* @test
 * @bug 4527345
 * @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();
        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, null, new CompletionHandler<SocketAddress,Void>() {
            public void completed(SocketAddress source, Void att) {
                latch.countDown();
            }
            public void failed (Throwable exc, Void att) {
            }
            public void cancelled(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, null, new CompletionHandler<SocketAddress,Void>() {
            public void completed(SocketAddress source, Void att) {
            }
            public void failed (Throwable exc, Void att) {
                exception.set(exc);
            }
            public void cancelled(Void att) {
            }
        });
        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, null, new CompletionHandler<SocketAddress,Void>() {
            public void completed(SocketAddress source, Void att) {
            }
            public void failed (Throwable exc, Void att) {
                exception.set(exc);
            }
            public void cancelled(Void att) {
            }
        });
        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, null, new CompletionHandler<Integer,Void>() {
            public void completed(Integer bytesRead, Void att) {
                l1.countDown();
            }
            public void failed (Throwable exc, Void att) {
            }
            public void cancelled(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, null, new CompletionHandler<Integer,Void>() {
            public void completed(Integer bytesRead, Void att) {
            }
            public void failed (Throwable exc, Void att) {
                exception.set(exc);
            }
            public void cancelled(Void att) {
            }
        });
        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, null, new CompletionHandler<Integer,Void>() {
            public void completed(Integer bytesRead, Void att) {
            }
            public void failed (Throwable exc, Void att) {
                exception.set(exc);
            }
            public void cancelled(Void att) {
            }
        });
        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, 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) {
            }
            public void cancelled(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, 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);
                }
            }
            public void cancelled(Void att) {
            }
        });
        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), 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) {
            }
            public void cancelled(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();
    }

    // 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();
    }
}