mirror of
https://github.com/golang/go
synced 2024-11-25 22:47:57 -07:00
b0b1d42db3
Doing this because the slices functions are slightly faster and slightly easier to use. It also removes one dependency layer. This CL does not change packages that are used during bootstrap, as the bootstrap compiler does not have the required slices functions. It does not change the go/scanner package because the ErrorList Len, Swap, and Less methods are part of the Go 1 API. Change-Id: If52899be791c829198e11d2408727720b91ebe8a Reviewed-on: https://go-review.googlesource.com/c/go/+/587655 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Commit-Queue: Ian Lance Taylor <iant@google.com> Reviewed-by: Damien Neil <dneil@google.com>
223 lines
7.5 KiB
Go
223 lines
7.5 KiB
Go
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package net
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"net/internal/socktest"
|
|
"os"
|
|
"runtime"
|
|
"slices"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
sw socktest.Switch
|
|
|
|
// uninstallTestHooks runs just before a run of benchmarks.
|
|
testHookUninstaller sync.Once
|
|
)
|
|
|
|
var (
|
|
testTCPBig = flag.Bool("tcpbig", false, "whether to test massive size of data per read or write call on TCP connection")
|
|
|
|
testDNSFlood = flag.Bool("dnsflood", false, "whether to test DNS query flooding")
|
|
|
|
// If external IPv4 connectivity exists, we can try dialing
|
|
// non-node/interface local scope IPv4 addresses.
|
|
// On Windows, Lookup APIs may not return IPv4-related
|
|
// resource records when a node has no external IPv4
|
|
// connectivity.
|
|
testIPv4 = flag.Bool("ipv4", true, "assume external IPv4 connectivity exists")
|
|
|
|
// If external IPv6 connectivity exists, we can try dialing
|
|
// non-node/interface local scope IPv6 addresses.
|
|
// On Windows, Lookup APIs may not return IPv6-related
|
|
// resource records when a node has no external IPv6
|
|
// connectivity.
|
|
testIPv6 = flag.Bool("ipv6", false, "assume external IPv6 connectivity exists")
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
setupTestData()
|
|
installTestHooks()
|
|
|
|
st := m.Run()
|
|
|
|
testHookUninstaller.Do(uninstallTestHooks)
|
|
if testing.Verbose() {
|
|
printRunningGoroutines()
|
|
printInflightSockets()
|
|
printSocketStats()
|
|
}
|
|
forceCloseSockets()
|
|
os.Exit(st)
|
|
}
|
|
|
|
// mustSetDeadline calls the bound method m to set a deadline on a Conn.
|
|
// If the call fails, mustSetDeadline skips t if the current GOOS is believed
|
|
// not to support deadlines, or fails the test otherwise.
|
|
func mustSetDeadline(t testing.TB, m func(time.Time) error, d time.Duration) {
|
|
err := m(time.Now().Add(d))
|
|
if err != nil {
|
|
t.Helper()
|
|
if runtime.GOOS == "plan9" {
|
|
t.Skipf("skipping: %s does not support deadlines", runtime.GOOS)
|
|
}
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
type ipv6LinkLocalUnicastTest struct {
|
|
network, address string
|
|
nameLookup bool
|
|
}
|
|
|
|
var (
|
|
ipv6LinkLocalUnicastTCPTests []ipv6LinkLocalUnicastTest
|
|
ipv6LinkLocalUnicastUDPTests []ipv6LinkLocalUnicastTest
|
|
)
|
|
|
|
func setupTestData() {
|
|
if supportsIPv4() {
|
|
resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
|
|
{"tcp", "localhost:1", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil},
|
|
{"tcp4", "localhost:2", &TCPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil},
|
|
}...)
|
|
resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
|
|
{"udp", "localhost:1", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 1}, nil},
|
|
{"udp4", "localhost:2", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 2}, nil},
|
|
}...)
|
|
resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
|
|
{"ip", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
|
|
{"ip4", "localhost", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
|
|
}...)
|
|
}
|
|
|
|
if supportsIPv6() {
|
|
resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp6", "localhost:3", &TCPAddr{IP: IPv6loopback, Port: 3}, nil})
|
|
resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp6", "localhost:3", &UDPAddr{IP: IPv6loopback, Port: 3}, nil})
|
|
resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip6", "localhost", &IPAddr{IP: IPv6loopback}, nil})
|
|
|
|
// Issue 20911: don't return IPv4 addresses for
|
|
// Resolve*Addr calls of the IPv6 unspecified address.
|
|
resolveTCPAddrTests = append(resolveTCPAddrTests, resolveTCPAddrTest{"tcp", "[::]:4", &TCPAddr{IP: IPv6unspecified, Port: 4}, nil})
|
|
resolveUDPAddrTests = append(resolveUDPAddrTests, resolveUDPAddrTest{"udp", "[::]:4", &UDPAddr{IP: IPv6unspecified, Port: 4}, nil})
|
|
resolveIPAddrTests = append(resolveIPAddrTests, resolveIPAddrTest{"ip", "::", &IPAddr{IP: IPv6unspecified}, nil})
|
|
}
|
|
|
|
ifi := loopbackInterface()
|
|
if ifi != nil {
|
|
index := fmt.Sprintf("%v", ifi.Index)
|
|
resolveTCPAddrTests = append(resolveTCPAddrTests, []resolveTCPAddrTest{
|
|
{"tcp6", "[fe80::1%" + ifi.Name + "]:1", &TCPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneCache.name(ifi.Index)}, nil},
|
|
{"tcp6", "[fe80::1%" + index + "]:2", &TCPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil},
|
|
}...)
|
|
resolveUDPAddrTests = append(resolveUDPAddrTests, []resolveUDPAddrTest{
|
|
{"udp6", "[fe80::1%" + ifi.Name + "]:1", &UDPAddr{IP: ParseIP("fe80::1"), Port: 1, Zone: zoneCache.name(ifi.Index)}, nil},
|
|
{"udp6", "[fe80::1%" + index + "]:2", &UDPAddr{IP: ParseIP("fe80::1"), Port: 2, Zone: index}, nil},
|
|
}...)
|
|
resolveIPAddrTests = append(resolveIPAddrTests, []resolveIPAddrTest{
|
|
{"ip6", "fe80::1%" + ifi.Name, &IPAddr{IP: ParseIP("fe80::1"), Zone: zoneCache.name(ifi.Index)}, nil},
|
|
{"ip6", "fe80::1%" + index, &IPAddr{IP: ParseIP("fe80::1"), Zone: index}, nil},
|
|
}...)
|
|
}
|
|
|
|
addr := ipv6LinkLocalUnicastAddr(ifi)
|
|
if addr != "" {
|
|
if runtime.GOOS != "dragonfly" {
|
|
ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{
|
|
{"tcp", "[" + addr + "%" + ifi.Name + "]:0", false},
|
|
}...)
|
|
ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{
|
|
{"udp", "[" + addr + "%" + ifi.Name + "]:0", false},
|
|
}...)
|
|
}
|
|
ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{
|
|
{"tcp6", "[" + addr + "%" + ifi.Name + "]:0", false},
|
|
}...)
|
|
ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{
|
|
{"udp6", "[" + addr + "%" + ifi.Name + "]:0", false},
|
|
}...)
|
|
switch runtime.GOOS {
|
|
case "darwin", "ios", "dragonfly", "freebsd", "openbsd", "netbsd":
|
|
ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{
|
|
{"tcp", "[localhost%" + ifi.Name + "]:0", true},
|
|
{"tcp6", "[localhost%" + ifi.Name + "]:0", true},
|
|
}...)
|
|
ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{
|
|
{"udp", "[localhost%" + ifi.Name + "]:0", true},
|
|
{"udp6", "[localhost%" + ifi.Name + "]:0", true},
|
|
}...)
|
|
case "linux":
|
|
ipv6LinkLocalUnicastTCPTests = append(ipv6LinkLocalUnicastTCPTests, []ipv6LinkLocalUnicastTest{
|
|
{"tcp", "[ip6-localhost%" + ifi.Name + "]:0", true},
|
|
{"tcp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
|
|
}...)
|
|
ipv6LinkLocalUnicastUDPTests = append(ipv6LinkLocalUnicastUDPTests, []ipv6LinkLocalUnicastTest{
|
|
{"udp", "[ip6-localhost%" + ifi.Name + "]:0", true},
|
|
{"udp6", "[ip6-localhost%" + ifi.Name + "]:0", true},
|
|
}...)
|
|
}
|
|
}
|
|
}
|
|
|
|
func printRunningGoroutines() {
|
|
gss := runningGoroutines()
|
|
if len(gss) == 0 {
|
|
return
|
|
}
|
|
fmt.Fprintf(os.Stderr, "Running goroutines:\n")
|
|
for _, gs := range gss {
|
|
fmt.Fprintf(os.Stderr, "%v\n", gs)
|
|
}
|
|
fmt.Fprintf(os.Stderr, "\n")
|
|
}
|
|
|
|
// runningGoroutines returns a list of remaining goroutines.
|
|
func runningGoroutines() []string {
|
|
var gss []string
|
|
b := make([]byte, 2<<20)
|
|
b = b[:runtime.Stack(b, true)]
|
|
for _, s := range strings.Split(string(b), "\n\n") {
|
|
_, stack, _ := strings.Cut(s, "\n")
|
|
stack = strings.TrimSpace(stack)
|
|
if !strings.Contains(stack, "created by net") {
|
|
continue
|
|
}
|
|
gss = append(gss, stack)
|
|
}
|
|
slices.Sort(gss)
|
|
return gss
|
|
}
|
|
|
|
func printInflightSockets() {
|
|
sos := sw.Sockets()
|
|
if len(sos) == 0 {
|
|
return
|
|
}
|
|
fmt.Fprintf(os.Stderr, "Inflight sockets:\n")
|
|
for s, so := range sos {
|
|
fmt.Fprintf(os.Stderr, "%v: %v\n", s, so)
|
|
}
|
|
fmt.Fprintf(os.Stderr, "\n")
|
|
}
|
|
|
|
func printSocketStats() {
|
|
sts := sw.Stats()
|
|
if len(sts) == 0 {
|
|
return
|
|
}
|
|
fmt.Fprintf(os.Stderr, "Socket statistical information:\n")
|
|
for _, st := range sts {
|
|
fmt.Fprintf(os.Stderr, "%v\n", st)
|
|
}
|
|
fmt.Fprintf(os.Stderr, "\n")
|
|
}
|