/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.tests.java.net;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.DatagramSocketImpl;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.channels.DatagramChannel;

public class DatagramSocketTest extends junit.framework.TestCase {

    static final class DatagramServer extends Thread {

        volatile boolean running = true;

        private final boolean echo;
        private final byte[] rbuf;
        private final DatagramPacket rdp;
        final DatagramSocket serverSocket;

        public DatagramServer(InetAddress address, boolean echo)
                throws IOException {
            this.echo = echo;
            rbuf = new byte[512];
            rbuf[0] = -1;
            rdp = new DatagramPacket(rbuf, rbuf.length);
            serverSocket = new DatagramSocket(0, address);
            serverSocket.setSoTimeout(2000);
        }

        public DatagramServer(InetAddress address) throws IOException {
            this(address, true /* echo */);
        }

        public void run() {
            try {
                while (running) {
                    try {
                        serverSocket.receive(rdp);
                        if (echo) {
                            serverSocket.send(rdp);
                        }
                    } catch (InterruptedIOException e) {
                    }
                }
            } catch (IOException e) {
                fail();
            } finally {
                serverSocket.close();
            }
        }

        public int getPort() {
            return serverSocket.getLocalPort();
        }

        public void stopServer() {
            running = false;
        }
    }

    /**
     * java.net.DatagramSocket#DatagramSocket()
     */
    public void test_Constructor() throws SocketException {
        new DatagramSocket();
    }

    /**
     * java.net.DatagramSocket#DatagramSocket(int)
     */
    public void test_ConstructorI() throws SocketException {
        DatagramSocket ds = new DatagramSocket(0);
        ds.close();
    }

    /**
     * java.net.DatagramSocket#DatagramSocket(int, java.net.InetAddress)
     */
    public void test_ConstructorILjava_net_InetAddress() throws IOException {
        DatagramSocket ds = new DatagramSocket(0, InetAddress.getLocalHost());
        assertTrue("Created socket with incorrect port", ds.getLocalPort() != 0);
        assertEquals("Created socket with incorrect address", InetAddress
                .getLocalHost(), ds.getLocalAddress());
    }

    /**
     * java.net.DatagramSocket#close()
     */
    public void test_close() throws UnknownHostException, SocketException {
        DatagramSocket ds = new DatagramSocket(0);
        DatagramPacket dp = new DatagramPacket("Test String".getBytes(), 11,
                InetAddress.getLocalHost(), 0);
        ds.close();
        try {
            ds.send(dp);
            fail("Data sent after close");
        } catch (IOException e) {
            // Expected
        }
    }

    public void test_connectLjava_net_InetAddressI() throws Exception {
        DatagramSocket ds = new DatagramSocket();
        InetAddress inetAddress = InetAddress.getLocalHost();
        ds.connect(inetAddress, 0);
        assertEquals("Incorrect InetAddress", inetAddress, ds.getInetAddress());
        assertEquals("Incorrect Port", 0, ds.getPort());
        ds.disconnect();

        ds = new java.net.DatagramSocket();
        inetAddress = InetAddress.getByName("FE80:0000:0000:0000:020D:60FF:FE0F:A776%4");
        ds.connect(inetAddress, 0);
        assertEquals(inetAddress, ds.getInetAddress());
        ds.disconnect();
    }

    public void testConnect_connectToSelf() throws Exception {
        // Create a connected datagram socket to test
        // PlainDatagramSocketImpl.peek()
        InetAddress localHost = InetAddress.getLocalHost();
        final DatagramSocket ds = new DatagramSocket(0);
        ds.connect(localHost, ds.getLocalPort());
        DatagramPacket send = new DatagramPacket(new byte[10], 10, localHost,
                ds.getLocalPort());
        ds.send(send);

        DatagramPacket receive = new DatagramPacket(new byte[20], 20);
        ds.setSoTimeout(2000);
        ds.receive(receive);
        ds.close();

        assertEquals(10, receive.getLength());
        assertEquals(localHost, receive.getAddress());
    }

