github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 // +build !js 6 7 package net 8 9 import ( 10 "fmt" 11 "reflect" 12 "runtime" 13 "testing" 14 ) 15 16 // loopbackInterface returns an available logical network interface 17 // for loopback tests. It returns nil if no suitable interface is 18 // found. 19 func loopbackInterface() *Interface { 20 ift, err := Interfaces() 21 if err != nil { 22 return nil 23 } 24 for _, ifi := range ift { 25 if ifi.Flags&FlagLoopback != 0 && ifi.Flags&FlagUp != 0 { 26 return &ifi 27 } 28 } 29 return nil 30 } 31 32 // ipv6LinkLocalUnicastAddr returns an IPv6 link-local unicast address 33 // on the given network interface for tests. It returns "" if no 34 // suitable address is found. 35 func ipv6LinkLocalUnicastAddr(ifi *Interface) string { 36 if ifi == nil { 37 return "" 38 } 39 ifat, err := ifi.Addrs() 40 if err != nil { 41 return "" 42 } 43 for _, ifa := range ifat { 44 if ifa, ok := ifa.(*IPNet); ok { 45 if ifa.IP.To4() == nil && ifa.IP.IsLinkLocalUnicast() { 46 return ifa.IP.String() 47 } 48 } 49 } 50 return "" 51 } 52 53 func TestInterfaces(t *testing.T) { 54 ift, err := Interfaces() 55 if err != nil { 56 t.Fatal(err) 57 } 58 for _, ifi := range ift { 59 ifxi, err := InterfaceByIndex(ifi.Index) 60 if err != nil { 61 t.Fatal(err) 62 } 63 switch runtime.GOOS { 64 case "solaris": 65 if ifxi.Index != ifi.Index { 66 t.Errorf("got %v; want %v", ifxi, ifi) 67 } 68 default: 69 if !reflect.DeepEqual(ifxi, &ifi) { 70 t.Errorf("got %v; want %v", ifxi, ifi) 71 } 72 } 73 ifxn, err := InterfaceByName(ifi.Name) 74 if err != nil { 75 t.Fatal(err) 76 } 77 if !reflect.DeepEqual(ifxn, &ifi) { 78 t.Errorf("got %v; want %v", ifxn, ifi) 79 } 80 t.Logf("%s: flags=%v index=%d mtu=%d hwaddr=%v", ifi.Name, ifi.Flags, ifi.Index, ifi.MTU, ifi.HardwareAddr) 81 } 82 } 83 84 func TestInterfaceAddrs(t *testing.T) { 85 ift, err := Interfaces() 86 if err != nil { 87 t.Fatal(err) 88 } 89 ifStats := interfaceStats(ift) 90 ifat, err := InterfaceAddrs() 91 if err != nil { 92 t.Fatal(err) 93 } 94 uniStats, err := validateInterfaceUnicastAddrs(ifat) 95 if err != nil { 96 t.Fatal(err) 97 } 98 if err := checkUnicastStats(ifStats, uniStats); err != nil { 99 t.Fatal(err) 100 } 101 } 102 103 func TestInterfaceUnicastAddrs(t *testing.T) { 104 ift, err := Interfaces() 105 if err != nil { 106 t.Fatal(err) 107 } 108 ifStats := interfaceStats(ift) 109 if err != nil { 110 t.Fatal(err) 111 } 112 var uniStats routeStats 113 for _, ifi := range ift { 114 ifat, err := ifi.Addrs() 115 if err != nil { 116 t.Fatal(ifi, err) 117 } 118 stats, err := validateInterfaceUnicastAddrs(ifat) 119 if err != nil { 120 t.Fatal(ifi, err) 121 } 122 uniStats.ipv4 += stats.ipv4 123 uniStats.ipv6 += stats.ipv6 124 } 125 if err := checkUnicastStats(ifStats, &uniStats); err != nil { 126 t.Fatal(err) 127 } 128 } 129 130 func TestInterfaceMulticastAddrs(t *testing.T) { 131 ift, err := Interfaces() 132 if err != nil { 133 t.Fatal(err) 134 } 135 ifStats := interfaceStats(ift) 136 ifat, err := InterfaceAddrs() 137 if err != nil { 138 t.Fatal(err) 139 } 140 uniStats, err := validateInterfaceUnicastAddrs(ifat) 141 if err != nil { 142 t.Fatal(err) 143 } 144 var multiStats routeStats 145 for _, ifi := range ift { 146 ifmat, err := ifi.MulticastAddrs() 147 if err != nil { 148 t.Fatal(ifi, err) 149 } 150 stats, err := validateInterfaceMulticastAddrs(ifmat) 151 if err != nil { 152 t.Fatal(ifi, err) 153 } 154 multiStats.ipv4 += stats.ipv4 155 multiStats.ipv6 += stats.ipv6 156 } 157 if err := checkMulticastStats(ifStats, uniStats, &multiStats); err != nil { 158 t.Fatal(err) 159 } 160 } 161 162 type ifStats struct { 163 loop int // # of active loopback interfaces 164 other int // # of active other interfaces 165 } 166 167 func interfaceStats(ift []Interface) *ifStats { 168 var stats ifStats 169 for _, ifi := range ift { 170 if ifi.Flags&FlagUp != 0 { 171 if ifi.Flags&FlagLoopback != 0 { 172 stats.loop++ 173 } else { 174 stats.other++ 175 } 176 } 177 } 178 return &stats 179 } 180 181 type routeStats struct { 182 ipv4, ipv6 int // # of active connected unicast, anycast or multicast routes 183 } 184 185 func validateInterfaceUnicastAddrs(ifat []Addr) (*routeStats, error) { 186 // Note: BSD variants allow assigning any IPv4/IPv6 address 187 // prefix to IP interface. For example, 188 // - 0.0.0.0/0 through 255.255.255.255/32 189 // - ::/0 through ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128 190 // In other words, there is no tightly-coupled combination of 191 // interface address prefixes and connected routes. 192 stats := new(routeStats) 193 for _, ifa := range ifat { 194 switch ifa := ifa.(type) { 195 case *IPNet: 196 if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() || ifa.Mask == nil { 197 return nil, fmt.Errorf("unexpected value: %#v", ifa) 198 } 199 if len(ifa.IP) != IPv6len { 200 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa) 201 } 202 prefixLen, maxPrefixLen := ifa.Mask.Size() 203 if ifa.IP.To4() != nil { 204 if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len { 205 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa) 206 } 207 if ifa.IP.IsLoopback() && prefixLen < 8 { // see RFC 1122 208 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa) 209 } 210 stats.ipv4++ 211 } 212 if ifa.IP.To16() != nil && ifa.IP.To4() == nil { 213 if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len { 214 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa) 215 } 216 if ifa.IP.IsLoopback() && prefixLen != 8*IPv6len { // see RFC 4291 217 return nil, fmt.Errorf("unexpected prefix length: %d/%d for %#v", prefixLen, maxPrefixLen, ifa) 218 } 219 stats.ipv6++ 220 } 221 case *IPAddr: 222 if ifa == nil || ifa.IP == nil || ifa.IP.IsMulticast() { 223 return nil, fmt.Errorf("unexpected value: %#v", ifa) 224 } 225 if len(ifa.IP) != IPv6len { 226 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa) 227 } 228 if ifa.IP.To4() != nil { 229 stats.ipv4++ 230 } 231 if ifa.IP.To16() != nil && ifa.IP.To4() == nil { 232 stats.ipv6++ 233 } 234 default: 235 return nil, fmt.Errorf("unexpected type: %T", ifa) 236 } 237 } 238 return stats, nil 239 } 240 241 func validateInterfaceMulticastAddrs(ifat []Addr) (*routeStats, error) { 242 stats := new(routeStats) 243 for _, ifa := range ifat { 244 switch ifa := ifa.(type) { 245 case *IPAddr: 246 if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || !ifa.IP.IsMulticast() { 247 return nil, fmt.Errorf("unexpected value: %#v", ifa) 248 } 249 if len(ifa.IP) != IPv6len { 250 return nil, fmt.Errorf("should be internal representation either IPv6 or IPv4-mapped IPv6 address: %#v", ifa) 251 } 252 if ifa.IP.To4() != nil { 253 stats.ipv4++ 254 } 255 if ifa.IP.To16() != nil && ifa.IP.To4() == nil { 256 stats.ipv6++ 257 } 258 default: 259 return nil, fmt.Errorf("unexpected type: %T", ifa) 260 } 261 } 262 return stats, nil 263 } 264 265 func checkUnicastStats(ifStats *ifStats, uniStats *routeStats) error { 266 // Test the existence of connected unicast routes for IPv4. 267 if supportsIPv4() && ifStats.loop+ifStats.other > 0 && uniStats.ipv4 == 0 { 268 return fmt.Errorf("num IPv4 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats) 269 } 270 // Test the existence of connected unicast routes for IPv6. 271 // We can assume the existence of ::1/128 when at least one 272 // loopback interface is installed. 273 if supportsIPv6() && ifStats.loop > 0 && uniStats.ipv6 == 0 { 274 return fmt.Errorf("num IPv6 unicast routes = 0; want >0; summary: %+v, %+v", ifStats, uniStats) 275 } 276 return nil 277 } 278 279 func checkMulticastStats(ifStats *ifStats, uniStats, multiStats *routeStats) error { 280 switch runtime.GOOS { 281 case "aix", "dragonfly", "nacl", "netbsd", "openbsd", "plan9", "solaris": 282 default: 283 // Test the existence of connected multicast route 284 // clones for IPv4. Unlike IPv6, IPv4 multicast 285 // capability is not a mandatory feature, and so IPv4 286 // multicast validation is ignored and we only check 287 // IPv6 below. 288 // 289 // Test the existence of connected multicast route 290 // clones for IPv6. Some platform never uses loopback 291 // interface as the nexthop for multicast routing. 292 // We can assume the existence of connected multicast 293 // route clones when at least two connected unicast 294 // routes, ::1/128 and other, are installed. 295 if supportsIPv6() && ifStats.loop > 0 && uniStats.ipv6 > 1 && multiStats.ipv6 == 0 { 296 return fmt.Errorf("num IPv6 multicast route clones = 0; want >0; summary: %+v, %+v, %+v", ifStats, uniStats, multiStats) 297 } 298 } 299 return nil 300 } 301 302 func BenchmarkInterfaces(b *testing.B) { 303 testHookUninstaller.Do(uninstallTestHooks) 304 305 for i := 0; i < b.N; i++ { 306 if _, err := Interfaces(); err != nil { 307 b.Fatal(err) 308 } 309 } 310 } 311 312 func BenchmarkInterfaceByIndex(b *testing.B) { 313 testHookUninstaller.Do(uninstallTestHooks) 314 315 ifi := loopbackInterface() 316 if ifi == nil { 317 b.Skip("loopback interface not found") 318 } 319 for i := 0; i < b.N; i++ { 320 if _, err := InterfaceByIndex(ifi.Index); err != nil { 321 b.Fatal(err) 322 } 323 } 324 } 325 326 func BenchmarkInterfaceByName(b *testing.B) { 327 testHookUninstaller.Do(uninstallTestHooks) 328 329 ifi := loopbackInterface() 330 if ifi == nil { 331 b.Skip("loopback interface not found") 332 } 333 for i := 0; i < b.N; i++ { 334 if _, err := InterfaceByName(ifi.Name); err != nil { 335 b.Fatal(err) 336 } 337 } 338 } 339 340 func BenchmarkInterfaceAddrs(b *testing.B) { 341 testHookUninstaller.Do(uninstallTestHooks) 342 343 for i := 0; i < b.N; i++ { 344 if _, err := InterfaceAddrs(); err != nil { 345 b.Fatal(err) 346 } 347 } 348 } 349 350 func BenchmarkInterfacesAndAddrs(b *testing.B) { 351 testHookUninstaller.Do(uninstallTestHooks) 352 353 ifi := loopbackInterface() 354 if ifi == nil { 355 b.Skip("loopback interface not found") 356 } 357 for i := 0; i < b.N; i++ { 358 if _, err := ifi.Addrs(); err != nil { 359 b.Fatal(err) 360 } 361 } 362 } 363 364 func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) { 365 testHookUninstaller.Do(uninstallTestHooks) 366 367 ifi := loopbackInterface() 368 if ifi == nil { 369 b.Skip("loopback interface not found") 370 } 371 for i := 0; i < b.N; i++ { 372 if _, err := ifi.MulticastAddrs(); err != nil { 373 b.Fatal(err) 374 } 375 } 376 }