net: update test cases for network interface API

This change extends existing test case to Windows for helping to fix
golang.org/issue/5395.

Change-Id: Iff077fa98ede511981df513f48d84c19375b3e04
Reviewed-on: https://go-review.googlesource.com/3304
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index efabb5f..fbf15de 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"reflect"
+	"runtime"
 	"testing"
 )
 
@@ -38,10 +39,6 @@
 	}
 	for _, ifa := range ifat {
 		switch ifa := ifa.(type) {
-		case *IPAddr:
-			if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
-				return ifa.IP.String()
-			}
 		case *IPNet:
 			if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
 				return ifa.IP.String()
@@ -52,104 +49,165 @@
 }
 
 func TestInterfaces(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("temporarily disabled until golang.org/issue/5395 is fixed")
+	}
+
 	ift, err := Interfaces()
 	if err != nil {
-		t.Fatalf("Interfaces failed: %v", err)
+		t.Fatal(err)
 	}
-	t.Logf("table: len/cap = %v/%v", len(ift), cap(ift))
-
+	var nifs, naf4, naf6, nmaf4, nmaf6 int
 	for _, ifi := range ift {
 		ifxi, err := InterfaceByIndex(ifi.Index)
 		if err != nil {
-			t.Fatalf("InterfaceByIndex(%v) failed: %v", ifi.Index, err)
+			t.Fatal(err)
 		}
 		if !reflect.DeepEqual(ifxi, &ifi) {
-			t.Fatalf("InterfaceByIndex(%v) = %v, want %v", ifi.Index, ifxi, ifi)
+			t.Errorf("got %v; want %v", ifxi, ifi)
 		}
 		ifxn, err := InterfaceByName(ifi.Name)
 		if err != nil {
-			t.Fatalf("InterfaceByName(%q) failed: %v", ifi.Name, err)
+			t.Fatal(err)
 		}
 		if !reflect.DeepEqual(ifxn, &ifi) {
-			t.Fatalf("InterfaceByName(%q) = %v, want %v", ifi.Name, ifxn, ifi)
+			t.Errorf("got %v; want %v", ifxn, ifi)
 		}
 		t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
-		t.Logf("\thardware address %q", ifi.HardwareAddr.String())
-		testInterfaceAddrs(t, &ifi)
-		testInterfaceMulticastAddrs(t, &ifi)
+		t.Logf("hardware address %q", ifi.HardwareAddr.String())
+		if ifi.Flags&FlagUp != 0 && ifi.Flags&FlagLoopback == 0 {
+			nifs++ // active interfaces except loopback interfaces
+		}
+		n4, n6 := testInterfaceAddrs(t, &ifi)
+		naf4 += n4
+		naf6 += n6
+		n4, n6 = testInterfaceMulticastAddrs(t, &ifi)
+		nmaf4 += n4
+		nmaf6 += n6
+	}
+	switch runtime.GOOS {
+	case "nacl", "plan9", "solaris":
+	default:
+		if supportsIPv4 && nifs > 0 && naf4 == 0 {
+			t.Errorf("got %v; want more than or equal to one", naf4)
+		}
+		if supportsIPv6 && nifs > 0 && naf6 == 0 {
+			t.Errorf("got %v; want more than or equal to one", naf6)
+		}
+	}
+	switch runtime.GOOS {
+	case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris":
+	default:
+		// Unlike IPv6, IPv4 multicast capability is not a
+		// mandatory feature.
+		//if supportsIPv4 && nactvifs > 0 && nmaf4 == 0 {
+		//	t.Errorf("got %v; want more than or equal to one", nmaf4)
+		//}
+		if supportsIPv6 && nifs > 0 && nmaf6 == 0 {
+			t.Errorf("got %v; want more than or equal to one", nmaf6)
+		}
 	}
 }
 
 func TestInterfaceAddrs(t *testing.T) {
-	ifat, err := InterfaceAddrs()
-	if err != nil {
-		t.Fatalf("InterfaceAddrs failed: %v", err)
+	if runtime.GOOS == "windows" {
+		t.Skip("temporarily disabled until golang.org/issue/5395 is fixed")
 	}
-	t.Logf("table: len/cap = %v/%v", len(ifat), cap(ifat))
-	testAddrs(t, ifat)
-}
 
-func testInterfaceAddrs(t *testing.T, ifi *Interface) {
-	ifat, err := ifi.Addrs()
+	ift, err := Interfaces()
 	if err != nil {
-		t.Fatalf("Interface.Addrs failed: %v", err)
+		t.Fatal(err)
 	}
-	testAddrs(t, ifat)
-}
-
-func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
-	ifmat, err := ifi.MulticastAddrs()
-	if err != nil {
-		t.Fatalf("Interface.MulticastAddrs failed: %v", err)
-	}
-	testMulticastAddrs(t, ifmat)
-}
-
-func testAddrs(t *testing.T, ifat []Addr) {
-	for _, ifa := range ifat {
-		switch ifa := ifa.(type) {
-		case *IPAddr:
-			if ifa == nil || ifa.IP == nil {
-				t.Errorf("\tunexpected value: %v, %v", ifa, ifa.IP)
-			} else {
-				t.Logf("\tinterface address %q", ifa.String())
-			}
-		case *IPNet:
-			if ifa == nil || ifa.IP == nil || ifa.Mask == nil {
-				t.Errorf("\tunexpected value: %v, %v, %v", ifa, ifa.IP, ifa.Mask)
-			} else {
-				_, prefixLen := ifa.Mask.Size()
-				if ifa.IP.To4() != nil && prefixLen != 8*IPv4len || ifa.IP.To16() != nil && ifa.IP.To4() == nil && prefixLen != 8*IPv6len {
-					t.Errorf("\tunexpected value: %v, %v, %v, %v", ifa, ifa.IP, ifa.Mask, prefixLen)
-				} else {
-					t.Logf("\tinterface address %q", ifa.String())
-				}
-			}
-		default:
-			t.Errorf("\tunexpected type: %T", ifa)
+	var nifs int
+	for _, ifi := range ift {
+		if ifi.Flags&FlagUp != 0 && ifi.Flags&FlagLoopback == 0 {
+			nifs++ // active interfaces except loopback interfaces
 		}
 	}
+	ifat, err := InterfaceAddrs()
+	if err != nil {
+		t.Fatal(err)
+	}
+	naf4, naf6 := testAddrs(t, ifat)
+	if supportsIPv4 && nifs > 0 && naf4 == 0 {
+		t.Errorf("got %v; want more than or equal to one", naf4)
+	}
+	if supportsIPv6 && nifs > 0 && naf6 == 0 {
+		t.Errorf("got %v; want more than or equal to one", naf6)
+	}
 }
 
-func testMulticastAddrs(t *testing.T, ifmat []Addr) {
+func testInterfaceAddrs(t *testing.T, ifi *Interface) (naf4, naf6 int) {
+	ifat, err := ifi.Addrs()
+	if err != nil {
+		t.Fatal(err)
+	}
+	return testAddrs(t, ifat)
+}
+
+func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) (nmaf4, nmaf6 int) {
+	ifmat, err := ifi.MulticastAddrs()
+	if err != nil {
+		t.Fatal(err)
+	}
+	return testMulticastAddrs(t, ifmat)
+}
+
+func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
+	for _, ifa := range ifat {
+		switch ifa := ifa.(type) {
+		case *IPNet:
+			if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || ifa.IP.IsMulticast() || ifa.Mask == nil {
+				t.Errorf("unexpected value: %#v", ifa)
+				continue
+			}
+			prefixLen, maxPrefixLen := ifa.Mask.Size()
+			if ifa.IP.To4() != nil {
+				if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
+					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+					continue
+				}
+				naf4++
+			} else if ifa.IP.To16() != nil {
+				if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
+					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+					continue
+				}
+				naf6++
+			}
+			t.Logf("interface address %q", ifa.String())
+		default:
+			t.Errorf("unexpected type: %T", ifa)
+		}
+	}
+	return
+}
+
+func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) {
 	for _, ifma := range ifmat {
 		switch ifma := ifma.(type) {
 		case *IPAddr:
-			if ifma == nil {
-				t.Errorf("\tunexpected value: %v", ifma)
-			} else {
-				t.Logf("\tjoined group address %q", ifma.String())
+			if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() {
+				t.Errorf("unexpected value: %#v", ifma)
+				continue
 			}
+			if ifma.IP.To4() != nil {
+				nmaf4++
+			} else if ifma.IP.To16() != nil {
+				nmaf6++
+			}
+			t.Logf("joined group address %q", ifma.String())
 		default:
-			t.Errorf("\tunexpected type: %T", ifma)
+			t.Errorf("unexpected type: %T", ifma)
 		}
 	}
+	return
 }
 
 func BenchmarkInterfaces(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		if _, err := Interfaces(); err != nil {
-			b.Fatalf("Interfaces failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }
@@ -161,7 +219,7 @@
 	}
 	for i := 0; i < b.N; i++ {
 		if _, err := InterfaceByIndex(ifi.Index); err != nil {
-			b.Fatalf("InterfaceByIndex failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }
@@ -173,7 +231,7 @@
 	}
 	for i := 0; i < b.N; i++ {
 		if _, err := InterfaceByName(ifi.Name); err != nil {
-			b.Fatalf("InterfaceByName failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }
@@ -181,7 +239,7 @@
 func BenchmarkInterfaceAddrs(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		if _, err := InterfaceAddrs(); err != nil {
-			b.Fatalf("InterfaceAddrs failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }
@@ -193,7 +251,7 @@
 	}
 	for i := 0; i < b.N; i++ {
 		if _, err := ifi.Addrs(); err != nil {
-			b.Fatalf("Interface.Addrs failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }
@@ -205,7 +263,7 @@
 	}
 	for i := 0; i < b.N; i++ {
 		if _, err := ifi.MulticastAddrs(); err != nil {
-			b.Fatalf("Interface.MulticastAddrs failed: %v", err)
+			b.Fatal(err)
 		}
 	}
 }