rsc.io/go@v0.0.0-20150416155037-e040fd465409/src/net/lookup_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  	"strings"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  func lookupLocalhost(fn func(string) ([]IPAddr, error), host string) ([]IPAddr, error) {
    15  	switch host {
    16  	case "localhost":
    17  		return []IPAddr{
    18  			{IP: IPv4(127, 0, 0, 1)},
    19  			{IP: IPv6loopback},
    20  		}, nil
    21  	default:
    22  		return fn(host)
    23  	}
    24  }
    25  
    26  var lookupGoogleSRVTests = []struct {
    27  	service, proto, name string
    28  	cname, target        string
    29  }{
    30  	{
    31  		"xmpp-server", "tcp", "google.com",
    32  		".google.com", ".google.com",
    33  	},
    34  	{
    35  		"", "", "_xmpp-server._tcp.google.com", // non-standard back door
    36  		".google.com", ".google.com",
    37  	},
    38  }
    39  
    40  func TestLookupGoogleSRV(t *testing.T) {
    41  	if testing.Short() || !*testExternal {
    42  		t.Skip("skipping test to avoid external network")
    43  	}
    44  
    45  	for _, tt := range lookupGoogleSRVTests {
    46  		cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
    47  		if err != nil {
    48  			t.Fatal(err)
    49  		}
    50  		if len(srvs) == 0 {
    51  			t.Error("got no record")
    52  		}
    53  		if !strings.Contains(cname, tt.cname) {
    54  			t.Errorf("got %q; want %q", cname, tt.cname)
    55  		}
    56  		for _, srv := range srvs {
    57  			if !strings.Contains(srv.Target, tt.target) {
    58  				t.Errorf("got %v; want a record containing %q", srv, tt.target)
    59  			}
    60  		}
    61  	}
    62  }
    63  
    64  func TestLookupGmailMX(t *testing.T) {
    65  	if testing.Short() || !*testExternal {
    66  		t.Skip("skipping test to avoid external network")
    67  	}
    68  
    69  	mxs, err := LookupMX("gmail.com")
    70  	if err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	if len(mxs) == 0 {
    74  		t.Error("got no record")
    75  	}
    76  	for _, mx := range mxs {
    77  		if !strings.Contains(mx.Host, ".google.com") {
    78  			t.Errorf("got %v; want a record containing .google.com.", mx)
    79  		}
    80  	}
    81  }
    82  
    83  func TestLookupGmailNS(t *testing.T) {
    84  	if testing.Short() || !*testExternal {
    85  		t.Skip("skipping test to avoid external network")
    86  	}
    87  
    88  	nss, err := LookupNS("gmail.com")
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	if len(nss) == 0 {
    93  		t.Error("got no record")
    94  	}
    95  	for _, ns := range nss {
    96  		if !strings.Contains(ns.Host, ".google.com") {
    97  			t.Errorf("got %v; want a record containing .google.com.", ns)
    98  		}
    99  	}
   100  }
   101  
   102  func TestLookupGmailTXT(t *testing.T) {
   103  	if testing.Short() || !*testExternal {
   104  		t.Skip("skipping test to avoid external network")
   105  	}
   106  
   107  	txts, err := LookupTXT("gmail.com")
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	if len(txts) == 0 {
   112  		t.Error("got no record")
   113  	}
   114  	for _, txt := range txts {
   115  		if !strings.Contains(txt, "spf") {
   116  			t.Errorf("got %q; want a spf record", txt)
   117  		}
   118  	}
   119  }
   120  
   121  var lookupGooglePublicDNSAddrs = []struct {
   122  	addr string
   123  	name string
   124  }{
   125  	{"8.8.8.8", ".google.com."},
   126  	{"8.8.4.4", ".google.com."},
   127  	{"2001:4860:4860::8888", ".google.com."},
   128  	{"2001:4860:4860::8844", ".google.com."},
   129  }
   130  
   131  func TestLookupGooglePublicDNSAddr(t *testing.T) {
   132  	if testing.Short() || !*testExternal {
   133  		t.Skip("skipping test to avoid external network")
   134  	}
   135  
   136  	for _, tt := range lookupGooglePublicDNSAddrs {
   137  		names, err := LookupAddr(tt.addr)
   138  		if err != nil {
   139  			t.Fatal(err)
   140  		}
   141  		if len(names) == 0 {
   142  			t.Error("got no record")
   143  		}
   144  		for _, name := range names {
   145  			if !strings.HasSuffix(name, tt.name) {
   146  				t.Errorf("got %q; want a record containing %q", name, tt.name)
   147  			}
   148  		}
   149  	}
   150  }
   151  
   152  func TestLookupIANACNAME(t *testing.T) {
   153  	if testing.Short() || !*testExternal {
   154  		t.Skip("skipping test to avoid external network")
   155  	}
   156  
   157  	cname, err := LookupCNAME("www.iana.org")
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	if !strings.HasSuffix(cname, ".icann.org.") {
   162  		t.Errorf("got %q; want a record containing .icann.org.", cname)
   163  	}
   164  }
   165  
   166  func TestLookupGoogleHost(t *testing.T) {
   167  	if testing.Short() || !*testExternal {
   168  		t.Skip("skipping test to avoid external network")
   169  	}
   170  
   171  	addrs, err := LookupHost("google.com")
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	if len(addrs) == 0 {
   176  		t.Error("got no record")
   177  	}
   178  	for _, addr := range addrs {
   179  		if ParseIP(addr) == nil {
   180  			t.Errorf("got %q; want a literal ip address", addr)
   181  		}
   182  	}
   183  }
   184  
   185  func TestLookupGoogleIP(t *testing.T) {
   186  	if testing.Short() || !*testExternal {
   187  		t.Skip("skipping test to avoid external network")
   188  	}
   189  
   190  	ips, err := LookupIP("google.com")
   191  	if err != nil {
   192  		t.Fatal(err)
   193  	}
   194  	if len(ips) == 0 {
   195  		t.Error("got no record")
   196  	}
   197  	for _, ip := range ips {
   198  		if ip.To4() == nil && ip.To16() == nil {
   199  			t.Errorf("got %v; want an ip address", ip)
   200  		}
   201  	}
   202  }
   203  
   204  var revAddrTests = []struct {
   205  	Addr      string
   206  	Reverse   string
   207  	ErrPrefix string
   208  }{
   209  	{"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
   210  	{"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
   211  	{"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
   212  	{"::1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", ""},
   213  	{"1::", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa.", ""},
   214  	{"1234:567::89a:bcde", "e.d.c.b.a.9.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
   215  	{"1234:567:fefe:bcbc:adad:9e4a:89a:bcde", "e.d.c.b.a.9.8.0.a.4.e.9.d.a.d.a.c.b.c.b.e.f.e.f.7.6.5.0.4.3.2.1.ip6.arpa.", ""},
   216  	{"1.2.3", "", "unrecognized address"},
   217  	{"1.2.3.4.5", "", "unrecognized address"},
   218  	{"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
   219  	{"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
   220  }
   221  
   222  func TestReverseAddress(t *testing.T) {
   223  	for i, tt := range revAddrTests {
   224  		a, err := reverseaddr(tt.Addr)
   225  		if len(tt.ErrPrefix) > 0 && err == nil {
   226  			t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
   227  			continue
   228  		}
   229  		if len(tt.ErrPrefix) == 0 && err != nil {
   230  			t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
   231  		}
   232  		if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
   233  			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
   234  		}
   235  		if a != tt.Reverse {
   236  			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
   237  		}
   238  	}
   239  }
   240  
   241  func TestLookupIPDeadline(t *testing.T) {
   242  	if !*testDNSFlood {
   243  		t.Skip("test disabled; use -dnsflood to enable")
   244  	}
   245  
   246  	const N = 5000
   247  	const timeout = 3 * time.Second
   248  	c := make(chan error, 2*N)
   249  	for i := 0; i < N; i++ {
   250  		name := fmt.Sprintf("%d.net-test.golang.org", i)
   251  		go func() {
   252  			_, err := lookupIPDeadline(name, time.Now().Add(timeout/2))
   253  			c <- err
   254  		}()
   255  		go func() {
   256  			_, err := lookupIPDeadline(name, time.Now().Add(timeout))
   257  			c <- err
   258  		}()
   259  	}
   260  	qstats := struct {
   261  		succeeded, failed         int
   262  		timeout, temporary, other int
   263  		unknown                   int
   264  	}{}
   265  	deadline := time.After(timeout + time.Second)
   266  	for i := 0; i < 2*N; i++ {
   267  		select {
   268  		case <-deadline:
   269  			t.Fatal("deadline exceeded")
   270  		case err := <-c:
   271  			switch err := err.(type) {
   272  			case nil:
   273  				qstats.succeeded++
   274  			case Error:
   275  				qstats.failed++
   276  				if err.Timeout() {
   277  					qstats.timeout++
   278  				}
   279  				if err.Temporary() {
   280  					qstats.temporary++
   281  				}
   282  				if !err.Timeout() && !err.Temporary() {
   283  					qstats.other++
   284  				}
   285  			default:
   286  				qstats.failed++
   287  				qstats.unknown++
   288  			}
   289  		}
   290  	}
   291  
   292  	// A high volume of DNS queries for sub-domain of golang.org
   293  	// would be coordinated by authoritative or recursive server,
   294  	// or stub resolver which implements query-response rate
   295  	// limitation, so we can expect some query successes and more
   296  	// failures including timeout, temporary and other here.
   297  	// As a rule, unknown must not be shown but it might possibly
   298  	// happen due to issue 4856 for now.
   299  	t.Logf("%v succeeded, %v failed (%v timeout, %v temporary, %v other, %v unknown)", qstats.succeeded, qstats.failed, qstats.timeout, qstats.temporary, qstats.other, qstats.unknown)
   300  }