rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/net/main_test.go (about) 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 package net 6 7 import ( 8 "flag" 9 "fmt" 10 "net/internal/socktest" 11 "os" 12 "runtime" 13 "sort" 14 "strings" 15 "sync" 16 "testing" 17 ) 18 19 var ( 20 sw socktest.Switch 21 22 // uninstallTestHooks runs just before a run of benchmarks. 23 testHookUninstaller sync.Once 24 ) 25 26 var ( 27 // Do not test datagrams with empty payload by default. 28 // It depends on each platform implementation whether generic 29 // read, socket recv system calls return the result of zero 30 // byte read. 31 testDatagram = flag.Bool("datagram", false, "whether to test UDP and unixgram") 32 33 testDNSFlood = flag.Bool("dnsflood", false, "whether to test DNS query flooding") 34 35 testExternal = flag.Bool("external", true, "allow use of external networks during long test") 36 37 // If external IPv4 connectivity exists, we can try dialing 38 // non-node/interface local scope IPv4 addresses. 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 testIPv6 = flag.Bool("ipv6", false, "assume external IPv6 connectivity exists") 44 45 // BUG: TestDialError has been broken, and so this flag 46 // exists. We should fix the test and remove this flag soon. 47 runErrorTest = flag.Bool("run_error_test", false, "let TestDialError check for DNS errors") 48 ) 49 50 func TestMain(m *testing.M) { 51 setupTestData() 52 installTestHooks() 53 54 st := m.Run() 55 56 testHookUninstaller.Do(func() { uninstallTestHooks() }) 57 if !testing.Short() { 58 printLeakedGoroutines() 59 printLeakedSockets() 60 printSocketStats() 61 } 62 forceCloseSockets() 63 os.Exit(st) 64 } 65 66 func setupTestData() { 67 if supportsIPv4 { 68 resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{ 69 {"tcp", "localhost:1", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil}, 70 {"tcp4", "localhost:2", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil}, 71 }...) 72 resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{ 73 {"udp", "localhost:1", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil}, 74 {"udp4", "localhost:2", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil}, 75 }...) 76 resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{ 77 {"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, 78 {"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil}, 79 }...) 80 } 81 82 if supportsIPv6 { 83 resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp6", "localhost:3", &TCPAddr{IP: IPv6loopback, Port: 3}, nil}) 84 resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp6", "localhost:3", &UDPAddr{IP: IPv6loopback, Port: 3}, nil}) 85 resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil}) 86 } 87 88 if ifi := loopbackInterface(); ifi != nil { 89 index := fmt.Sprintf("%v", ifi.Index) 90 resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{ 91 {"tcp6", "[fe80::1%" + ifi.Name + "]:1", &TCPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneToString(ifi.Index)}, nil}, 92 {"tcp6", "[fe80::1%" + index + "]:2", &TCPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil}, 93 }...) 94 resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{ 95 {"udp6", "[fe80::1%" + ifi.Name + "]:1", &UDPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneToString(ifi.Index)}, nil}, 96 {"udp6", "[fe80::1%" + index + "]:2", &UDPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil}, 97 }...) 98 resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{ 99 {"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneToString(ifi.Index)}, nil}, 100 {"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil}, 101 }...) 102 } 103 } 104 105 func printLeakedGoroutines() { 106 gss := leakedGoroutines() 107 if len(gss) == 0 { 108 return 109 } 110 fmt.Fprintf(os.Stderr, "Leaked goroutines:\n") 111 for _, gs := range gss { 112 fmt.Fprintf(os.Stderr, "%v\n", gs) 113 } 114 fmt.Fprintf(os.Stderr, "\n") 115 } 116 117 // leakedGoroutines returns a list of remaining goroutines used in 118 // test cases. 119 func leakedGoroutines() []string { 120 var gss []string 121 b := make([]byte, 2<<20) 122 b = b[:runtime.Stack(b, true)] 123 for _, s := range strings.Split(string(b), "\n\n") { 124 ss := strings.SplitN(s, "\n", 2) 125 if len(ss) != 2 { 126 continue 127 } 128 stack := strings.TrimSpace(ss[1]) 129 if !strings.Contains(stack, "created by net") { 130 continue 131 } 132 gss = append(gss, stack) 133 } 134 sort.Strings(gss) 135 return gss 136 } 137 138 func printLeakedSockets() { 139 sos := sw.Sockets() 140 if len(sos) == 0 { 141 return 142 } 143 fmt.Fprintf(os.Stderr, "Leaked sockets:\n") 144 for s, so := range sos { 145 fmt.Fprintf(os.Stderr, "%v: %v\n", s, so) 146 } 147 fmt.Fprintf(os.Stderr, "\n") 148 } 149 150 func printSocketStats() { 151 sts := sw.Stats() 152 if len(sts) == 0 { 153 return 154 } 155 fmt.Fprintf(os.Stderr, "Socket statistical information:\n") 156 for _, st := range sts { 157 fmt.Fprintf(os.Stderr, "%v\n", st) 158 } 159 fmt.Fprintf(os.Stderr, "\n") 160 }