]> Cypherpunks repositories - gostls13.git/commitdiff
net: deflake TestDialGoogle, TestResolveDialGoogle
authorMikio Hara <mikioh.mikioh@gmail.com>
Wed, 1 Apr 2015 13:18:33 +0000 (22:18 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Fri, 3 Apr 2015 01:50:30 +0000 (01:50 +0000)
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>
src/net/dialgoogle_test.go
src/net/main_plan9_test.go
src/net/main_posix_test.go [new file with mode: 0644]
src/net/main_test.go

index 084de9f444c6b6387f04095fad0f26b51bbe2985..20611ff420e71bd1df3ca635fa5322bfdb2fba0e 100644 (file)
@@ -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
-       }
-       fetchGoogle(t, fd, network, addr)
-       fd.Close()
-}
+               t.Error(err)
+       }
+       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
 }
index bbd47aaaf67cfc0ffb5044aa9a018f156c17b158..94501cada9a234afbd6c1556fed0f94e81d02e06 100644 (file)
@@ -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 (file)
index 0000000..da80ff0
--- /dev/null
@@ -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
+       })
+}
index 2948c4ecd8fd5489b68ea5c320859e8abba182ed..ac56d31a2526ec310a2f29162c389da595e2b16c 100644 (file)
@@ -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)