/*
 *  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();
        final int timeoutSet = 100;
        ds.setSoTimeout(timeoutSet);
        int actualTimeout = ds.getSoTimeout();
        // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
        assertTrue("Returned incorrect timeout", Math.abs(actualTimeout - timeoutSet) <= 10);
    }

    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(Inet6Address.LOOPBACK, 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"));
    }
}
