package malva.java.net;

import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import malva.TestCase;

public class NetworkInterfaceTest extends TestCase {
  public static void testGetName() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      assertNotNull(iface.getName());
    }
  }

  public static void testGetInetAddresses() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      for (InetAddress addr : getInetAddresses(iface)) {
        assertNotNull(addr);
      }
    }
  }

  public static void testGetInterfaceAddresses() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      for (InterfaceAddress addr : iface.getInterfaceAddresses()) {
        assertNotNull(addr);
      }
    }
  }

  public static void testGetSubInterfacesAndGetParent() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      for (NetworkInterface subIface : Collections.list(iface.getSubInterfaces())) {
        assertNotNull(subIface);
        assertEquals(subIface.getParent(), iface);
      }
    }
  }

  public static void testGetByName() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      assertEquals(iface, NetworkInterface.getByName(iface.getName()));
    }
  }

  public static void testGetByInetAddress() throws Exception {
    Map<InetAddress, Set<NetworkInterface>> map = mapInetAddressesToNetworkInterfaces(getNetworkInterfaces());

    // Multiple network interfaces can be bound to the same address. Which one in the set is returned by
    // getByInetAddress() is not defined.
    for (InetAddress addr : map.keySet()) {
      assertTrue(map.get(addr).contains(NetworkInterface.getByInetAddress(addr)));
    }
  }


  public static void testGetMTU() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      assertTrue(iface.getMTU() > 0);
    }
  }

  public static void testIsLoopback() throws Exception {
    assertTrue (NetworkInterface.getByName("127.0.0.1").isLoopback());
    assertFalse(NetworkInterface.getByName("192.168.0.1").isLoopback());
  }

  public static void testToString() throws Exception {
    for (NetworkInterface iface : getNetworkInterfaces()) {
      assertNotNull(iface.toString());
    }
  }

  private static List<NetworkInterface> getNetworkInterfaces() throws Exception {
    return Collections.list(NetworkInterface.getNetworkInterfaces());
  }

  private static List<InetAddress> getInetAddresses(NetworkInterface iface) {
    return Collections.list(iface.getInetAddresses());
  }

  private static Map<InetAddress, Set<NetworkInterface>> mapInetAddressesToNetworkInterfaces(List<NetworkInterface> ifaces) {
    Map<InetAddress, Set<NetworkInterface>> map = new HashMap<InetAddress, Set<NetworkInterface>>();

    for (NetworkInterface iface : ifaces) {
      for (InetAddress addr : getInetAddresses(iface)) {
        Set<NetworkInterface> set = map.get(addr);
        if (set == null) {
          set = new HashSet<NetworkInterface>();
          map.put(addr, set);
        }
        set.add(iface);
      }
    }

    return map;
  }

  public static void main(String[] args) throws Exception {
    testGetName();
    testGetInetAddresses();
    testGetInterfaceAddresses();
    testGetSubInterfacesAndGetParent();
    testGetByName();
    testGetByInetAddress();
    testGetMTU();
    testToString();
  }
}

@@ -3495,115 +3495,109 @@
 tGet
-InterfaceAddresses();%0A    testGetSubInterfacesAndGetParent();%0A    testGetByName();%0A 
+ByName();%0A    testGetByInetAddress();%0A    testToString();%0A/* @since 1.6%0A
    
+ 
 testGet
-ByInet
+Interface
 Address
+es
 ();%0A
@@ -3611,34 +3611,57 @@
 tGet
-MTU();%0A    testToString();
+SubInterfacesAndGetParent();%0A    testGetMTU();%0A*/
 %0A  %7D

Disable 1.6 APIs in NetworkInterfaceTest