rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/net/dialgoogle_test.go (about)

     1  // Copyright 2009 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  	"fmt"
     9  	"io"
    10  	"strings"
    11  	"testing"
    12  )
    13  
    14  func TestResolveGoogle(t *testing.T) {
    15  	if testing.Short() || !*testExternal {
    16  		t.Skip("avoid external network")
    17  	}
    18  	if !supportsIPv4 && !supportsIPv6 {
    19  		t.Skip("ipv4 and ipv6 are not supported")
    20  	}
    21  
    22  	for _, network := range []string{"tcp", "tcp4", "tcp6"} {
    23  		addr, err := ResolveTCPAddr(network, "www.google.com:http")
    24  		if err != nil {
    25  			switch {
    26  			case network == "tcp" && !supportsIPv4:
    27  				fallthrough
    28  			case network == "tcp4" && !supportsIPv4:
    29  				t.Logf("skipping test; ipv4 is not supported: %v", err)
    30  			case network == "tcp6" && !supportsIPv6:
    31  				t.Logf("skipping test; ipv6 is not supported: %v", err)
    32  			default:
    33  				t.Error(err)
    34  			}
    35  			continue
    36  		}
    37  
    38  		switch {
    39  		case network == "tcp" && addr.IP.To4() == nil:
    40  			fallthrough
    41  		case network == "tcp4" && addr.IP.To4() == nil:
    42  			t.Errorf("got %v; want an ipv4 address on %s", addr, network)
    43  		case network == "tcp6" && (addr.IP.To16() == nil || addr.IP.To4() != nil):
    44  			t.Errorf("got %v; want an ipv6 address on %s", addr, network)
    45  		}
    46  	}
    47  }
    48  
    49  var dialGoogleTests = []struct {
    50  	dial               func(string, string) (Conn, error)
    51  	unreachableNetwork string
    52  	networks           []string
    53  	addrs              []string
    54  }{
    55  	{
    56  		dial:     (&Dialer{DualStack: true}).Dial,
    57  		networks: []string{"tcp", "tcp4", "tcp6"},
    58  		addrs:    []string{"www.google.com:http"},
    59  	},
    60  	{
    61  		dial:               Dial,
    62  		unreachableNetwork: "tcp6",
    63  		networks:           []string{"tcp", "tcp4"},
    64  	},
    65  	{
    66  		dial:               Dial,
    67  		unreachableNetwork: "tcp4",
    68  		networks:           []string{"tcp", "tcp6"},
    69  	},
    70  }
    71  
    72  func TestDialGoogle(t *testing.T) {
    73  	if testing.Short() || !*testExternal {
    74  		t.Skip("avoid external network")
    75  	}
    76  	if !supportsIPv4 && !supportsIPv6 {
    77  		t.Skip("ipv4 and ipv6 are not supported")
    78  	}
    79  
    80  	var err error
    81  	dialGoogleTests[1].addrs, dialGoogleTests[2].addrs, err = googleLiteralAddrs()
    82  	if err != nil {
    83  		t.Error(err)
    84  	}
    85  	for _, tt := range dialGoogleTests {
    86  		for _, network := range tt.networks {
    87  			switch {
    88  			case network == "tcp4" && !supportsIPv4:
    89  				t.Log("skipping test; ipv4 is not supported")
    90  				continue
    91  			case network == "tcp4" && !*testIPv4:
    92  				fallthrough
    93  			case tt.unreachableNetwork == "tcp6" && !*testIPv4:
    94  				t.Log("disabled; use -ipv4 to enable")
    95  				continue
    96  			case network == "tcp6" && !supportsIPv6:
    97  				t.Log("skipping test; ipv6 is not supported")
    98  				continue
    99  			case network == "tcp6" && !*testIPv6:
   100  				fallthrough
   101  			case tt.unreachableNetwork == "tcp4" && !*testIPv6:
   102  				t.Log("disabled; use -ipv6 to enable")
   103  				continue
   104  			}
   105  
   106  			disableSocketConnect(tt.unreachableNetwork)
   107  			for _, addr := range tt.addrs {
   108  				if err := fetchGoogle(tt.dial, network, addr); err != nil {
   109  					t.Error(err)
   110  				}
   111  			}
   112  			enableSocketConnect()
   113  		}
   114  	}
   115  }
   116  
   117  var (
   118  	literalAddrs4 = [...]string{
   119  		"%d.%d.%d.%d:80",
   120  		"www.google.com:80",
   121  		"%d.%d.%d.%d:http",
   122  		"www.google.com:http",
   123  		"%03d.%03d.%03d.%03d:0080",
   124  		"[::ffff:%d.%d.%d.%d]:80",
   125  		"[::ffff:%02x%02x:%02x%02x]:80",
   126  		"[0:0:0:0:0000:ffff:%d.%d.%d.%d]:80",
   127  		"[0:0:0:0:000000:ffff:%d.%d.%d.%d]:80",
   128  		"[0:0:0:0::ffff:%d.%d.%d.%d]:80",
   129  	}
   130  	literalAddrs6 = [...]string{
   131  		"[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:80",
   132  		"ipv6.google.com:80",
   133  		"[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:http",
   134  		"ipv6.google.com:http",
   135  	}
   136  )
   137  
   138  func googleLiteralAddrs() (lits4, lits6 []string, err error) {
   139  	ips, err := LookupIP("www.google.com")
   140  	if err != nil {
   141  		return nil, nil, err
   142  	}
   143  	if len(ips) == 0 {
   144  		return nil, nil, nil
   145  	}
   146  	var ip4, ip6 IP
   147  	for _, ip := range ips {
   148  		if ip4 == nil && ip.To4() != nil {
   149  			ip4 = ip.To4()
   150  		}
   151  		if ip6 == nil && ip.To16() != nil && ip.To4() == nil {
   152  			ip6 = ip.To16()
   153  		}
   154  		if ip4 != nil && ip6 != nil {
   155  			break
   156  		}
   157  	}
   158  	if ip4 != nil {
   159  		for i, lit4 := range literalAddrs4 {
   160  			if strings.Contains(lit4, "%") {
   161  				literalAddrs4[i] = fmt.Sprintf(lit4, ip4[0], ip4[1], ip4[2], ip4[3])
   162  			}
   163  		}
   164  		lits4 = literalAddrs4[:]
   165  	}
   166  	if ip6 != nil {
   167  		for i, lit6 := range literalAddrs6 {
   168  			if strings.Contains(lit6, "%") {
   169  				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])
   170  			}
   171  		}
   172  		lits6 = literalAddrs6[:]
   173  	}
   174  	return
   175  }
   176  
   177  func fetchGoogle(dial func(string, string) (Conn, error), network, address string) error {
   178  	c, err := dial(network, address)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	defer c.Close()
   183  	req := []byte("GET /robots.txt HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
   184  	if _, err := c.Write(req); err != nil {
   185  		return err
   186  	}
   187  	b := make([]byte, 1000)
   188  	n, err := io.ReadFull(c, b)
   189  	if err != nil {
   190  		return err
   191  	}
   192  	if n < 1000 {
   193  		return fmt.Errorf("short read from %s:%s->%s", network, c.RemoteAddr(), c.LocalAddr())
   194  	}
   195  	return nil
   196  }