/*
 *  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.net.BindException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import libcore.junit.junit3.TestCaseWithRules;
import libcore.junit.util.ResourceLeakageDetector;
import org.junit.Rule;
import org.junit.rules.TestRule;

public class MulticastSocketTest extends TestCaseWithRules {
    @Rule
    public TestRule guardRule = ResourceLeakageDetector.getRule();

    private static InetAddress lookup(String s) {
        try {
            return InetAddress.getByName(s);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    // These IP addresses aren't inherently "good" or "bad"; they're just used like that.
    // We use the "good" addresses for our actual group, and the "bad" addresses are for
    // a group that we won't actually set up.

    private static InetAddress GOOD_IPv4 = lookup("224.0.0.3");
    private static InetAddress BAD_IPv4 = lookup("224.0.0.4");
    private static InetAddress GOOD_IPv6 = lookup("ff05::7:7");
    private static InetAddress BAD_IPv6 = lookup("ff05::7:8");

    private NetworkInterface loopbackInterface;
    private NetworkInterface ipv4NetworkInterface;
    private NetworkInterface ipv6NetworkInterface;
    private boolean supportsMulticast;

    @Override
    protected void setUp() throws Exception {
        // The loopback interface isn't actually useful for sending/receiving multicast messages
        // but it can be used as a dummy for tests where that does not matter.
        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
        assertNotNull(loopbackInterface);
        assertTrue(loopbackInterface.isLoopback());
        assertFalse(loopbackInterface.supportsMulticast());

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        assertNotNull(interfaces);

        // Determine if the device is marked to support multicast or not. If this propery is not
        // set we assume the device has an interface capable of supporting multicast.
        supportsMulticast = Boolean.parseBoolean(
                System.getProperty("android.cts.device.multicast", "true"));
        if (!supportsMulticast) {
            return;
        }

        while (interfaces.hasMoreElements()
                && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
            NetworkInterface nextInterface = interfaces.nextElement();
            if (willWorkForMulticast(nextInterface)) {
                Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    final InetAddress nextAddress = addresses.nextElement();
                    if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
                        ipv6NetworkInterface = nextInterface;
                    } else if (nextAddress instanceof Inet4Address
                            && ipv4NetworkInterface == null) {
                        ipv4NetworkInterface = nextInterface;
                    }
                }
            }
        }
        assertTrue("Test environment must have at least one interface capable of multicast for IPv4"
                        + " and IPv6",
                ipv4NetworkInterface != null && ipv6NetworkInterface != null);
    }

    public void test_Constructor() throws IOException {
        if (!supportsMulticast) {
            return;
        }
        // Regression test for 497.
        MulticastSocket s = new MulticastSocket();
        // Regression test for Harmony-1162.
        assertTrue(s.getReuseAddress());

        s.close();
    }

    public void test_ConstructorI() throws IOException {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket orig = new MulticastSocket();
        int port = orig.getLocalPort();
        orig.close();

        MulticastSocket dup = new MulticastSocket(port);
        // Regression test for Harmony-1162.
        assertTrue(dup.getReuseAddress());
        dup.close();
    }

    public void test_getInterface() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Validate that we get the expected response when one was not set.
        MulticastSocket mss = new MulticastSocket(0);
        // We expect an ANY address in this case.
        assertTrue(mss.getInterface().isAnyLocalAddress());

        // Validate that we get the expected response when we set via setInterface.
        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
        if (addresses.hasMoreElements()) {
            InetAddress firstAddress = (InetAddress) addresses.nextElement();
            mss.setInterface(firstAddress);
            assertEquals("getNetworkInterface did not return interface set by setInterface",
                    firstAddress, mss.getInterface());

            mss.close();
            mss = new MulticastSocket(0);
            mss.setNetworkInterface(ipv4NetworkInterface);
            assertEquals("getInterface did not return interface set by setNetworkInterface",
                    ipv4NetworkInterface, NetworkInterface.getByInetAddress(mss.getInterface()));
        }

        mss.close();
    }

    public void test_getNetworkInterface() throws IOException {
        if (!supportsMulticast) {
            return;
        }
        // Validate that we get the expected response when one was not set.
        MulticastSocket mss = new MulticastSocket(0);
        NetworkInterface theInterface = mss.getNetworkInterface();
        assertTrue(
                "network interface returned wrong network interface when not set:" + theInterface,
                theInterface.getInetAddresses().hasMoreElements());
        InetAddress firstAddress = theInterface.getInetAddresses().nextElement();
        // Validate we the first address in the network interface is the ANY address.
        assertTrue(firstAddress.isAnyLocalAddress());

        mss.setNetworkInterface(ipv4NetworkInterface);
        assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
                ipv4NetworkInterface, mss.getNetworkInterface());

        mss.setNetworkInterface(loopbackInterface);
        assertEquals(
                "getNetworkInterface did not return network interface set by second"
                        + " setNetworkInterface call",
                loopbackInterface, mss.getNetworkInterface());
        mss.close();

        if (ipv6NetworkInterface != null) {
            mss = new MulticastSocket(0);
            mss.setNetworkInterface(ipv6NetworkInterface);
            assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
                    ipv6NetworkInterface, mss.getNetworkInterface());
            mss.close();
        }

        // Validate that we get the expected response when we set via setInterface.
        mss = new MulticastSocket(0);
        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
        if (addresses.hasMoreElements()) {
            firstAddress = (InetAddress) addresses.nextElement();
            mss.setInterface(firstAddress);
            assertEquals("getNetworkInterface did not return interface set by setInterface",
                    ipv4NetworkInterface, mss.getNetworkInterface());
        }
        mss.close();
    }

    public void test_getTimeToLive() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket();
        mss.setTimeToLive(120);
        assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
        mss.setTimeToLive(220);
        assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
        mss.close();
    }

    public void test_getTTL() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket();
        mss.setTTL((byte) 120);
        assertEquals("Returned incorrect TTL", 120, mss.getTTL());
        mss.close();
    }

    public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_InetAddress(GOOD_IPv4);
    }

    public void test_joinGroupLjava_net_InetAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_InetAddress(GOOD_IPv6);
    }

    private void test_joinGroupLjava_net_InetAddress(InetAddress group) throws Exception {
        MulticastSocket receivingSocket = createReceivingSocket(0);
        receivingSocket.joinGroup(group);

        String msg = "Hello World";
        MulticastSocket sendingSocket = new MulticastSocket(receivingSocket.getLocalPort());
        InetSocketAddress groupAddress =
                new InetSocketAddress(group, receivingSocket.getLocalPort());
        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
        sendingSocket.send(sdp, (byte) 10 /* ttl */);

        DatagramPacket rdp = createReceiveDatagramPacket();
        receivingSocket.receive(rdp);
        String receivedMessage = extractMessage(rdp);
        assertEquals("Group member did not recv data", msg, receivedMessage);

        sendingSocket.close();
        receivingSocket.close();
    }

    public void test_joinGroup_null_null() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.joinGroup(null, null);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        mss.close();
    }

    public void test_joinGroup_non_multicast_address_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.joinGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
            fail();
        } catch (IOException expected) {
        }
        mss.close();
    }

    public void test_joinGroup_non_multicast_address_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.joinGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
            fail();
        } catch (IOException expected) {
        }
        mss.close();
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface()
            throws Exception {
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv4, BAD_IPv4);
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6_nullInterface()
            throws Exception {
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv6, BAD_IPv6);
    }

    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
            throws Exception {
        // Create the sending socket and specify the interface to use as needed (otherwise use the
        // default).
        MulticastSocket sendingSocket = new MulticastSocket(0);
        if (networkInterface != null) {
            sendingSocket.setNetworkInterface(networkInterface);
        }
        sendingSocket.setTimeToLive(2);

        MulticastSocket receivingSocket = createReceivingSocket(0);
        InetSocketAddress groupAddress =
                new InetSocketAddress(group, receivingSocket.getLocalPort());
        // Join the group. A null network interface is valid and means "use default".
        receivingSocket.joinGroup(groupAddress, networkInterface);

        String msg = "Hello World";
        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
        sendingSocket.send(sdp);

        DatagramPacket rdp = createReceiveDatagramPacket();
        receivingSocket.receive(rdp);
        // Now validate that we received the data as expected.
        assertEquals("Group member did not recv data", msg, extractMessage(rdp));
        receivingSocket.close();
        sendingSocket.close();

        // Create the sending socket and specify the interface to use as needed (otherwise use the
        // default).
        sendingSocket = new MulticastSocket(0);
        if (networkInterface != null) {
            sendingSocket.setNetworkInterface(networkInterface);
        }
        sendingSocket.setTimeToLive(10);

        receivingSocket = createReceivingSocket(0);
        groupAddress = new InetSocketAddress(group, receivingSocket.getLocalPort());
        // Join the group. A null network interface is valid and means "use default".
        receivingSocket.joinGroup(groupAddress, networkInterface);

        msg = "Hello World - Different Group";
        InetSocketAddress group2Address =
                new InetSocketAddress(group2, receivingSocket.getLocalPort());
        sdp = createSendDatagramPacket(group2Address, msg);
        sendingSocket.send(sdp);

        rdp = createReceiveDatagramPacket();
        try {
            receivingSocket.receive(rdp);
            fail("Expected timeout");
        } catch (SocketTimeoutException expected) {
        }

        receivingSocket.close();
        sendingSocket.close();
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Check that we can join on specific interfaces and that we only receive if data is
        // received on that interface. This test is only really useful on devices with multiple
        // non-loopback interfaces.

        List<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
        while (theInterfaces.hasMoreElements()) {
            NetworkInterface thisInterface = theInterfaces.nextElement();
            // Skip interfaces that do not support multicast - there's no point in proving
            // they cannot send / receive multicast messages.
            if (willWorkForMulticast(thisInterface)) {
                realInterfaces.add(thisInterface);
            }
        }

        for (NetworkInterface thisInterface : realInterfaces) {
            // Find a suitable group IP and interface to use to sent packets to thisInterface.
            Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();

            NetworkInterface sendingInterface = null;
            InetAddress group = null;
            if (addresses.hasMoreElements()) {
                InetAddress firstAddress = addresses.nextElement();
                if (firstAddress instanceof Inet4Address) {
                    group = GOOD_IPv4;
                    sendingInterface = ipv4NetworkInterface;
                } else {
                    // if this interface only seems to support IPV6 addresses
                    group = GOOD_IPv6;
                    sendingInterface = ipv6NetworkInterface;
                }
            }

            // Create a receivingSocket which is joined to the group and has only asked for packets
            // on thisInterface.
            MulticastSocket receivingSocket = createReceivingSocket(0);
            InetSocketAddress groupAddress =
                    new InetSocketAddress(group, receivingSocket.getLocalPort());
            receivingSocket.joinGroup(groupAddress, thisInterface);

            // Now send out a packet on sendingInterface. We should only see the packet if we send
            // it on thisInterface.
            MulticastSocket sendingSocket = new MulticastSocket(0);
            sendingSocket.setNetworkInterface(sendingInterface);
            String msg = "Hello World - Again " + thisInterface.getName();
            DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
            sendingSocket.send(sdp);

            DatagramPacket rdp = createReceiveDatagramPacket();
            try {
                receivingSocket.receive(rdp);

                // If the packet is received....
                assertEquals(thisInterface, sendingInterface);
                assertEquals("Group member did not recv data when bound on specific interface",
                        msg, extractMessage(rdp));
            } catch (SocketTimeoutException e) {
                // If the packet was not received...
                assertTrue(!thisInterface.equals(sendingInterface));
            }

            receivingSocket.close();
            sendingSocket.close();
        }
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
                ipv4NetworkInterface, GOOD_IPv4);
    }

    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
                ipv6NetworkInterface, GOOD_IPv6);
    }

    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
            NetworkInterface networkInterface, InetAddress group) throws Exception {
        // Validate that we can join the same address on two different interfaces but not on the
        // same interface.
        MulticastSocket mss = new MulticastSocket(0);
        SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
        mss.joinGroup(groupSockAddr, networkInterface);
        mss.joinGroup(groupSockAddr, loopbackInterface);
        try {
            mss.joinGroup(groupSockAddr, networkInterface);
            fail("Did not get expected exception when joining for second time on same interface");
        } catch (IOException e) {
        }
        mss.close();
    }

    public void test_leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
    }

    public void test_leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
    }

    private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
        String msg = "Hello World";
        MulticastSocket mss = new MulticastSocket(0);
        InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
        mss.send(sdp, (byte) 10 /* ttl */);
        try {
            // Try to leave a group we didn't join.
            mss.leaveGroup(group);
            fail();
        } catch (IOException expected) {
        }
        mss.close();
    }

    public void test_leaveGroup_null_null() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.leaveGroup(null, null);
            fail();
        } catch (IllegalArgumentException expected) {
        }
        mss.close();
    }

    public void test_leaveGroup_non_multicast_address_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
            fail();
        } catch (IOException expected) {
        }
        mss.close();
    }

    public void test_leaveGroup_non_multicast_address_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket(0);
        try {
            mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
            fail();
        } catch (IOException expected) {
        }
        mss.close();
    }

    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
    }

    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
            throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
    }

    private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
            throws Exception {
        SocketAddress groupSockAddr = null;
        SocketAddress groupSockAddr2 = null;

        try (MulticastSocket mss = new MulticastSocket(0)) {
            groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
            mss.joinGroup(groupSockAddr, null);
            mss.leaveGroup(groupSockAddr, null);
            try {
                mss.leaveGroup(groupSockAddr, null);
                fail("Did not get exception when trying to leave group that was already left");
            } catch (IOException expected) {
            }

            groupSockAddr2 = new InetSocketAddress(group2, mss.getLocalPort());
            mss.joinGroup(groupSockAddr, networkInterface);
            try {
                mss.leaveGroup(groupSockAddr2, networkInterface);
                fail("Did not get exception when trying to leave group that was never joined");
            } catch (IOException expected) {
            }

            mss.leaveGroup(groupSockAddr, networkInterface);

            mss.joinGroup(groupSockAddr, networkInterface);
            try {
                mss.leaveGroup(groupSockAddr, loopbackInterface);
                fail("Did not get exception when trying to leave group on wrong interface " +
                        "joined on [" + networkInterface + "] left on [" + loopbackInterface + "]");
            } catch (IOException expected) {
            }
        }
    }

    public void test_sendLjava_net_DatagramPacketB_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_sendLjava_net_DatagramPacketB(GOOD_IPv4);
    }

    public void test_sendLjava_net_DatagramPacketB_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_sendLjava_net_DatagramPacketB(GOOD_IPv6);
    }

    private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
        String msg = "Hello World";
        MulticastSocket sendingSocket = new MulticastSocket(0);
        MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
        receivingSocket.joinGroup(group);

        InetSocketAddress groupAddress = new InetSocketAddress(group, sendingSocket.getLocalPort());
        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
        sendingSocket.send(sdp, (byte) 10 /* ttl */);
        sendingSocket.close();

        DatagramPacket rdp = createReceiveDatagramPacket();
        receivingSocket.receive(rdp);
        String receivedMessage = extractMessage(rdp);
        assertEquals("Failed to send data. Received " + rdp.getLength(), msg, receivedMessage);
        receivingSocket.close();
    }

    public void test_setInterfaceLjava_net_InetAddress() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket();
        mss.setInterface(InetAddress.getLocalHost());
        InetAddress theInterface = mss.getInterface();
        // Under IPV6 we are not guaranteed to get the same address back as the address that was
        // set, all we should be guaranteed is that we get an address on the same interface.
        if (theInterface instanceof Inet6Address) {
            assertEquals("Failed to return correct interface IPV6",
                    NetworkInterface.getByInetAddress(mss.getInterface()),
                    NetworkInterface.getByInetAddress(theInterface));
        } else {
            assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() +
                    " expected: " + InetAddress.getLocalHost(),
                    mss.getInterface().equals(InetAddress.getLocalHost()));
        }
        mss.close();
    }

    public void test_setInterface_unbound_address_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setInterface_unbound_address(GOOD_IPv4);
    }

    public void test_setInterface_unbound_address_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setInterface_unbound_address(GOOD_IPv6);
    }

    // Regression test for Harmony-2410.
    private void test_setInterface_unbound_address(InetAddress address) throws Exception {
        MulticastSocket mss = new MulticastSocket();
        try {
            mss.setInterface(address);
            fail();
        } catch (SocketException expected) {
        }
        mss.close();
    }

    public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Validate that null interface is handled ok.
        MulticastSocket mss = new MulticastSocket();
        try {
            mss.setNetworkInterface(null);
            fail("No socket exception when we set then network interface with NULL");
        } catch (SocketException ex) {
        }
        mss.close();
    }

    public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Validate that we can get and set the interface.
        MulticastSocket mss = new MulticastSocket();
        mss.setNetworkInterface(ipv4NetworkInterface);
        assertEquals("Interface did not seem to be set by setNeworkInterface",
                ipv4NetworkInterface, mss.getNetworkInterface());
        mss.close();
    }

    public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
    }

    public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
    }

    private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
            throws IOException, InterruptedException {
        // Set up the receiving socket and join the group.
        Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
        while (theInterfaces.hasMoreElements()) {
            NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
            if (willWorkForMulticast(thisInterface)) {
                if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
                    MulticastSocket receivingSocket = createReceivingSocket(0);
                    InetSocketAddress groupAddress =
                            new InetSocketAddress(group, receivingSocket.getLocalPort());
                    receivingSocket.joinGroup(groupAddress, thisInterface);

                    // Send the packets on a particular interface. The source address in the
                    // received packet should be one of the addresses for the interface set.
                    MulticastSocket sendingSocket = new MulticastSocket(0);
                    sendingSocket.setNetworkInterface(thisInterface);
                    String msg = thisInterface.getName();
                    DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
                    sendingSocket.send(sdp);

                    DatagramPacket rdp = createReceiveDatagramPacket();
                    receivingSocket.receive(rdp);
                    String receivedMessage = extractMessage(rdp);
                    assertEquals("Group member did not recv data sent on a specific interface",
                            msg, receivedMessage);
                    // Stop the server.
                    receivingSocket.close();
                    sendingSocket.close();
                }
            }
        }
    }

    public void test_setTimeToLiveI() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket();
        mss.setTimeToLive(120);
        assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
        mss.setTimeToLive(220);
        assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
        mss.close();
    }

    public void test_setTTLB() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket mss = new MulticastSocket();
        mss.setTTL((byte) 120);
        assertEquals("Failed to set TTL", 120, mss.getTTL());
        mss.close();
    }

    public void test_ConstructorLjava_net_SocketAddress() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket ms = new MulticastSocket((SocketAddress) null);
        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.bind(null);
        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.close();
        assertTrue("should be closed", ms.isClosed());

        ms = new MulticastSocket(0);
        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.close();
        assertTrue("should be closed", ms.isClosed());

        ms = new MulticastSocket(0);
        assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.close();
        assertTrue("should be closed", ms.isClosed());

        try {
            new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
            fail();
        } catch (IOException expected) {
        }

        // Regression test for Harmony-1162.
        InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
        MulticastSocket s = new MulticastSocket(addr);
        assertTrue(s.getReuseAddress());
        s.close();
    }

    public void test_getLoopbackMode() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket ms = new MulticastSocket(null);
        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.getLoopbackMode();
        assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
        ms.close();
        assertTrue("should be closed", ms.isClosed());
    }

    public void test_setLoopbackModeZ() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        MulticastSocket ms = new MulticastSocket();
        ms.setLoopbackMode(true);
        assertTrue("loopback should be true", ms.getLoopbackMode());
        ms.setLoopbackMode(false);
        assertTrue("loopback should be false", !ms.getLoopbackMode());
        ms.close();
        assertTrue("should be closed", ms.isClosed());
    }

    public void test_setLoopbackModeSendReceive_IPv4() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setLoopbackModeSendReceive(GOOD_IPv4);
    }

    public void test_setLoopbackModeSendReceive_IPv6() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        test_setLoopbackModeSendReceive(GOOD_IPv6);
    }

    private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
        // Test send receive.
        final String message = "Hello, world!";

        MulticastSocket socket = new MulticastSocket(0);
        socket.setLoopbackMode(false); // false indicates doing loop back
        socket.joinGroup(group);

        // Send the datagram.
        InetSocketAddress groupAddress = new InetSocketAddress(group, socket.getLocalPort());
        DatagramPacket sendDatagram = createSendDatagramPacket(groupAddress, message);
        socket.send(sendDatagram);

        // Receive the datagram.
        DatagramPacket recvDatagram = createReceiveDatagramPacket();
        socket.setSoTimeout(5000); // Prevent eternal block in.
        socket.receive(recvDatagram);
        String recvMessage = extractMessage(recvDatagram);
        assertEquals(message, recvMessage);
        socket.close();
    }

    public void test_setReuseAddressZ() throws Exception {
        if (!supportsMulticast) {
            return;
        }
        // Test case were we to set ReuseAddress to false.
        MulticastSocket theSocket1 = new MulticastSocket(null);
        theSocket1.setReuseAddress(false);

        MulticastSocket theSocket2 = new MulticastSocket(null);
        theSocket2.setReuseAddress(false);

        InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
        theSocket1.bind(addr);
        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
        try {
            theSocket2.bind(addr);
            fail("No exception when trying to connect to do duplicate socket bind with re-useaddr"
                    + " set to false");
        } catch (BindException expected) {
        }
        theSocket1.close();
        theSocket2.close();

        // Test case were we set it to true.
        theSocket1 = new MulticastSocket(null);
        theSocket2 = new MulticastSocket(null);
        theSocket1.setReuseAddress(true);
        theSocket2.setReuseAddress(true);
        addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
        theSocket1.bind(addr);
        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
        theSocket2.bind(addr);

        theSocket1.close();
        theSocket2.close();

        // Test the default case which we expect to be the same on all platforms.
        theSocket1 = new MulticastSocket(null);
        theSocket2 = new MulticastSocket(null);
        addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
        theSocket1.bind(addr);
        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
        theSocket2.bind(addr);
        theSocket1.close();
        theSocket2.close();
    }

    private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
        return iface.isUp()
                // Typically loopback interfaces do not support multicast, but we rule them out
                // explicitly anyway.
                && !iface.isLoopback()
                // Point-to-point interfaces are known to cause problems. http://b/23279677
                && !iface.isPointToPoint()
                && iface.supportsMulticast()
                && iface.getInetAddresses().hasMoreElements();
    }

    private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
        MulticastSocket ms = new MulticastSocket(aPort);
        ms.setSoTimeout(2000);
        return ms;
    }

    private static DatagramPacket createReceiveDatagramPacket() {
        byte[] rbuf = new byte[512];
        return new DatagramPacket(rbuf, rbuf.length);
    }

    private static DatagramPacket createSendDatagramPacket(
            InetSocketAddress groupAndPort, String msg) {
        return new DatagramPacket(
                msg.getBytes(), msg.length(), groupAndPort.getAddress(), groupAndPort.getPort());
    }

    private static String extractMessage(DatagramPacket rdp) {
        return new String(rdp.getData(), 0, rdp.getLength());
    }
}
