github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/net/interface_test.go (about)

     1  // Copyright 2011 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package net
     6  
     7  import (
     8  	"reflect"
     9  	"runtime"
    10  	"testing"
    11  )
    12  
    13  // loopbackInterface returns an available logical network interface
    14  // for loopback tests.  It returns nil if no suitable interface is
    15  // found.
    16  func loopbackInterface() *Interface {
    17  	ift, err := Interfaces()
    18  	if err != nil {
    19  		return nil
    20  	}
    21  	for _, ifi := range ift {
    22  		if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 {
    23  			return &ifi
    24  		}
    25  	}
    26  	return nil
    27  }
    28  
    29  // ipv6LinkLocalUnicastAddr returns an IPv6 link-local unicast address
    30  // on the given network interface for tests. It returns "" if no
    31  // suitable address is found.
    32  func ipv6LinkLocalUnicastAddr(ifi *Interface) string {
    33  	if ifi == nil {
    34  		return ""
    35  	}
    36  	ifat, err := ifi.Addrs()
    37  	if err != nil {
    38  		return ""
    39  	}
    40  	for _, ifa := range ifat {
    41  		if ifa, ok := ifa.(*IPNet); ok {
    42  			if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() {
    43  				return ifa.IP.String()
    44  			}
    45  		}
    46  	}
    47  	return ""
    48  }
    49  
    50  type routeStats struct {
    51  	loop  int // # of active loopback interfaces
    52  	other int // # of active other interfaces
    53  
    54  	uni4, uni6     int // # of active connected unicast, anycast routes
    55  	multi4, multi6 int // # of active connected multicast route clones
    56  }
    57  
    58  func TestInterfaces(t *testing.T) {
    59  	ift, err := Interfaces()
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	var stats routeStats
    64  	for _, ifi := range ift {
    65  		ifxi, err := InterfaceByIndex(ifi.Index)
    66  		if err != nil {
    67  			t.Fatal(err)
    68  		}
    69  		if !reflect.DeepEqual(ifxi, &ifi) {
    70  			t.Errorf("got %v; want %v", ifxi, ifi)
    71  		}
    72  		ifxn, err := InterfaceByName(ifi.Name)
    73  		if err != nil {
    74  			t.Fatal(err)
    75  		}
    76  		if !reflect.DeepEqual(ifxn, &ifi) {
    77  			t.Errorf("got %v; want %v", ifxn, ifi)
    78  		}
    79  		t.Logf("%q: flags %q, ifindex %v, mtu %v", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
    80  		t.Logf("hardware address %q", ifi.HardwareAddr.String())
    81  		if ifi.Flags&FlagUp != 0 {
    82  			if ifi.Flags&FlagLoopback != 0 {
    83  				stats.loop++
    84  			} else {
    85  				stats.other++
    86  			}
    87  		}
    88  		n4, n6 := testInterfaceAddrs(t, &ifi)
    89  		stats.uni4 += n4
    90  		stats.uni6 += n6
    91  		n4, n6 = testInterfaceMulticastAddrs(t, &ifi)
    92  		stats.multi4 += n4
    93  		stats.multi6 += n6
    94  	}
    95  	switch runtime.GOOS {
    96  	case "nacl", "plan9", "solaris":
    97  	default:
    98  		// Test the existence of connected unicast routes for
    99  		// IPv4.
   100  		if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 {
   101  			t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats)
   102  		}
   103  		// Test the existence of connected unicast routes for
   104  		// IPv6. We can assume the existence of ::1/128 when
   105  		// at least one looopback interface is installed.
   106  		if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 {
   107  			t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats)
   108  		}
   109  	}
   110  	switch runtime.GOOS {
   111  	case "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris":
   112  	default:
   113  		// Test the existence of connected multicast route
   114  		// clones for IPv4. Unlike IPv6, IPv4 multicast
   115  		// capability is not a mandatory feature, and so this
   116  		// test is disabled.
   117  		//if supportsIPv4 && stats.loop > 0 && stats.uni4 > 1 && stats.multi4 == 0 {
   118  		//	t.Errorf("num IPv4 multicast route clones = 0; want >0; summary: %+v", stats)
   119  		//}
   120  		// Test the existence of connected multicast route
   121  		// clones for IPv6. Some platform never uses loopback
   122  		// interface as the nexthop for multicast routing.
   123  		// We can assume the existence of connected multicast
   124  		// route clones when at least two connected unicast
   125  		// routes, ::1/128 and other, are installed.
   126  		if supportsIPv6 && stats.loop > 0 && stats.uni6 > 1 && stats.multi6 == 0 {
   127  			t.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v", stats)
   128  		}
   129  	}
   130  }
   131  
   132  func TestInterfaceAddrs(t *testing.T) {
   133  	ift, err := Interfaces()
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	var stats routeStats
   138  	for _, ifi := range ift {
   139  		if ifi.Flags&FlagUp != 0 {
   140  			if ifi.Flags&FlagLoopback != 0 {
   141  				stats.loop++
   142  			} else {
   143  				stats.other++
   144  			}
   145  		}
   146  	}
   147  	ifat, err := InterfaceAddrs()
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	stats.uni4, stats.uni6 = testAddrs(t, ifat)
   152  	// Test the existence of connected unicast routes for IPv4.
   153  	if supportsIPv4 && stats.loop+stats.other > 0 && stats.uni4 == 0 {
   154  		t.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v", stats)
   155  	}
   156  	// Test the existence of connected unicast routes for IPv6.
   157  	// We can assume the existence of ::1/128 when at least one
   158  	// looopback interface is installed.
   159  	if supportsIPv6 && stats.loop > 0 && stats.uni6 == 0 {
   160  		t.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v", stats)
   161  	}
   162  }
   163  
   164  func testInterfaceAddrs(t *testing.T, ifi *Interface) (naf4, naf6 int) {
   165  	ifat, err := ifi.Addrs()
   166  	if err != nil {
   167  		t.Fatal(err)
   168  	}
   169  	return testAddrs(t, ifat)
   170  }
   171  
   172  func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) (nmaf4, nmaf6 int) {
   173  	ifmat, err := ifi.MulticastAddrs()
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	return testMulticastAddrs(t, ifmat)
   178  }
   179  
   180  func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
   181  	for _, ifa := range ifat {
   182  		switch ifa := ifa.(type) {
   183  		case *IPNet:
   184  			if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || ifa.IP.IsMulticast() || ifa.Mask == nil {
   185  				t.Errorf("unexpected value: %#v", ifa)
   186  				continue
   187  			}
   188  			prefixLen, maxPrefixLen := ifa.Mask.Size()
   189  			if ifa.IP.To4() != nil {
   190  				if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
   191  					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
   192  					continue
   193  				}
   194  				naf4++
   195  			} else if ifa.IP.To16() != nil {
   196  				if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
   197  					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
   198  					continue
   199  				}
   200  				naf6++
   201  			}
   202  			t.Logf("interface address %q", ifa.String())
   203  		default:
   204  			t.Errorf("unexpected type: %T", ifa)
   205  		}
   206  	}
   207  	return
   208  }
   209  
   210  func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) {
   211  	for _, ifma := range ifmat {
   212  		switch ifma := ifma.(type) {
   213  		case *IPAddr:
   214  			if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() {
   215  				t.Errorf("unexpected value: %#v", ifma)
   216  				continue
   217  			}
   218  			if ifma.IP.To4() != nil {
   219  				nmaf4++
   220  			} else if ifma.IP.To16() != nil {
   221  				nmaf6++
   222  			}
   223  			t.Logf("joined group address %q", ifma.String())
   224  		default:
   225  			t.Errorf("unexpected type: %T", ifma)
   226  		}
   227  	}
   228  	return
   229  }
   230  
   231  func BenchmarkInterfaces(b *testing.B) {
   232  	testHookUninstaller.Do(uninstallTestHooks)
   233  
   234  	for i := 0; i < b.N; i++ {
   235  		if _, err := Interfaces(); err != nil {
   236  			b.Fatal(err)
   237  		}
   238  	}
   239  }
   240  
   241  func BenchmarkInterfaceByIndex(b *testing.B) {
   242  	testHookUninstaller.Do(uninstallTestHooks)
   243  
   244  	ifi := loopbackInterface()
   245  	if ifi == nil {
   246  		b.Skip("loopback interface not found")
   247  	}
   248  	for i := 0; i < b.N; i++ {
   249  		if _, err := InterfaceByIndex(ifi.Index); err != nil {
   250  			b.Fatal(err)
   251  		}
   252  	}
   253  }
   254  
   255  func BenchmarkInterfaceByName(b *testing.B) {
   256  	testHookUninstaller.Do(uninstallTestHooks)
   257  
   258  	ifi := loopbackInterface()
   259  	if ifi == nil {
   260  		b.Skip("loopback interface not found")
   261  	}
   262  	for i := 0; i < b.N; i++ {
   263  		if _, err := InterfaceByName(ifi.Name); err != nil {
   264  			b.Fatal(err)
   265  		}
   266  	}
   267  }
   268  
   269  func BenchmarkInterfaceAddrs(b *testing.B) {
   270  	testHookUninstaller.Do(uninstallTestHooks)
   271  
   272  	for i := 0; i < b.N; i++ {
   273  		if _, err := InterfaceAddrs(); err != nil {
   274  			b.Fatal(err)
   275  		}
   276  	}
   277  }
   278  
   279  func BenchmarkInterfacesAndAddrs(b *testing.B) {
   280  	testHookUninstaller.Do(uninstallTestHooks)
   281  
   282  	ifi := loopbackInterface()
   283  	if ifi == nil {
   284  		b.Skip("loopback interface not found")
   285  	}
   286  	for i := 0; i < b.N; i++ {
   287  		if _, err := ifi.Addrs(); err != nil {
   288  			b.Fatal(err)
   289  		}
   290  	}
   291  }
   292  
   293  func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
   294  	testHookUninstaller.Do(uninstallTestHooks)
   295  
   296  	ifi := loopbackInterface()
   297  	if ifi == nil {
   298  		b.Skip("loopback interface not found")
   299  	}
   300  	for i := 0; i < b.N; i++ {
   301  		if _, err := ifi.MulticastAddrs(); err != nil {
   302  			b.Fatal(err)
   303  		}
   304  	}
   305  }