1// Copyright 2015 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//go:build !js 6// +build !js 7 8package net 9 10import ( 11 "flag" 12 "fmt" 13 "net/internal/socktest" 14 "os" 15 "runtime" 16 "sort" 17 "strings" 18 "sync" 19 "testing" 20) 21 22var ( 23 sw socktest.Switch 24 25 // uninstallTestHooks runs just before a run of benchmarks. 26 testHookUninstaller sync.Once 27) 28 29var ( 30 testTCPBig = flag.Bool("tcpbig", false, "whether to test massive size of data per read or write call on TCP connection") 31 32 testDNSFlood = flag.Bool("dnsflood", false, "whether to test DNS query flooding") 33 34 // If external IPv4 connectivity exists, we can try dialing 35 // non-node/interface local scope IPv4 addresses. 36 // On Windows, Lookup APIs may not return IPv4-related 37 // resource records when a node has no external IPv4 38 // connectivity. 39 testIPv4 = flag.Bool("ipv4", true, "assume external IPv4 connectivity exists") 40 41 // If external IPv6 connectivity exists, we can try dialing 42 // non-node/interface local scope IPv6 addresses. 43 // On Windows, Lookup APIs may not return IPv6-related 44 // resource records when a node has no external IPv6 45 // connectivity. 46 testIPv6 = flag.Bool("ipv6", false, "assume external IPv6 connectivity exists") 47) 48 49func TestMain(m *testing.M) { 50 setupTestData() 51 installTestHooks() 52 53 st := m.Run() 54 55 testHookUninstaller.Do(uninstallTestHooks) 56 if testing.Verbose() { 57 printRunningGoroutines() 58 printInflightSockets() 59 printSocketStats() 60 } 61 forceCloseSockets() 62 os.Exit(st) 63} 64 65type ipv6LinkLocalUnicastTest struct { 66 network, address string 67 nameLookup bool 68} 69 70var ( 71 ipv6LinkLocalUnicastTCPTests []ipv6LinkLocalUnicastTest 72 ipv6LinkLocalUnicastUDPTests []ipv6LinkLocalUnicastTest 73) 74 75func setupTestData() { 76 if supportsIPv4() { 77 resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{ 78 {"tcp", "localhost:1", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil}, 79 {"tcp4", "localhost:2", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil}, 80 }...) 81 resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{ 82 {"udp", "localhost:1", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil}, 83 {"udp4", "localhost:2", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil}, 84 }...) 85 resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{ 86 {"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, 87 {"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, 88 }...) 89 } 90 91 if supportsIPv6() { 92 resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp6", "localhost:3", &TCPAddr{IP: IPv6loopback, Port: 3}, nil}) 93 resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp6", "localhost:3", &UDPAddr{IP: IPv6loopback, Port: 3}, nil}) 94 resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil}) 95 96 // Issue 20911: don't return IPv4 addresses for 97 // Resolve*Addr calls of the IPv6 unspecified address. 98 resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp", "[::]:4", &TCPAddr{IP: IPv6unspecified, Port: 4}, nil}) 99 resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp", "[::]:4", &UDPAddr{IP: IPv6unspecified, Port: 4}, nil}) 100 resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip", "::", &IPAddr{IP: IPv6unspecified}, nil}) 101 } 102 103 ifi := loopbackInterface() 104 if ifi != nil { 105 index := fmt.Sprintf("%v", ifi.Index) 106 resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{ 107 {"tcp6", "[fe80::1%" + ifi.Name + "]:1", &TCPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneCache.name(ifi.Index)}, nil}, 108 {"tcp6", "[fe80::1%" + index + "]:2", &TCPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil}, 109 }...) 110 resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{ 111 {"udp6", "[fe80::1%" + ifi.Name + "]:1", &UDPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneCache.name(ifi.Index)}, nil}, 112 {"udp6", "[fe80::1%" + index + "]:2", &UDPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil}, 113 }...) 114 resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{ 115 {"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneCache.name(ifi.Index)}, nil}, 116 {"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil}, 117 }...) 118 } 119 120 addr := ipv6LinkLocalUnicastAddr(ifi) 121 if addr != "" { 122 if runtime.GOOS != "dragonfly" { 123 ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{ 124 {"tcp", "[" + addr + "%" + ifi.Name + "]:0", false}, 125 }...) 126 ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{ 127 {"udp", "[" + addr + "%" + ifi.Name + "]:0", false}, 128 }...) 129 } 130 ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{ 131 {"tcp6", "[" + addr + "%" + ifi.Name + "]:0", false}, 132 }...) 133 ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{ 134 {"udp6", "[" + addr + "%" + ifi.Name + "]:0", false}, 135 }...) 136 switch runtime.GOOS { 137 case "darwin", "ios", "dragonfly", "freebsd", "openbsd", "netbsd": 138 ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{ 139 {"tcp", "[localhost%" + ifi.Name + "]:0", true}, 140 {"tcp6", "[localhost%" + ifi.Name + "]:0", true}, 141 }...) 142 ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{ 143 {"udp", "[localhost%" + ifi.Name + "]:0", true}, 144 {"udp6", "[localhost%" + ifi.Name + "]:0", true}, 145 }...) 146 case "linux": 147 ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{ 148 {"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true}, 149 {"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true}, 150 }...) 151 ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{ 152 {"udp", "[ip6-localhost%" + ifi.Name + "]:0", true}, 153 {"udp6", "[ip6-localhost%" + ifi.Name + "]:0", true}, 154 }...) 155 } 156 } 157} 158 159func printRunningGoroutines() { 160 gss := runningGoroutines() 161 if len(gss) == 0 { 162 return 163 } 164 fmt.Fprintf(os.Stderr, "Running goroutines:\n") 165 for _, gs := range gss { 166 fmt.Fprintf(os.Stderr, "%v\n", gs) 167 } 168 fmt.Fprintf(os.Stderr, "\n") 169} 170 171// runningGoroutines returns a list of remaining goroutines. 172func runningGoroutines() []string { 173 var gss []string 174 b := make([]byte, 2<<20) 175 b = b[:runtime.Stack(b, true)] 176 for _, s := range strings.Split(string(b), "\n\n") { 177 ss := strings.SplitN(s, "\n", 2) 178 if len(ss) != 2 { 179 continue 180 } 181 stack := strings.TrimSpace(ss[1]) 182 if !strings.Contains(stack, "created by net") { 183 continue 184 } 185 gss = append(gss, stack) 186 } 187 sort.Strings(gss) 188 return gss 189} 190 191func printInflightSockets() { 192 sos := sw.Sockets() 193 if len(sos) == 0 { 194 return 195 } 196 fmt.Fprintf(os.Stderr, "Inflight sockets:\n") 197 for s, so := range sos { 198 fmt.Fprintf(os.Stderr, "%v: %v\n", s, so) 199 } 200 fmt.Fprintf(os.Stderr, "\n") 201} 202 203func printSocketStats() { 204 sts := sw.Stats() 205 if len(sts) == 0 { 206 return 207 } 208 fmt.Fprintf(os.Stderr, "Socket statistical information:\n") 209 for _, st := range sts { 210 fmt.Fprintf(os.Stderr, "%v\n", st) 211 } 212 fmt.Fprintf(os.Stderr, "\n") 213} 214