aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikio Hara <mikioh.mikioh@gmail.com>2015-04-01 22:18:33 +0900
committerMikio Hara <mikioh.mikioh@gmail.com>2015-04-03 01:50:30 +0000
commit21ed40c8cb4795433bda0cfb7754db5603a916f0 (patch)
tree4dae7cedab10df7c0ca4bc37203ffc6db350fb42 /src
parente8694c8196e39328d6d61b1f32228d21112008d7 (diff)
downloadgo-21ed40c8cb4795433bda0cfb7754db5603a916f0.tar.xz
net: deflake TestDialGoogle, TestResolveDialGoogle
This change makes use of the socktest package instead of the non-thread safe variable syscall.SocketDisableIPv6 for simulating unreachable external networks. Also adds -ipv4 flag, -ipv6 flag already exists, as a control knob for testing on each of IPv4-only, IPv6-only and dual IP stack kernels. Fixes #7687. Change-Id: I82002007fd526e8cf4de207f935e721df049a22f Reviewed-on: https://go-review.googlesource.com/8390 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/net/dialgoogle_test.go287
-rw-r--r--src/net/main_plan9_test.go4
-rw-r--r--src/net/main_posix_test.go34
-rw-r--r--src/net/main_test.go8
4 files changed, 183 insertions, 150 deletions
diff --git a/src/net/dialgoogle_test.go b/src/net/dialgoogle_test.go
index 084de9f444..20611ff420 100644
--- a/src/net/dialgoogle_test.go
+++ b/src/net/dialgoogle_test.go
@@ -8,198 +8,189 @@ import (
"fmt"
"io"
"strings"
- "syscall"
"testing"
)
func TestResolveGoogle(t *testing.T) {
if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
+ t.Skip("avoid external network")
+ }
+ if !supportsIPv4 && !supportsIPv6 {
+ t.Skip("ipv4 and ipv6 are not supported")
}
for _, network := range []string{"tcp", "tcp4", "tcp6"} {
addr, err := ResolveTCPAddr(network, "www.google.com:http")
if err != nil {
- if (network == "tcp" || network == "tcp4") && !supportsIPv4 {
- t.Logf("ipv4 is not supported: %v", err)
- } else if network == "tcp6" && !supportsIPv6 {
- t.Logf("ipv6 is not supported: %v", err)
- } else {
- t.Errorf("ResolveTCPAddr failed: %v", err)
+ switch {
+ case network == "tcp" && !supportsIPv4:
+ fallthrough
+ case network == "tcp4" && !supportsIPv4:
+ t.Logf("skipping test; ipv4 is not supported: %v", err)
+ case network == "tcp6" && !supportsIPv6:
+ t.Logf("skipping test; ipv6 is not supported: %v", err)
+ default:
+ t.Error(err)
}
continue
}
- if (network == "tcp" || network == "tcp4") && addr.IP.To4() == nil {
- t.Errorf("got %v; expected an IPv4 address on %v", addr, network)
- } else if network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil) {
- t.Errorf("got %v; expected an IPv6 address on %v", addr, network)
+
+ switch {
+ case network == "tcp" && addr.IP.To4() == nil:
+ fallthrough
+ case network == "tcp4" && addr.IP.To4() == nil:
+ t.Errorf("got %v; want an ipv4 address on %s", addr, network)
+ case network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil):
+ t.Errorf("got %v; want an ipv6 address on %s", addr, network)
}
}
}
+var dialGoogleTests = []struct {
+ dial func(string, string) (Conn, error)
+ unreachableNetwork string
+ networks []string
+ addrs []string
+}{
+ {
+ dial: (&Dialer{DualStack: true}).Dial,
+ networks: []string{"tcp", "tcp4", "tcp6"},
+ addrs: []string{"www.google.com:http"},
+ },
+ {
+ dial: Dial,
+ unreachableNetwork: "tcp6",
+ networks: []string{"tcp", "tcp4"},
+ },
+ {
+ dial: Dial,
+ unreachableNetwork: "tcp4",
+ networks: []string{"tcp", "tcp6"},
+ },
+}
+
func TestDialGoogle(t *testing.T) {
if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
-
- d := &Dialer{DualStack: true}
- for _, network := range []string{"tcp", "tcp4", "tcp6"} {
- if network == "tcp" && !supportsIPv4 && !supportsIPv6 {
- t.Logf("skipping test; both ipv4 and ipv6 are not supported")
- continue
- } else if network == "tcp4" && !supportsIPv4 {
- t.Logf("skipping test; ipv4 is not supported")
- continue
- } else if network == "tcp6" && !supportsIPv6 {
- t.Logf("skipping test; ipv6 is not supported")
- continue
- } else if network == "tcp6" && !*testIPv6 {
- t.Logf("test disabled; use -ipv6 to enable")
- continue
- }
- if c, err := d.Dial(network, "www.google.com:http"); err != nil {
- t.Errorf("Dial failed: %v", err)
- } else {
- c.Close()
- }
+ t.Skip("avoid external network")
}
-}
-
-// fd is already connected to the destination, port 80.
-// Run an HTTP request to fetch the appropriate page.
-func fetchGoogle(t *testing.T, fd Conn, network, addr string) {
- req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
- n, err := fd.Write(req)
-
- buf := make([]byte, 1000)
- n, err = io.ReadFull(fd, buf)
-
- if n < 1000 {
- t.Errorf("fetchGoogle: short HTTP read from %s %s - %v", network, addr, err)
- return
+ if !supportsIPv4 && !supportsIPv6 {
+ t.Skip("ipv4 and ipv6 are not supported")
}
-}
-func doDial(t *testing.T, network, addr string) {
- fd, err := Dial(network, addr)
+ var err error
+ dialGoogleTests[1].addrs, dialGoogleTests[2].addrs, err = googleLiteralAddrs()
if err != nil {
- t.Errorf("Dial(%q, %q, %q) = _, %v", network, "", addr, err)
- return
+ t.Error(err)
}
- fetchGoogle(t, fd, network, addr)
- fd.Close()
-}
+ for _, tt := range dialGoogleTests {
+ for _, network := range tt.networks {
+ switch {
+ case network == "tcp4" && !supportsIPv4:
+ t.Log("skipping test; ipv4 is not supported")
+ continue
+ case network == "tcp4" && !*testIPv4:
+ fallthrough
+ case tt.unreachableNetwork == "tcp6" && !*testIPv4:
+ t.Log("disabled; use -ipv4 to enable")
+ continue
+ case network == "tcp6" && !supportsIPv6:
+ t.Log("skipping test; ipv6 is not supported")
+ continue
+ case network == "tcp6" && !*testIPv6:
+ fallthrough
+ case tt.unreachableNetwork == "tcp4" && !*testIPv6:
+ t.Log("disabled; use -ipv6 to enable")
+ continue
+ }
-var googleaddrsipv4 = []string{
- "%d.%d.%d.%d:80",
- "www.google.com:80",
- "%d.%d.%d.%d:http",
- "www.google.com:http",
- "%03d.%03d.%03d.%03d:0080",
- "[::ffff:%d.%d.%d.%d]:80",
- "[::ffff:%02x%02x:%02x%02x]:80",
- "[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
- "[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
- "[0:0:0:0::ffff:%d.%d.%d.%d]:80",
+ disableSocketConnect(tt.unreachableNetwork)
+ for _, addr := range tt.addrs {
+ if err := fetchGoogle(tt.dial, network, addr); err != nil {
+ t.Error(err)
+ }
+ }
+ enableSocketConnect()
+ }
+ }
}
-func TestDialGoogleIPv4(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
+var (
+ literalAddrs4 = [...]string{
+ "%d.%d.%d.%d:80",
+ "www.google.com:80",
+ "%d.%d.%d.%d:http",
+ "www.google.com:http",
+ "%03d.%03d.%03d.%03d:0080",
+ "[::ffff:%d.%d.%d.%d]:80",
+ "[::ffff:%02x%02x:%02x%02x]:80",
+ "[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
+ "[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
+ "[0:0:0:0::ffff:%d.%d.%d.%d]:80",
+ }
+ literalAddrs6 = [...]string{
+ "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
+ "ipv6.google.com:80",
+ "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
+ "ipv6.google.com:http",
}
+)
- // Insert an actual IPv4 address for google.com
- // into the table.
- addrs, err := LookupIP("www.google.com")
+func googleLiteralAddrs() (lits4, lits6 []string, err error) {
+ ips, err := LookupIP("www.google.com")
if err != nil {
- t.Fatalf("lookup www.google.com: %v", err)
+ return nil, nil, err
}
- var ip IP
- for _, addr := range addrs {
- if x := addr.To4(); x != nil {
- ip = x
+ if len(ips) == 0 {
+ return nil, nil, nil
+ }
+ var ip4, ip6 IP
+ for _, ip := range ips {
+ if ip4 == nil && ip.To4() != nil {
+ ip4 = ip.To4()
+ }
+ if ip6 == nil && ip.To16() != nil && ip.To4() == nil {
+ ip6 = ip.To16()
+ }
+ if ip4 != nil && ip6 != nil {
break
}
}
- if ip == nil {
- t.Fatalf("no IPv4 addresses for www.google.com")
- }
-
- for i, s := range googleaddrsipv4 {
- if strings.Contains(s, "%") {
- googleaddrsipv4[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3])
+ if ip4 != nil {
+ for i, lit4 := range literalAddrs4 {
+ if strings.Contains(lit4, "%") {
+ literalAddrs4[i] = fmt.Sprintf(lit4, ip4[0], ip4[1], ip4[2], ip4[3])
+ }
}
+ lits4 = literalAddrs4[:]
}
-
- for i := 0; i < len(googleaddrsipv4); i++ {
- addr := googleaddrsipv4[i]
- if addr == "" {
- continue
- }
- t.Logf("-- %s --", addr)
- doDial(t, "tcp", addr)
- if addr[0] != '[' {
- doDial(t, "tcp4", addr)
- if supportsIPv6 {
- // make sure syscall.SocketDisableIPv6 flag works.
- syscall.SocketDisableIPv6 = true
- doDial(t, "tcp", addr)
- doDial(t, "tcp4", addr)
- syscall.SocketDisableIPv6 = false
+ if ip6 != nil {
+ for i, lit6 := range literalAddrs6 {
+ if strings.Contains(lit6, "%") {
+ literalAddrs6[i] = fmt.Sprintf(lit6, ip6[0], ip6[1], ip6[2], ip6[3], ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15])
}
}
+ lits6 = literalAddrs6[:]
}
+ return
}
-var googleaddrsipv6 = []string{
- "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
- "ipv6.google.com:80",
- "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
- "ipv6.google.com:http",
-}
-
-func TestDialGoogleIPv6(t *testing.T) {
- if testing.Short() || !*testExternal {
- t.Skip("skipping test to avoid external network")
- }
- // Only run tcp6 if the kernel will take it.
- if !supportsIPv6 {
- t.Skip("skipping test; ipv6 is not supported")
- }
- if !*testIPv6 {
- t.Skip("test disabled; use -ipv6 to enable")
- }
-
- // Insert an actual IPv6 address for ipv6.google.com
- // into the table.
- addrs, err := LookupIP("ipv6.google.com")
+func fetchGoogle(dial func(string, string) (Conn, error), network, address string) error {
+ c, err := dial(network, address)
if err != nil {
- t.Fatalf("lookup ipv6.google.com: %v", err)
+ return err
}
- var ip IP
- for _, addr := range addrs {
- if x := addr.To16(); x != nil {
- ip = x
- break
- }
- }
- if ip == nil {
- t.Fatalf("no IPv6 addresses for ipv6.google.com")
+ defer c.Close()
+ req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
+ if _, err := c.Write(req); err != nil {
+ return err
}
-
- for i, s := range googleaddrsipv6 {
- if strings.Contains(s, "%") {
- googleaddrsipv6[i] = fmt.Sprintf(s, ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15])
- }
+ b := make([]byte, 1000)
+ n, err := io.ReadFull(c, b)
+ if err != nil {
+ return err
}
-
- for i := 0; i < len(googleaddrsipv6); i++ {
- addr := googleaddrsipv6[i]
- if addr == "" {
- continue
- }
- t.Logf("-- %s --", addr)
- doDial(t, "tcp", addr)
- doDial(t, "tcp6", addr)
+ if n < 1000 {
+ return fmt.Errorf("short read from %s:%s->%s", network, c.RemoteAddr(), c.LocalAddr())
}
+ return nil
}
diff --git a/src/net/main_plan9_test.go b/src/net/main_plan9_test.go
index bbd47aaaf6..94501cada9 100644
--- a/src/net/main_plan9_test.go
+++ b/src/net/main_plan9_test.go
@@ -9,3 +9,7 @@ func installTestHooks() {}
func uninstallTestHooks() {}
func forceCloseSockets() {}
+
+func enableSocketConnect() {}
+
+func disableSocketConnect(network string) {}
diff --git a/src/net/main_posix_test.go b/src/net/main_posix_test.go
new file mode 100644
index 0000000000..da80ff03c8
--- /dev/null
+++ b/src/net/main_posix_test.go
@@ -0,0 +1,34 @@
+// 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.
+
+// +build !plan9
+
+package net
+
+import (
+ "net/internal/socktest"
+ "strings"
+ "syscall"
+)
+
+func enableSocketConnect() {
+ sw.Set(socktest.FilterConnect, nil)
+}
+
+func disableSocketConnect(network string) {
+ ss := strings.Split(network, ":")
+ sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
+ switch ss[0] {
+ case "tcp4", "udp4", "ip4":
+ if so.Cookie.Family() == syscall.AF_INET {
+ return nil, syscall.EHOSTUNREACH
+ }
+ case "tcp6", "udp6", "ip6":
+ if so.Cookie.Family() == syscall.AF_INET6 {
+ return nil, syscall.EHOSTUNREACH
+ }
+ }
+ return nil, nil
+ })
+}
diff --git a/src/net/main_test.go b/src/net/main_test.go
index 2948c4ecd8..ac56d31a25 100644
--- a/src/net/main_test.go
+++ b/src/net/main_test.go
@@ -34,6 +34,10 @@ var (
testExternal = flag.Bool("external", true, "allow use of external networks during long test")
+ // If external IPv4 connectivity exists, we can try dialing
+ // non-node/interface local scope IPv4 addresses.
+ 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.
testIPv6 = flag.Bool("ipv6", false, "assume external IPv6 connectivity exists")
@@ -70,8 +74,8 @@ func printLeakedGoroutines() {
fmt.Fprintf(os.Stderr, "\n")
}
-// leakedGoroutines returns a list of remaining goroutins used in test
-// cases.
+// leakedGoroutines returns a list of remaining goroutines used in
+// test cases.
func leakedGoroutines() []string {
var gss []string
b := make([]byte, 2<<20)