    private static void assertPacketDataEquals(DatagramPacket p1, DatagramPacket p2)
            throws Exception {
        assertEquals(p1.getLength(), p2.getLength());
        final byte[] p1Bytes = p1.getData();
        final byte[] p2Bytes = p2.getData();

        for (int i = 0; i < p1.getLength(); ++i) {
            if (p1Bytes[p1.getOffset() + i] != p2Bytes[p2.getOffset() + i]) {
                String expected = new String(p1Bytes, p1.getOffset(), p1.getLength(),
                        "UTF-8");
                String actual = new String(p2Bytes, p2.getOffset(), p2.getLength(),
                        "UTF-8");
                fail("expected: " + expected + ", actual: " + actual);
            }
        }
    }

    public void testConnect_echoServer() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);

        final DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        server.start();

        ds.connect(Inet6Address.LOOPBACK, server.getPort());

        final byte[] sendBytes = { 'T', 'e', 's', 't', 0 };
        final DatagramPacket send = new DatagramPacket(sendBytes, sendBytes.length);
        final DatagramPacket receive = new DatagramPacket(new byte[20], 20);

        ds.send(send);
        ds.setSoTimeout(2000);
        ds.receive(receive);
        ds.close();

        assertEquals(sendBytes.length, receive.getLength());
        assertPacketDataEquals(send, receive);
        assertEquals(Inet6Address.LOOPBACK, receive.getAddress());

        server.stopServer();
    }

    // Validate that once connected we cannot send to another address.
    public void testConnect_throwsOnAddressMismatch() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);

        DatagramServer s1 = new DatagramServer(Inet6Address.LOOPBACK);
        DatagramServer s2 = new DatagramServer(Inet6Address.LOOPBACK);
        try {
            ds.connect(Inet6Address.LOOPBACK, s1.getPort());
            ds.send(new DatagramPacket(new byte[10], 10, Inet6Address.LOOPBACK, s2.getPort()));
            fail();
        } catch (IllegalArgumentException expected) {
        } finally {
            ds.close();
            s1.stopServer();
            s2.stopServer();
        }
    }

    // Validate that we can connect, then disconnect, then connect then
    // send/recv.
    public void testConnect_connectDisconnectConnectThenSendRecv() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);

        final DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        final DatagramServer broken = new DatagramServer(Inet6Address.LOOPBACK, false);
        server.start();
        broken.start();

        final int serverPortNumber = server.getPort();
        ds.connect(Inet6Address.LOOPBACK, broken.getPort());
        ds.disconnect();
        ds.connect(Inet6Address.LOOPBACK, serverPortNumber);

        final byte[] sendBytes = { 'T', 'e', 's', 't', 0 };
        final DatagramPacket send = new DatagramPacket(sendBytes, sendBytes.length);
        final DatagramPacket receive = new DatagramPacket(new byte[20], 20);
        ds.send(send);
        ds.setSoTimeout(2000);
        ds.receive(receive);
        ds.close();

        assertPacketDataEquals(send, receive);
        assertEquals(Inet6Address.LOOPBACK, receive.getAddress());

        server.stopServer();
        broken.stopServer();
    }

    // Validate that we can connect/disconnect then send/recv to any address
    public void testConnect_connectDisconnectThenSendRecv() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);

        final DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        server.start();

        final int serverPortNumber = server.getPort();
        ds.connect(Inet6Address.LOOPBACK, serverPortNumber);
        ds.disconnect();

        final byte[] sendBytes = { 'T', 'e', 's', 't', 0 };
        final DatagramPacket send = new DatagramPacket(sendBytes, sendBytes.length,
                Inet6Address.LOOPBACK, serverPortNumber);
        final DatagramPacket receive = new DatagramPacket(new byte[20], 20);
        ds.send(send);
        ds.setSoTimeout(2000);
        ds.receive(receive);
        ds.close();

        assertPacketDataEquals(send, receive);
        assertEquals(Inet6Address.LOOPBACK, receive.getAddress());

        server.stopServer();
    }

    public void testConnect_connectTwice() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);

        final DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        final DatagramServer broken = new DatagramServer(Inet6Address.LOOPBACK);
        server.start();
        broken.start();

        final int serverPortNumber = server.getPort();
        ds.connect(Inet6Address.LOOPBACK, broken.getPort());
        ds.connect(Inet6Address.LOOPBACK, serverPortNumber);
        ds.disconnect();

        final byte[] sendBytes = { 'T', 'e', 's', 't', 0 };
        final DatagramPacket send = new DatagramPacket(sendBytes, sendBytes.length,
                Inet6Address.LOOPBACK, serverPortNumber);
        final DatagramPacket receive = new DatagramPacket(new byte[20], 20);
        ds.send(send);
        ds.setSoTimeout(2000);
        ds.receive(receive);
        ds.close();

        assertPacketDataEquals(send, receive);
        assertEquals(Inet6Address.LOOPBACK, receive.getAddress());

        server.stopServer();
        broken.stopServer();
    }

    public void testConnect_zeroAddress() throws Exception {
        DatagramSocket ds = new DatagramSocket();
        byte[] addressBytes = { 0, 0, 0, 0 };
        InetAddress inetAddress = InetAddress.getByAddress(addressBytes);
        ds.connect(inetAddress, 0);

        ds = new java.net.DatagramSocket();
        byte[] addressTestBytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0 };
        inetAddress = InetAddress.getByAddress(addressTestBytes);
        ds.connect(inetAddress, 0);
    }

    public void test_disconnect() throws Exception {
        DatagramSocket ds = new DatagramSocket();
        InetAddress inetAddress = InetAddress.getLocalHost();
        ds.connect(inetAddress, 0);
        ds.disconnect();
        assertNull("Incorrect InetAddress", ds.getInetAddress());
        assertEquals("Incorrect Port", -1, ds.getPort());

        ds = new DatagramSocket();
        inetAddress = InetAddress.getByName("FE80:0000:0000:0000:020D:60FF:FE0F:A776%4");
        ds.connect(inetAddress, 0);
        ds.disconnect();
        assertNull("Incorrect InetAddress", ds.getInetAddress());
        assertEquals("Incorrect Port", -1, ds.getPort());
    }

    public void test_getLocalAddress() throws Exception {
        // Test for method java.net.InetAddress
        // java.net.DatagramSocket.getLocalAddress()
        InetAddress local = InetAddress.getLocalHost();
        DatagramSocket ds = new java.net.DatagramSocket(0, local);
        assertEquals(InetAddress.getByName(InetAddress.getLocalHost().getHostName()), ds.getLocalAddress());

        // now check behavior when the ANY address is returned
        DatagramSocket s = new DatagramSocket(0);
        assertTrue("ANY address not IPv6: " + s.getLocalSocketAddress(), s.getLocalAddress() instanceof Inet6Address);
        s.close();
    }

    public void test_getLocalPort() throws SocketException {
        DatagramSocket ds = new DatagramSocket();
        assertTrue("Returned incorrect port", ds.getLocalPort() != 0);
    }

    public void test_getPort() throws IOException {
        DatagramSocket theSocket = new DatagramSocket();
        assertEquals("Expected -1 for remote port as not connected", -1,
                theSocket.getPort());

        // Now connect the socket and validate that we get the right port
        int portNumber = 49152; // any valid port, even if it is unreachable
        theSocket.connect(InetAddress.getLocalHost(), portNumber);
        assertEquals("getPort returned wrong value", portNumber, theSocket
                .getPort());
    }

    public void test_getReceiveBufferSize() throws Exception {
        DatagramSocket ds = new DatagramSocket();
        ds.setReceiveBufferSize(130);
        assertTrue("Incorrect buffer size", ds.getReceiveBufferSize() >= 130);
        ds.close();
        try {
            ds.getReceiveBufferSize();
            fail("SocketException was not thrown.");
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_getSendBufferSize() throws Exception {
        final DatagramSocket ds = new java.net.DatagramSocket(0);
        ds.setSendBufferSize(134);
        assertTrue("Incorrect buffer size", ds.getSendBufferSize() >= 134);
        ds.close();
        try {
            ds.getSendBufferSize();
            fail("SocketException was not thrown.");
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_getSoTimeout() throws Exception {
        DatagramSocket ds = new DatagramSocket();
        ds.setSoTimeout(100);
        assertEquals("Returned incorrect timeout", 100, ds.getSoTimeout());
    }

    static final class TestDatagramSocketImpl extends DatagramSocketImpl {
        // This field exists solely to force initialization of this class
        // inside a test method.
        public static final Object ACCESS = new Object();

        @Override
        protected void create() throws SocketException {
        }

        @Override
        protected void bind(int arg0, InetAddress arg1)
                throws SocketException {
        }

        @Override
        protected void send(DatagramPacket arg0) throws IOException {
        }

        @Override
        protected int peek(InetAddress arg0) throws IOException {
            return 0;
        }

        @Override
        protected int peekData(DatagramPacket arg0) throws IOException {
            return 0;
        }

        @Override
        protected void receive(DatagramPacket arg0) throws IOException {
        }

        @Override
        protected void setTTL(byte arg0) throws IOException {
        }

        @Override
        protected byte getTTL() throws IOException {
            return 0;
        }

        @Override
        protected void setTimeToLive(int arg0) throws IOException {
        }

        @Override
        protected int getTimeToLive() throws IOException {
            return 0;
        }

        @Override
        protected void join(InetAddress arg0) throws IOException {
        }

        @Override
        protected void joinGroup(SocketAddress addr, NetworkInterface netInterface) throws IOException {

        }

        @Override
        protected void leave(InetAddress arg0) throws IOException {
        }

        @Override
        protected void leaveGroup(SocketAddress arg0, NetworkInterface arg1)
                throws IOException {
        }

        @Override
        protected void close() {
        }

        public void setOption(int arg0, Object arg1) throws SocketException {
        }

        public Object getOption(int arg0) throws SocketException {
            return null;
        }
    }

    static final class TestDatagramSocket extends DatagramSocket {
        // This field exists solely to force initialization of this class
        // inside a test method.
        public static final Object ACCESS = new Object();

        public TestDatagramSocket(DatagramSocketImpl impl) {
            super(impl);
        }
    }


    public void testArchivedHarmonyRegressions() throws Exception {
        // Regression for HARMONY-1118
        assertNotNull(TestDatagramSocketImpl.ACCESS);
        assertNotNull(TestDatagramSocket.ACCESS);

        // Regression test for Harmony-2938
        InetAddress i = InetAddress.getByName("127.0.0.1");
        DatagramSocket d = new DatagramSocket(0, i);
        try {
            d.send(new DatagramPacket(new byte[] { 1 }, 1));
            fail();
        } catch (NullPointerException expected) {
        } finally {
            d.close();
        }

        // Regression test for Harmony-6413
        InetSocketAddress addr = InetSocketAddress.createUnresolved(
                "localhost", 0);
        try {
            new DatagramPacket(new byte[272], 3, addr);
            fail();
        } catch (IllegalArgumentException expected) {
        }
    }

    public void test_sendLjava_net_DatagramPacket_nullDestination() throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(0);
        byte[] data = { 65 };
        DatagramPacket sendPacket = new DatagramPacket(data, data.length, null, 25000);
        try {
            datagramSocket.send(sendPacket);
            fail();
        } catch (NullPointerException expected) {
            // Expected
        } finally {
            datagramSocket.close();
        }

    }

    public void test_setSendBufferSizeI() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);
        ds.setSendBufferSize(134);
        assertTrue("Incorrect buffer size", ds.getSendBufferSize() >= 134);
        ds.close();
        try {
            ds.setSendBufferSize(1);
            fail("SocketException was not thrown.");
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_setReceiveBufferSizeI() throws Exception {
        final DatagramSocket ds = new DatagramSocket(0);
        ds.setReceiveBufferSize(130);
        assertTrue("Incorrect buffer size", ds.getReceiveBufferSize() >= 130);

        try {
            ds.setReceiveBufferSize(0);
            fail("IllegalArgumentException was not thrown.");
        } catch(IllegalArgumentException iae) {
            //expected
        }

        try {
            ds.setReceiveBufferSize(-1);
            fail("IllegalArgumentException was not thrown.");
        } catch(IllegalArgumentException iae) {
            //expected
        }

        ds.close();

        try {
            ds.setReceiveBufferSize(1);
            fail("SocketException was not thrown.");
        } catch (SocketException e) {
            //expected
        }
    }


    public void test_ConstructorLjava_net_DatagramSocketImpl() {
        class SimpleTestDatagramSocket extends DatagramSocket {
            public SimpleTestDatagramSocket(DatagramSocketImpl impl) {
                super(impl);
            }
        }

        try {
            new SimpleTestDatagramSocket(null);
            fail("exception expected");
        } catch (NullPointerException ex) {
            // expected
        }
    }

    public void test_ConstructorLjava_net_SocketAddress() throws Exception {
        class UnsupportedSocketAddress extends SocketAddress {
            public UnsupportedSocketAddress() {
            }
        }

        DatagramSocket ds = new DatagramSocket(new InetSocketAddress(
                InetAddress.getLocalHost(), 0));
        assertTrue(ds.getBroadcast());
        assertTrue("Created socket with incorrect port", ds.getLocalPort() != 0);
        assertEquals("Created socket with incorrect address", InetAddress
                .getLocalHost(), ds.getLocalAddress());

        try {
            ds = new java.net.DatagramSocket(new UnsupportedSocketAddress());
            fail("No exception when constructing datagramSocket with unsupported SocketAddress type");
        } catch (IllegalArgumentException e) {
            // Expected
        }

        // regression for HARMONY-894
        ds = new DatagramSocket(null);
        assertTrue(ds.getBroadcast());
    }


    public void test_bindLjava_net_SocketAddress_null() throws Exception {
        // validate if we pass in null that it picks an address for us.
        DatagramSocket theSocket = new DatagramSocket((SocketAddress) null);
        theSocket.bind(null);
        assertNotNull(theSocket.getLocalSocketAddress());
        theSocket.close();
    }

    public void test_bindLjava_net_SocketAddress_address_in_use() throws Exception {
        DatagramSocket socket1 = new DatagramSocket(0);
        try {
            new DatagramSocket(socket1.getLocalPort());
            fail();
        } catch (SocketException expected) {
        }
        socket1.close();
    }

    public void test_bindLjava_net_SocketAddress_unsupported_address_type() throws Exception {
        class mySocketAddress extends SocketAddress {
            public mySocketAddress() {
            }
        }

        // unsupported SocketAddress subclass
        DatagramSocket theSocket = new DatagramSocket((SocketAddress) null);
        try {
            theSocket.bind(new mySocketAddress());
            fail("No exception when binding using unsupported SocketAddress subclass");
        } catch (IllegalArgumentException expected) {
        }
        theSocket.close();
    }

    public void test_isBound() throws Exception {
        DatagramSocket theSocket = new DatagramSocket(0);
        assertTrue(theSocket.isBound());
        theSocket.close();

        theSocket = new DatagramSocket(new InetSocketAddress(Inet6Address.LOOPBACK, 0));
        assertTrue(theSocket.isBound());
        theSocket.close();

        theSocket = new DatagramSocket(null);
        assertFalse(theSocket.isBound());
        theSocket.close();

        // connect causes implicit bind
        theSocket = new DatagramSocket(null);
        theSocket.connect(new InetSocketAddress(Inet6Address.LOOPBACK, 0));
        assertTrue(theSocket.isBound());
        theSocket.close();

        // now test when we bind explicitely
        InetSocketAddress theLocalAddress = new InetSocketAddress(Inet6Address.LOOPBACK, 0);
        theSocket = new DatagramSocket(null);
        assertFalse(theSocket.isBound());
        theSocket.bind(theLocalAddress);
        assertTrue(theSocket.isBound());
        theSocket.close();
        assertTrue(theSocket.isBound());
    }

    public void test_isConnected() throws Exception {
        DatagramServer ds = new DatagramServer(Inet6Address.LOOPBACK);

        // base test
        DatagramSocket theSocket = new DatagramSocket(0);
        assertFalse(theSocket.isConnected());
        theSocket.connect(new InetSocketAddress(Inet6Address.LOOPBACK, ds.getPort()));
        assertTrue(theSocket.isConnected());

        // reconnect the socket and make sure we get the right answer
        theSocket.connect(new InetSocketAddress(Inet6Address.LOOPBACK, ds.getPort()));
        assertTrue(theSocket.isConnected());

        // now disconnect the socket and make sure we get the right answer
        theSocket.disconnect();
        assertFalse(theSocket.isConnected());
        theSocket.close();

        // now check behavior when socket is closed when connected
        theSocket = new DatagramSocket(0);
        theSocket.connect(new InetSocketAddress(Inet6Address.LOOPBACK, ds.getPort()));
        theSocket.close();
        assertTrue(theSocket.isConnected());
    }

    public void test_getRemoteSocketAddress() throws Exception {
        DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        DatagramSocket s = new DatagramSocket(0);
        s.connect(new InetSocketAddress(Inet6Address.LOOPBACK, server.getPort()));

        assertEquals(new InetSocketAddress(Inet6Address.LOOPBACK, server.getPort()),
                s.getRemoteSocketAddress());
        s.close();

        // now create one that is not connected and validate that we get the
        // right answer
        DatagramSocket theSocket = new DatagramSocket(null);
        theSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 0));
        assertNull(theSocket.getRemoteSocketAddress());

        // now connect and validate we get the right answer
        theSocket.connect(new InetSocketAddress(Inet6Address.LOOPBACK, server.getPort()));
        assertEquals(new InetSocketAddress(Inet6Address.LOOPBACK, server.getPort()),
                theSocket.getRemoteSocketAddress());
        theSocket.close();
    }

    public void test_getLocalSocketAddress_late_bind() throws Exception {
        // An unbound socket should return null as its local address.
        DatagramSocket theSocket = new DatagramSocket((SocketAddress) null);
        assertNull(theSocket.getLocalSocketAddress());

        // now bind the socket and make sure we get the right answer
        InetSocketAddress localAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
        theSocket.bind(localAddress);
        assertEquals(localAddress.getAddress(), theSocket.getLocalAddress());
        assertTrue(theSocket.getLocalPort() > 0);
        theSocket.close();
    }

    public void test_getLocalSocketAddress_unbound() throws Exception {
        InetSocketAddress localAddress1 = new InetSocketAddress(InetAddress.getLocalHost(), 0);
        DatagramSocket s = new DatagramSocket(localAddress1);
        assertEquals(localAddress1.getAddress(), s.getLocalAddress());
        s.close();

        InetSocketAddress remoteAddress = (InetSocketAddress) s.getRemoteSocketAddress();
        assertNull(remoteAddress);
    }

    public void test_getLocalSocketAddress_ANY() throws Exception {
        DatagramSocket s = new DatagramSocket(0);
        assertEquals("ANY address not IPv6: " + s.getLocalSocketAddress(),
                Inet6Address.ANY, s.getLocalAddress());
        s.close();
        s = new DatagramSocket(0, null);
        assertEquals(Inet6Address.ANY, s.getLocalAddress());
        assertFalse(0 == s.getLocalPort());
        s.close();
    }

    public void test_setReuseAddressZ() throws Exception {
        // test case were we set it to false
        DatagramSocket theSocket1 = null;
        DatagramSocket theSocket2 = null;
        try {
            InetSocketAddress theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
            theSocket1 = new DatagramSocket(null);
            theSocket2 = new DatagramSocket(null);
            theSocket1.setReuseAddress(false);
            theSocket2.setReuseAddress(false);
            theSocket1.bind(theAddress);
            theSocket2.bind(new InetSocketAddress(InetAddress.getLocalHost(), theSocket1.getLocalPort()));
            fail();
        } catch (BindException expected) {
        }
        if (theSocket1 != null) {
            theSocket1.close();
        }
        if (theSocket2 != null) {
            theSocket2.close();
        }

        // test case were we set it to true
        InetSocketAddress theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
        theSocket1 = new DatagramSocket(null);
        theSocket2 = new DatagramSocket(null);
        theSocket1.setReuseAddress(true);
        theSocket2.setReuseAddress(true);
        theSocket1.bind(theAddress);
        theSocket2.bind(new InetSocketAddress(InetAddress.getLocalHost(), theSocket1.getLocalPort()));

        if (theSocket1 != null) {
            theSocket1.close();
        }
        if (theSocket2 != null) {
            theSocket2.close();
        }

        // test the default case which we expect to be the same on all
        // platforms
        try {
            theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
            theSocket1 = new DatagramSocket(null);
            theSocket2 = new DatagramSocket(null);
            theSocket1.bind(theAddress);
            theSocket2.bind(new InetSocketAddress(InetAddress.getLocalHost(), theSocket1.getLocalPort()));
            fail("No exception when trying to connect to do duplicate socket bind with re-useaddr left as default");
        } catch (BindException expected) {
        }
        if (theSocket1 != null) {
            theSocket1.close();
        }
        if (theSocket2 != null) {
            theSocket2.close();
        }

        try {
            theSocket1.setReuseAddress(true);
            fail("SocketException was not thrown.");
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_getReuseAddress() throws Exception {
        DatagramSocket theSocket = new DatagramSocket();
        theSocket.setReuseAddress(true);
        assertTrue("getReuseAddress false when it should be true", theSocket.getReuseAddress());
        theSocket.setReuseAddress(false);
        assertFalse("getReuseAddress true when it should be False", theSocket.getReuseAddress());
        theSocket.close();
        try {
            theSocket.getReuseAddress();
            fail("SocketException was not thrown.");
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_setBroadcastZ() throws Exception {
        DatagramSocket theSocket = new DatagramSocket(0);
        theSocket.setBroadcast(false);
        byte theBytes[] = { -1, -1, -1, -1 };

        // validate we cannot connect to the broadcast address when
        // setBroadcast is false
        try {
            theSocket.connect(new InetSocketAddress(InetAddress.getByAddress(theBytes), 0));
            fail();
        } catch (Exception expected) {
        }

        // now validate that we can connect to the broadcast address when
        // setBroadcast is true
        theSocket.setBroadcast(true);
        theSocket.connect(new InetSocketAddress(InetAddress.getByAddress(theBytes), 0));

        theSocket.close();
        try {
            theSocket.setBroadcast(false);
            fail();
        } catch(SocketException se) {
            //expected
        }
    }

    public void test_getBroadcast() throws Exception {
        DatagramSocket theSocket = new DatagramSocket();
        theSocket.setBroadcast(true);
        assertTrue("getBroadcast false when it should be true", theSocket.getBroadcast());
        theSocket.setBroadcast(false);
        assertFalse("getBroadcast true when it should be False", theSocket.getBroadcast());
    }

    public void test_setTrafficClassI() throws Exception {
        int IPTOS_LOWCOST = 0x2;
        int IPTOS_THROUGHPUT = 0x8;
        DatagramSocket theSocket = new DatagramSocket(0);

        // validate that value set must be between 0 and 255
        try {
            theSocket.setTrafficClass(256);
            fail("No exception when traffic class set to 256");
        } catch (IllegalArgumentException e) {
        }

        try {
            theSocket.setTrafficClass(-1);
            fail("No exception when traffic class set to -1");
        } catch (IllegalArgumentException e) {
        }

        // now validate that we can set it to some good values
        theSocket.setTrafficClass(IPTOS_LOWCOST);
        theSocket.setTrafficClass(IPTOS_THROUGHPUT);
    }


    public void test_isClosed() throws Exception {
        DatagramSocket theSocket = new DatagramSocket();
        // validate isClosed returns expected values
        assertFalse(theSocket.isClosed());
        theSocket.close();
        assertTrue(theSocket.isClosed());

        InetSocketAddress theAddress = new InetSocketAddress(InetAddress
                .getLocalHost(), 0);
        theSocket = new DatagramSocket(theAddress);
        assertFalse(theSocket.isClosed());
        theSocket.close();
        assertTrue(theSocket.isClosed());
    }

    public void test_getChannel() throws Exception {
        assertNull(new DatagramSocket().getChannel());

        DatagramServer server = new DatagramServer(Inet6Address.LOOPBACK);
        DatagramSocket ds = new DatagramSocket(0);
        assertNull(ds.getChannel());
        ds.disconnect();
        ds.close();
        server.stopServer();

        DatagramChannel channel = DatagramChannel.open();
        DatagramSocket socket = channel.socket();
        assertEquals(channel, socket.getChannel());
        socket.close();
    }

    public void testReceiveOversizePacket() throws Exception {
        DatagramSocket ds = new DatagramSocket(0);
        DatagramSocket sds = new DatagramSocket(0);

        DatagramPacket rdp = new DatagramPacket("0123456789".getBytes("UTF-8"),
                5, Inet6Address.LOOPBACK, ds.getLocalPort());
        sds.send(rdp);
        sds.close();

        byte[] recvBuffer = new byte[5];
        DatagramPacket receive = new DatagramPacket(recvBuffer, recvBuffer.length);
        ds.receive(receive);
        ds.close();
        assertEquals(new String("01234"), new String(recvBuffer, 0, recvBuffer.length, "UTF-8"));
    }
}
