github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/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  // The Lookup APIs use various sources such as local database, DNS or
    27  // mDNS, and may use platform-dependent DNS stub resolver if possible.
    28  // The APIs accept any of forms for a query; host name in various
    29  // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
    30  // FQDN, but the result would be one of the forms and it depends on
    31  // the circumstances.
    32  
    33  var lookupGoogleSRVTests = []struct {
    34  	service, proto, name string
    35  	cname, target        string
    36  }{
    37  	{
    38  		"xmpp-server", "tcp", "google.com",
    39  		"google.com", "google.com",
    40  	},
    41  	{
    42  		"xmpp-server", "tcp", "google.com.",
    43  		"google.com", "google.com",
    44  	},
    45  
    46  	// non-standard back door
    47  	{
    48  		"", "", "_xmpp-server._tcp.google.com",
    49  		"google.com", "google.com",
    50  	},
    51  	{
    52  		"", "", "_xmpp-server._tcp.google.com.",
    53  		"google.com", "google.com",
    54  	},
    55  }
    56  
    57  func TestLookupGoogleSRV(t *testing.T) {
    58  	if testing.Short() || !*testExternal {
    59  		t.Skip("avoid external network")
    60  	}
    61  	if !supportsIPv4 || !*testIPv4 {
    62  		t.Skip("IPv4 is required")
    63  	}
    64  
    65  	for _, tt := range lookupGoogleSRVTests {
    66  		cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
    67  		if err != nil {
    68  			t.Fatal(err)
    69  		}
    70  		if len(srvs) == 0 {
    71  			t.Error("got no record")
    72  		}
    73  		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
    74  			t.Errorf("got %s; want %s", cname, tt.cname)
    75  		}
    76  		for _, srv := range srvs {
    77  			if !strings.HasSuffix(srv.Target, tt.target) && !strings.HasSuffix(srv.Target, tt.target+".") {
    78  				t.Errorf("got %v; want a record containing %s", srv, tt.target)
    79  			}
    80  		}
    81  	}
    82  }
    83  
    84  var lookupGmailMXTests = []struct {
    85  	name, host string
    86  }{
    87  	{"gmail.com", "google.com"},
    88  	{"gmail.com.", "google.com"},
    89  }
    90  
    91  func TestLookupGmailMX(t *testing.T) {
    92  	if testing.Short() || !*testExternal {
    93  		t.Skip("avoid external network")
    94  	}
    95  	if !supportsIPv4 || !*testIPv4 {
    96  		t.Skip("IPv4 is required")
    97  	}
    98  
    99  	for _, tt := range lookupGmailMXTests {
   100  		mxs, err := LookupMX(tt.name)
   101  		if err != nil {
   102  			t.Fatal(err)
   103  		}
   104  		if len(mxs) == 0 {
   105  			t.Error("got no record")
   106  		}
   107  		for _, mx := range mxs {
   108  			if !strings.HasSuffix(mx.Host, tt.host) && !strings.HasSuffix(mx.Host, tt.host+".") {
   109  				t.Errorf("got %v; want a record containing %s", mx, tt.host)
   110  			}
   111  		}
   112  	}
   113  }
   114  
   115  var lookupGmailNSTests = []struct {
   116  	name, host string
   117  }{
   118  	{"gmail.com", "google.com"},
   119  	{"gmail.com.", "google.com"},
   120  }
   121  
   122  func TestLookupGmailNS(t *testing.T) {
   123  	if testing.Short() || !*testExternal {
   124  		t.Skip("avoid external network")
   125  	}
   126  	if !supportsIPv4 || !*testIPv4 {
   127  		t.Skip("IPv4 is required")
   128  	}
   129  
   130  	for _, tt := range lookupGmailNSTests {
   131  		nss, err := LookupNS(tt.name)
   132  		if err != nil {
   133  			t.Fatal(err)
   134  		}
   135  		if len(nss) == 0 {
   136  			t.Error("got no record")
   137  		}
   138  		for _, ns := range nss {
   139  			if !strings.HasSuffix(ns.Host, tt.host) && !strings.HasSuffix(ns.Host, tt.host+".") {
   140  				t.Errorf("got %v; want a record containing %s", ns, tt.host)
   141  			}
   142  		}
   143  	}
   144  }
   145  
   146  var lookupGmailTXTTests = []struct {
   147  	name, txt, host string
   148  }{
   149  	{"gmail.com", "spf", "google.com"},
   150  	{"gmail.com.", "spf", "google.com"},
   151  }
   152  
   153  func TestLookupGmailTXT(t *testing.T) {
   154  	if testing.Short() || !*testExternal {
   155  		t.Skip("avoid external network")
   156  	}
   157  	if !supportsIPv4 || !*testIPv4 {
   158  		t.Skip("IPv4 is required")
   159  	}
   160  
   161  	for _, tt := range lookupGmailTXTTests {
   162  		txts, err := LookupTXT(tt.name)
   163  		if err != nil {
   164  			t.Fatal(err)
   165  		}
   166  		if len(txts) == 0 {
   167  			t.Error("got no record")
   168  		}
   169  		for _, txt := range txts {
   170  			if !strings.Contains(txt, tt.txt) || (!strings.HasSuffix(txt, tt.host) && !strings.HasSuffix(txt, tt.host+".")) {
   171  				t.Errorf("got %s; want a record containing %s, %s", txt, tt.txt, tt.host)
   172  			}
   173  		}
   174  	}
   175  }
   176  
   177  var lookupGooglePublicDNSAddrTests = []struct {
   178  	addr, name string
   179  }{
   180  	{"8.8.8.8", ".google.com"},
   181  	{"8.8.4.4", ".google.com"},
   182  	{"2001:4860:4860::8888", ".google.com"},
   183  	{"2001:4860:4860::8844", ".google.com"},
   184  }
   185  
   186  func TestLookupGooglePublicDNSAddr(t *testing.T) {
   187  	if testing.Short() || !*testExternal {
   188  		t.Skip("avoid external network")
   189  	}
   190  	if !supportsIPv4 || !supportsIPv6 || !*testIPv4 || !*testIPv6 {
   191  		t.Skip("both IPv4 and IPv6 are required")
   192  	}
   193  
   194  	for _, tt := range lookupGooglePublicDNSAddrTests {
   195  		names, err := LookupAddr(tt.addr)
   196  		if err != nil {
   197  			t.Fatal(err)
   198  		}
   199  		if len(names) == 0 {
   200  			t.Error("got no record")
   201  		}
   202  		for _, name := range names {
   203  			if !strings.HasSuffix(name, tt.name) && !strings.HasSuffix(name, tt.name+".") {
   204  				t.Errorf("got %s; want a record containing %s", name, tt.name)
   205  			}
   206  		}
   207  	}
   208  }
   209  
   210  var lookupIANACNAMETests = []struct {
   211  	name, cname string
   212  }{
   213  	{"www.iana.org", "icann.org"},
   214  	{"www.iana.org.", "icann.org"},
   215  }
   216  
   217  func TestLookupIANACNAME(t *testing.T) {
   218  	if testing.Short() || !*testExternal {
   219  		t.Skip("avoid external network")
   220  	}
   221  	if !supportsIPv4 || !*testIPv4 {
   222  		t.Skip("IPv4 is required")
   223  	}
   224  
   225  	for _, tt := range lookupIANACNAMETests {
   226  		cname, err := LookupCNAME(tt.name)
   227  		if err != nil {
   228  			t.Fatal(err)
   229  		}
   230  		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
   231  			t.Errorf("got %s; want a record containing %s", cname, tt.cname)
   232  		}
   233  	}
   234  }
   235  
   236  var lookupGoogleHostTests = []struct {
   237  	name string
   238  }{
   239  	{"google.com"},
   240  	{"google.com."},
   241  }
   242  
   243  func TestLookupGoogleHost(t *testing.T) {
   244  	if testing.Short() || !*testExternal {
   245  		t.Skip("avoid external network")
   246  	}
   247  	if !supportsIPv4 || !*testIPv4 {
   248  		t.Skip("IPv4 is required")
   249  	}
   250  
   251  	for _, tt := range lookupGoogleHostTests {
   252  		addrs, err := LookupHost(tt.name)
   253  		if err != nil {
   254  			t.Fatal(err)
   255  		}
   256  		if len(addrs) == 0 {
   257  			t.Error("got no record")
   258  		}
   259  		for _, addr := range addrs {
   260  			if ParseIP(addr) == nil {
   261  				t.Errorf("got %q; want a literal IP address", addr)
   262  			}
   263  		}
   264  	}
   265  }
   266  
   267  var lookupGoogleIPTests = []struct {
   268  	name string
   269  }{
   270  	{"google.com"},
   271  	{"google.com."},
   272  }
   273  
   274  func TestLookupGoogleIP(t *testing.T) {
   275  	if testing.Short() || !*testExternal {
   276  		t.Skip("avoid external network")
   277  	}
   278  	if !supportsIPv4 || !*testIPv4 {
   279  		t.Skip("IPv4 is required")
   280  	}
   281  
   282  	for _, tt := range lookupGoogleIPTests {
   283  		ips, err := LookupIP(tt.name)
   284  		if err != nil {
   285  			t.Fatal(err)
   286  		}
   287  		if len(ips) == 0 {
   288  			t.Error("got no record")
   289  		}
   290  		for _, ip := range ips {
   291  			if ip.To4() == nil && ip.To16() == nil {
   292  				t.Errorf("got %v; want an IP address", ip)
   293  			}
   294  		}
   295  	}
   296  }
   297  
   298  var revAddrTests = []struct {
   299  	Addr      string
   300  	Reverse   string
   301  	ErrPrefix string
   302  }{
   303  	{"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
   304  	{"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
   305  	{"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
   306  	{"::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.", ""},
   307  	{"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.", ""},
   308  	{"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.", ""},
   309  	{"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.", ""},
   310  	{"1.2.3", "", "unrecognized address"},
   311  	{"1.2.3.4.5", "", "unrecognized address"},
   312  	{"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
   313  	{"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
   314  }
   315  
   316  func TestReverseAddress(t *testing.T) {
   317  	for i, tt := range revAddrTests {
   318  		a, err := reverseaddr(tt.Addr)
   319  		if len(tt.ErrPrefix) > 0 && err == nil {
   320  			t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
   321  			continue
   322  		}
   323  		if len(tt.ErrPrefix) == 0 && err != nil {
   324  			t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
   325  		}
   326  		if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
   327  			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
   328  		}
   329  		if a != tt.Reverse {
   330  			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
   331  		}
   332  	}
   333  }
   334  
   335  func TestLookupIPDeadline(t *testing.T) {
   336  	if !*testDNSFlood {
   337  		t.Skip("test disabled; use -dnsflood to enable")
   338  	}
   339  
   340  	const N = 5000
   341  	const timeout = 3 * time.Second
   342  	c := make(chan error, 2*N)
   343  	for i := 0; i < N; i++ {
   344  		name := fmt.Sprintf("%d.net-test.golang.org", i)
   345  		go func() {
   346  			_, err := lookupIPDeadline(name, time.Now().Add(timeout/2))
   347  			c <- err
   348  		}()
   349  		go func() {
   350  			_, err := lookupIPDeadline(name, time.Now().Add(timeout))
   351  			c <- err
   352  		}()
   353  	}
   354  	qstats := struct {
   355  		succeeded, failed         int
   356  		timeout, temporary, other int
   357  		unknown                   int
   358  	}{}
   359  	deadline := time.After(timeout + time.Second)
   360  	for i := 0; i < 2*N; i++ {
   361  		select {
   362  		case <-deadline:
   363  			t.Fatal("deadline exceeded")
   364  		case err := <-c:
   365  			switch err := err.(type) {
   366  			case nil:
   367  				qstats.succeeded++
   368  			case Error:
   369  				qstats.failed++
   370  				if err.Timeout() {
   371  					qstats.timeout++
   372  				}
   373  				if err.Temporary() {
   374  					qstats.temporary++
   375  				}
   376  				if !err.Timeout() && !err.Temporary() {
   377  					qstats.other++
   378  				}
   379  			default:
   380  				qstats.failed++
   381  				qstats.unknown++
   382  			}
   383  		}
   384  	}
   385  
   386  	// A high volume of DNS queries for sub-domain of golang.org
   387  	// would be coordinated by authoritative or recursive server,
   388  	// or stub resolver which implements query-response rate
   389  	// limitation, so we can expect some query successes and more
   390  	// failures including timeout, temporary and other here.
   391  	// As a rule, unknown must not be shown but it might possibly
   392  	// happen due to issue 4856 for now.
   393  	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)
   394  }