package com.bushchang.thrift.helper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.net.InetAddress;
import java.net.UnknownHostException;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;


/**
 * Tests for {@link NetworkUtils}.
 *
 * @author stevebu@stevebu.com (Steve Bush)
 * @version 1.0
 * @since <pre>03/31/2015</pre>
 */

public class NetworkUtilsTest {

    @Before
    public void before() throws Exception {
    }

    @After
    public void after() throws Exception {
    }

    /**
     * Method: getClassStatic()
     */
    @Test
    public void testGetClassStatic() throws Exception {
        Class<?> classTest = NetworkUtils.getClassStatic();

        assertThat(classTest, is(notNullValue()));
    }

    /**
     * Method: getInstance()
     */
    @Test
    public void testGetInstance() throws Exception {
        assertThat("NetworkUtils.getInstance", NetworkUtils.getInstance(), is(not(nullValue())));
    }




    private static class IPToStringResult
    {
        public int TestId;
        public String HostName;
        public InetAddress InetAddressTest;

        public IPToStringResult(int testId, String hostName)
        {
            TestId = testId;
            HostName = hostName;
            try {
                InetAddressTest = InetAddress.getByName(hostName);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    }


    // Array of IPToString used to generate test cases
    private static final IPToStringResult[] IPToStringResults = {
            new NetworkUtilsTest.IPToStringResult(1, "10.1.10.1"),
            new NetworkUtilsTest.IPToStringResult(2, "stevebu.com"),
            new NetworkUtilsTest.IPToStringResult(2, "msn.com"),
    };


    /**
     * Formats a string for displaying an alert
     *
     * @param index                 Index of Test
     * @param ipToStringResult      IPToStringResult
     * @return Formatted String for Assert
     */
    private static String formatAssert(int index, IPToStringResult ipToStringResult) {
        return String.format("%d (%s):\t", index + 1, ipToStringResult.HostName);
    }


    /**
     * Method: getMACAddress()
     */
    @Test
    public void testGetMACAddress() throws Exception {
        byte[] macAddressBytes = NetworkUtils.getMACAddress();

        assertThat(macAddressBytes, is(notNullValue()));
        assertThat(macAddressBytes.length, is(NetworkUtils.MAC_ADDRESS_DEFAULT.length));
    }

    /**
     * Method: getMACAddressAsLong()
     */
    @Test
    public void testGetMACAddressAsLong() throws Exception {
        long macAddressLong = NetworkUtils.getMACAddressAsLong();

        assertThat(macAddressLong, is(notNullValue()));
        assertNotEquals(macAddressLong, 0);
    }

    /**
     * Method: isDefaultMacAddress(byte[] macAddress)
     */
    @Test
    public void testIsDefaultMacAddress() throws Exception {
        byte[] macAddressBytes = NetworkUtils.getMACAddress();

        assertFalse(NetworkUtils.isDefaultMacAddress(macAddressBytes));
        assertThat("Mac Address is NOT default value", macAddressBytes, is(not(equalTo(NetworkUtils.MAC_ADDRESS_DEFAULT))));
    }


    /**
     * Method: inetAddressFromThriftString(String ipAddress)
     */
    @Test
    public void testInetAddressFromThriftString() throws Exception {

        for (int i = 0; i < IPToStringResults.length; i++) {

            String ipString = NetworkUtils.inetAddressToThriftString(IPToStringResults[i].InetAddressTest);

            assertThat(formatAssert(i, IPToStringResults[i]), ipString, is(IPToStringResults[i].InetAddressTest.getHostAddress()));
        }
    }


    /**
     * Method: inetAddressToThriftString(InetAddress inetAddress)
     */
    @Test
    public void testInetAddressToThriftString() throws Exception {

        InetAddress inetAddress = InetAddress.getLocalHost();

        // Round Trip IP Address to Thrift String and back
        String thriftIPAddress = NetworkUtils.inetAddressToThriftString(inetAddress);
        InetAddress inetAddressConverted = NetworkUtils.inetAddressFromThriftString(thriftIPAddress);

        assertThat(inetAddress, is(inetAddressConverted));
    }

    /**
     * @throws Exception
     */
    @Test
    public void testInetAddressToThriftBinary() throws Exception {
        InetAddress inetAddress = InetAddress.getLocalHost();

        // Round Trip IP Address to Thrift Binary and back
        byte[] thriftIPAddress = NetworkUtils.inetAddressToThriftBinary(inetAddress);
        InetAddress inetAddressConverted = NetworkUtils.inetAddressFromThriftBinary(thriftIPAddress);

        assertThat(inetAddress, is(inetAddressConverted));
    }

    /**
     * @throws Exception
     */
    @Test
    public void testInetAddressFromThriftBinary() throws Exception {

        for (int i = 0; i < IPToStringResults.length; i++) {

            byte[] ipBytes = NetworkUtils.inetAddressToThriftBinary(IPToStringResults[i].InetAddressTest);

            assertThat(formatAssert(i, IPToStringResults[i]), ipBytes, is(IPToStringResults[i].InetAddressTest.getAddress()));
        }
    }


    @Test
    public void testIntFromThriftString() throws Exception {

        for (int i = 0; i < IPToStringResults.length; i++) {

            int intIpAddress = NetworkUtils.intFromThriftString(IPToStringResults[i].HostName);

            assertThat(formatAssert(i, IPToStringResults[i]), NetworkUtils.inetAddressFromThriftInt(intIpAddress), is(IPToStringResults[i].InetAddressTest));
        }
    }

    @Test
    public void testIntFromThriftBinary() throws Exception {

        for (int i = 0; i < IPToStringResults.length; i++) {

            byte[] ipBytes = NetworkUtils.inetAddressToThriftBinary(IPToStringResults[i].InetAddressTest);

            assertThat(formatAssert(i, IPToStringResults[i]), NetworkUtils.intFromThriftBinary(ipBytes), is(NetworkUtils.intFromThriftString(IPToStringResults[i].HostName)));
        }
    }

    @Test
    public void testInetAddressFromThriftInt() throws Exception {
        for (int i = 0; i < IPToStringResults.length; i++) {

            int intIpAddress = NetworkUtils.intFromThriftString(IPToStringResults[i].HostName);

            assertThat(formatAssert(i, IPToStringResults[i]), NetworkUtils.inetAddressFromThriftInt(intIpAddress), is(IPToStringResults[i].InetAddressTest));
        }
    }
}


