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  }