Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/main_test.go

Documentation: net

     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  
     8  package net
     9  
    10  import (
    11  	"flag"
    12  	"fmt"
    13  	"net/internal/socktest"
    14  	"os"
    15  	"runtime"
    16  	"sort"
    17  	"strings"
    18  	"sync"
    19  	"testing"
    20  )
    21  
    22  var (
    23  	sw socktest.Switch
    24  
    25  	// uninstallTestHooks runs just before a run of benchmarks.
    26  	testHookUninstaller sync.Once
    27  )
    28  
    29  var (
    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  
    49  func 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  
    65  type ipv6LinkLocalUnicastTest struct {
    66  	network, address string
    67  	nameLookup       bool
    68  }
    69  
    70  var (
    71  	ipv6LinkLocalUnicastTCPTests []ipv6LinkLocalUnicastTest
    72  	ipv6LinkLocalUnicastUDPTests []ipv6LinkLocalUnicastTest
    73  )
    74  
    75  func 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  
   159  func 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.
   172  func 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  
   191  func 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  
   203  func 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  

View as plain text