github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/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  	"bytes"
     9  	"fmt"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  func lookupLocalhost(fn func(string) ([]IPAddr, error), host string) ([]IPAddr, error) {
    16  	switch host {
    17  	case "localhost":
    18  		return []IPAddr{
    19  			{IP: IPv4(127, 0, 0, 1)},
    20  			{IP: IPv6loopback},
    21  		}, nil
    22  	default:
    23  		return fn(host)
    24  	}
    25  }
    26  
    27  // The Lookup APIs use various sources such as local database, DNS or
    28  // mDNS, and may use platform-dependent DNS stub resolver if possible.
    29  // The APIs accept any of forms for a query; host name in various
    30  // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
    31  // FQDN, but the result would be one of the forms and it depends on
    32  // the circumstances.
    33  
    34  var lookupGoogleSRVTests = []struct {
    35  	service, proto, name string
    36  	cname, target        string
    37  }{
    38  	{
    39  		"xmpp-server", "tcp", "google.com",
    40  		"google.com", "google.com",
    41  	},
    42  	{
    43  		"xmpp-server", "tcp", "google.com.",
    44  		"google.com", "google.com",
    45  	},
    46  
    47  	// non-standard back door
    48  	{
    49  		"", "", "_xmpp-server._tcp.google.com",
    50  		"google.com", "google.com",
    51  	},
    52  	{
    53  		"", "", "_xmpp-server._tcp.google.com.",
    54  		"google.com", "google.com",
    55  	},
    56  }
    57  
    58  func TestLookupGoogleSRV(t *testing.T) {
    59  	if testing.Short() || !*testExternal {
    60  		t.Skip("avoid external network")
    61  	}
    62  	if !supportsIPv4 || !*testIPv4 {
    63  		t.Skip("IPv4 is required")
    64  	}
    65  
    66  	for _, tt := range lookupGoogleSRVTests {
    67  		cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
    68  		if err != nil {
    69  			t.Fatal(err)
    70  		}
    71  		if len(srvs) == 0 {
    72  			t.Error("got no record")
    73  		}
    74  		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
    75  			t.Errorf("got %s; want %s", cname, tt.cname)
    76  		}
    77  		for _, srv := range srvs {
    78  			if !strings.HasSuffix(srv.Target, tt.target) && !strings.HasSuffix(srv.Target, tt.target+".") {
    79  				t.Errorf("got %v; want a record containing %s", srv, tt.target)
    80  			}
    81  		}
    82  	}
    83  }
    84  
    85  var lookupGmailMXTests = []struct {
    86  	name, host string
    87  }{
    88  	{"gmail.com", "google.com"},
    89  	{"gmail.com.", "google.com"},
    90  }
    91  
    92  func TestLookupGmailMX(t *testing.T) {
    93  	if testing.Short() || !*testExternal {
    94  		t.Skip("avoid external network")
    95  	}
    96  	if !supportsIPv4 || !*testIPv4 {
    97  		t.Skip("IPv4 is required")
    98  	}
    99  
   100  	for _, tt := range lookupGmailMXTests {
   101  		mxs, err := LookupMX(tt.name)
   102  		if err != nil {
   103  			t.Fatal(err)
   104  		}
   105  		if len(mxs) == 0 {
   106  			t.Error("got no record")
   107  		}
   108  		for _, mx := range mxs {
   109  			if !strings.HasSuffix(mx.Host, tt.host) && !strings.HasSuffix(mx.Host, tt.host+".") {
   110  				t.Errorf("got %v; want a record containing %s", mx, tt.host)
   111  			}
   112  		}
   113  	}
   114  }
   115  
   116  var lookupGmailNSTests = []struct {
   117  	name, host string
   118  }{
   119  	{"gmail.com", "google.com"},
   120  	{"gmail.com.", "google.com"},
   121  }
   122  
   123  func TestLookupGmailNS(t *testing.T) {
   124  	if testing.Short() || !*testExternal {
   125  		t.Skip("avoid external network")
   126  	}
   127  	if !supportsIPv4 || !*testIPv4 {
   128  		t.Skip("IPv4 is required")
   129  	}
   130  
   131  	for _, tt := range lookupGmailNSTests {
   132  		nss, err := LookupNS(tt.name)
   133  		if err != nil {
   134  			t.Fatal(err)
   135  		}
   136  		if len(nss) == 0 {
   137  			t.Error("got no record")
   138  		}
   139  		for _, ns := range nss {
   140  			if !strings.HasSuffix(ns.Host, tt.host) && !strings.HasSuffix(ns.Host, tt.host+".") {
   141  				t.Errorf("got %v; want a record containing %s", ns, tt.host)
   142  			}
   143  		}
   144  	}
   145  }
   146  
   147  var lookupGmailTXTTests = []struct {
   148  	name, txt, host string
   149  }{
   150  	{"gmail.com", "spf", "google.com"},
   151  	{"gmail.com.", "spf", "google.com"},
   152  }
   153  
   154  func TestLookupGmailTXT(t *testing.T) {
   155  	if testing.Short() || !*testExternal {
   156  		t.Skip("avoid external network")
   157  	}
   158  	if !supportsIPv4 || !*testIPv4 {
   159  		t.Skip("IPv4 is required")
   160  	}
   161  
   162  	for _, tt := range lookupGmailTXTTests {
   163  		txts, err := LookupTXT(tt.name)
   164  		if err != nil {
   165  			t.Fatal(err)
   166  		}
   167  		if len(txts) == 0 {
   168  			t.Error("got no record")
   169  		}
   170  		for _, txt := range txts {
   171  			if !strings.Contains(txt, tt.txt) || (!strings.HasSuffix(txt, tt.host) && !strings.HasSuffix(txt, tt.host+".")) {
   172  				t.Errorf("got %s; want a record containing %s, %s", txt, tt.txt, tt.host)
   173  			}
   174  		}
   175  	}
   176  }
   177  
   178  var lookupGooglePublicDNSAddrTests = []struct {
   179  	addr, name string
   180  }{
   181  	{"8.8.8.8", ".google.com"},
   182  	{"8.8.4.4", ".google.com"},
   183  	{"2001:4860:4860::8888", ".google.com"},
   184  	{"2001:4860:4860::8844", ".google.com"},
   185  }
   186  
   187  func TestLookupGooglePublicDNSAddr(t *testing.T) {
   188  	if testing.Short() || !*testExternal {
   189  		t.Skip("avoid external network")
   190  	}
   191  	if !supportsIPv4 || !supportsIPv6 || !*testIPv4 || !*testIPv6 {
   192  		t.Skip("both IPv4 and IPv6 are required")
   193  	}
   194  
   195  	for _, tt := range lookupGooglePublicDNSAddrTests {
   196  		names, err := LookupAddr(tt.addr)
   197  		if err != nil {
   198  			t.Fatal(err)
   199  		}
   200  		if len(names) == 0 {
   201  			t.Error("got no record")
   202  		}
   203  		for _, name := range names {
   204  			if !strings.HasSuffix(name, tt.name) && !strings.HasSuffix(name, tt.name+".") {
   205  				t.Errorf("got %s; want a record containing %s", name, tt.name)
   206  			}
   207  		}
   208  	}
   209  }
   210  
   211  var lookupIANACNAMETests = []struct {
   212  	name, cname string
   213  }{
   214  	{"www.iana.org", "icann.org"},
   215  	{"www.iana.org.", "icann.org"},
   216  }
   217  
   218  func TestLookupIANACNAME(t *testing.T) {
   219  	if testing.Short() || !*testExternal {
   220  		t.Skip("avoid external network")
   221  	}
   222  	if !supportsIPv4 || !*testIPv4 {
   223  		t.Skip("IPv4 is required")
   224  	}
   225  
   226  	for _, tt := range lookupIANACNAMETests {
   227  		cname, err := LookupCNAME(tt.name)
   228  		if err != nil {
   229  			t.Fatal(err)
   230  		}
   231  		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
   232  			t.Errorf("got %s; want a record containing %s", cname, tt.cname)
   233  		}
   234  	}
   235  }
   236  
   237  var lookupGoogleHostTests = []struct {
   238  	name string
   239  }{
   240  	{"google.com"},
   241  	{"google.com."},
   242  }
   243  
   244  func TestLookupGoogleHost(t *testing.T) {
   245  	if testing.Short() || !*testExternal {
   246  		t.Skip("avoid external network")
   247  	}
   248  	if !supportsIPv4 || !*testIPv4 {
   249  		t.Skip("IPv4 is required")
   250  	}
   251  
   252  	for _, tt := range lookupGoogleHostTests {
   253  		addrs, err := LookupHost(tt.name)
   254  		if err != nil {
   255  			t.Fatal(err)
   256  		}
   257  		if len(addrs) == 0 {
   258  			t.Error("got no record")
   259  		}
   260  		for _, addr := range addrs {
   261  			if ParseIP(addr) == nil {
   262  				t.Errorf("got %q; want a literal IP address", addr)
   263  			}
   264  		}
   265  	}
   266  }
   267  
   268  var lookupGoogleIPTests = []struct {
   269  	name string
   270  }{
   271  	{"google.com"},
   272  	{"google.com."},
   273  }
   274  
   275  func TestLookupGoogleIP(t *testing.T) {
   276  	if testing.Short() || !*testExternal {
   277  		t.Skip("avoid external network")
   278  	}
   279  	if !supportsIPv4 || !*testIPv4 {
   280  		t.Skip("IPv4 is required")
   281  	}
   282  
   283  	for _, tt := range lookupGoogleIPTests {
   284  		ips, err := LookupIP(tt.name)
   285  		if err != nil {
   286  			t.Fatal(err)
   287  		}
   288  		if len(ips) == 0 {
   289  			t.Error("got no record")
   290  		}
   291  		for _, ip := range ips {
   292  			if ip.To4() == nil && ip.To16() == nil {
   293  				t.Errorf("got %v; want an IP address", ip)
   294  			}
   295  		}
   296  	}
   297  }
   298  
   299  var revAddrTests = []struct {
   300  	Addr      string
   301  	Reverse   string
   302  	ErrPrefix string
   303  }{
   304  	{"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
   305  	{"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
   306  	{"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
   307  	{"::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.", ""},
   308  	{"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.", ""},
   309  	{"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.", ""},
   310  	{"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.", ""},
   311  	{"1.2.3", "", "unrecognized address"},
   312  	{"1.2.3.4.5", "", "unrecognized address"},
   313  	{"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
   314  	{"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
   315  }
   316  
   317  func TestReverseAddress(t *testing.T) {
   318  	for i, tt := range revAddrTests {
   319  		a, err := reverseaddr(tt.Addr)
   320  		if len(tt.ErrPrefix) > 0 && err == nil {
   321  			t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
   322  			continue
   323  		}
   324  		if len(tt.ErrPrefix) == 0 && err != nil {
   325  			t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
   326  		}
   327  		if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
   328  			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
   329  		}
   330  		if a != tt.Reverse {
   331  			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
   332  		}
   333  	}
   334  }
   335  
   336  func TestLookupIPDeadline(t *testing.T) {
   337  	if !*testDNSFlood {
   338  		t.Skip("test disabled; use -dnsflood to enable")
   339  	}
   340  
   341  	const N = 5000
   342  	const timeout = 3 * time.Second
   343  	c := make(chan error, 2*N)
   344  	for i := 0; i < N; i++ {
   345  		name := fmt.Sprintf("%d.net-test.golang.org", i)
   346  		go func() {
   347  			_, err := lookupIPDeadline(name, time.Now().Add(timeout/2))
   348  			c <- err
   349  		}()
   350  		go func() {
   351  			_, err := lookupIPDeadline(name, time.Now().Add(timeout))
   352  			c <- err
   353  		}()
   354  	}
   355  	qstats := struct {
   356  		succeeded, failed         int
   357  		timeout, temporary, other int
   358  		unknown                   int
   359  	}{}
   360  	deadline := time.After(timeout + time.Second)
   361  	for i := 0; i < 2*N; i++ {
   362  		select {
   363  		case <-deadline:
   364  			t.Fatal("deadline exceeded")
   365  		case err := <-c:
   366  			switch err := err.(type) {
   367  			case nil:
   368  				qstats.succeeded++
   369  			case Error:
   370  				qstats.failed++
   371  				if err.Timeout() {
   372  					qstats.timeout++
   373  				}
   374  				if err.Temporary() {
   375  					qstats.temporary++
   376  				}
   377  				if !err.Timeout() && !err.Temporary() {
   378  					qstats.other++
   379  				}
   380  			default:
   381  				qstats.failed++
   382  				qstats.unknown++
   383  			}
   384  		}
   385  	}
   386  
   387  	// A high volume of DNS queries for sub-domain of golang.org
   388  	// would be coordinated by authoritative or recursive server,
   389  	// or stub resolver which implements query-response rate
   390  	// limitation, so we can expect some query successes and more
   391  	// failures including timeout, temporary and other here.
   392  	// As a rule, unknown must not be shown but it might possibly
   393  	// happen due to issue 4856 for now.
   394  	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)
   395  }
   396  
   397  func TestLookupDots(t *testing.T) {
   398  	if testing.Short() || !*testExternal {
   399  		t.Skipf("skipping external network test")
   400  	}
   401  
   402  	fixup := forceGoDNS()
   403  	defer fixup()
   404  	testDots(t, "go")
   405  
   406  	if forceCgoDNS() {
   407  		testDots(t, "cgo")
   408  	}
   409  }
   410  
   411  func testDots(t *testing.T, mode string) {
   412  	names, err := LookupAddr("8.8.8.8") // Google dns server
   413  	if err != nil {
   414  		t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
   415  	} else {
   416  		for _, name := range names {
   417  			if !strings.HasSuffix(name, ".google.com.") {
   418  				t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
   419  				break
   420  			}
   421  		}
   422  	}
   423  
   424  	cname, err := LookupCNAME("www.mit.edu")
   425  	if err != nil || !strings.HasSuffix(cname, ".") {
   426  		t.Errorf("LookupCNAME(www.mit.edu) = %v, %v, want cname ending in . with trailing dot (mode=%v)", cname, err, mode)
   427  	}
   428  
   429  	mxs, err := LookupMX("google.com")
   430  	if err != nil {
   431  		t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
   432  	} else {
   433  		for _, mx := range mxs {
   434  			if !strings.HasSuffix(mx.Host, ".google.com.") {
   435  				t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
   436  				break
   437  			}
   438  		}
   439  	}
   440  
   441  	nss, err := LookupNS("google.com")
   442  	if err != nil {
   443  		t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
   444  	} else {
   445  		for _, ns := range nss {
   446  			if !strings.HasSuffix(ns.Host, ".google.com.") {
   447  				t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
   448  				break
   449  			}
   450  		}
   451  	}
   452  
   453  	cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
   454  	if err != nil {
   455  		t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
   456  	} else {
   457  		if !strings.HasSuffix(cname, ".google.com.") {
   458  			t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
   459  		}
   460  		for _, srv := range srvs {
   461  			if !strings.HasSuffix(srv.Target, ".google.com.") {
   462  				t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned addrs=%v, want names ending in .google.com. with trailing dot (mode=%v)", srvString(srvs), mode)
   463  				break
   464  			}
   465  		}
   466  	}
   467  }
   468  
   469  func mxString(mxs []*MX) string {
   470  	var buf bytes.Buffer
   471  	sep := ""
   472  	fmt.Fprintf(&buf, "[")
   473  	for _, mx := range mxs {
   474  		fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
   475  		sep = " "
   476  	}
   477  	fmt.Fprintf(&buf, "]")
   478  	return buf.String()
   479  }
   480  
   481  func nsString(nss []*NS) string {
   482  	var buf bytes.Buffer
   483  	sep := ""
   484  	fmt.Fprintf(&buf, "[")
   485  	for _, ns := range nss {
   486  		fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
   487  		sep = " "
   488  	}
   489  	fmt.Fprintf(&buf, "]")
   490  	return buf.String()
   491  }
   492  
   493  func srvString(srvs []*SRV) string {
   494  	var buf bytes.Buffer
   495  	sep := ""
   496  	fmt.Fprintf(&buf, "[")
   497  	for _, srv := range srvs {
   498  		fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
   499  		sep = " "
   500  	}
   501  	fmt.Fprintf(&buf, "]")
   502  	return buf.String()
   503  }