...

Source file src/net/lookup_test.go

Documentation: net

		 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  //go:build !js
		 6  // +build !js
		 7  
		 8  package net
		 9  
		10  import (
		11  	"bytes"
		12  	"context"
		13  	"fmt"
		14  	"internal/testenv"
		15  	"reflect"
		16  	"runtime"
		17  	"sort"
		18  	"strings"
		19  	"sync"
		20  	"sync/atomic"
		21  	"testing"
		22  	"time"
		23  )
		24  
		25  func hasSuffixFold(s, suffix string) bool {
		26  	return strings.HasSuffix(strings.ToLower(s), strings.ToLower(suffix))
		27  }
		28  
		29  func lookupLocalhost(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
		30  	switch host {
		31  	case "localhost":
		32  		return []IPAddr{
		33  			{IP: IPv4(127, 0, 0, 1)},
		34  			{IP: IPv6loopback},
		35  		}, nil
		36  	default:
		37  		return fn(ctx, network, host)
		38  	}
		39  }
		40  
		41  // The Lookup APIs use various sources such as local database, DNS or
		42  // mDNS, and may use platform-dependent DNS stub resolver if possible.
		43  // The APIs accept any of forms for a query; host name in various
		44  // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
		45  // FQDN, but the result would be one of the forms and it depends on
		46  // the circumstances.
		47  
		48  var lookupGoogleSRVTests = []struct {
		49  	service, proto, name string
		50  	cname, target				string
		51  }{
		52  	{
		53  		"xmpp-server", "tcp", "google.com",
		54  		"google.com.", "google.com.",
		55  	},
		56  	{
		57  		"xmpp-server", "tcp", "google.com.",
		58  		"google.com.", "google.com.",
		59  	},
		60  
		61  	// non-standard back door
		62  	{
		63  		"", "", "_xmpp-server._tcp.google.com",
		64  		"google.com.", "google.com.",
		65  	},
		66  	{
		67  		"", "", "_xmpp-server._tcp.google.com.",
		68  		"google.com.", "google.com.",
		69  	},
		70  }
		71  
		72  var backoffDuration = [...]time.Duration{time.Second, 5 * time.Second, 30 * time.Second}
		73  
		74  func TestLookupGoogleSRV(t *testing.T) {
		75  	t.Parallel()
		76  	mustHaveExternalNetwork(t)
		77  
		78  	if iOS() {
		79  		t.Skip("no resolv.conf on iOS")
		80  	}
		81  
		82  	if !supportsIPv4() || !*testIPv4 {
		83  		t.Skip("IPv4 is required")
		84  	}
		85  
		86  	attempts := 0
		87  	for i := 0; i < len(lookupGoogleSRVTests); i++ {
		88  		tt := lookupGoogleSRVTests[i]
		89  		cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
		90  		if err != nil {
		91  			testenv.SkipFlakyNet(t)
		92  			if attempts < len(backoffDuration) {
		93  				dur := backoffDuration[attempts]
		94  				t.Logf("backoff %v after failure %v\n", dur, err)
		95  				time.Sleep(dur)
		96  				attempts++
		97  				i--
		98  				continue
		99  			}
	 100  			t.Fatal(err)
	 101  		}
	 102  		if len(srvs) == 0 {
	 103  			t.Error("got no record")
	 104  		}
	 105  		if !hasSuffixFold(cname, tt.cname) {
	 106  			t.Errorf("got %s; want %s", cname, tt.cname)
	 107  		}
	 108  		for _, srv := range srvs {
	 109  			if !hasSuffixFold(srv.Target, tt.target) {
	 110  				t.Errorf("got %v; want a record containing %s", srv, tt.target)
	 111  			}
	 112  		}
	 113  	}
	 114  }
	 115  
	 116  var lookupGmailMXTests = []struct {
	 117  	name, host string
	 118  }{
	 119  	{"gmail.com", "google.com."},
	 120  	{"gmail.com.", "google.com."},
	 121  }
	 122  
	 123  func TestLookupGmailMX(t *testing.T) {
	 124  	t.Parallel()
	 125  	mustHaveExternalNetwork(t)
	 126  
	 127  	if iOS() {
	 128  		t.Skip("no resolv.conf on iOS")
	 129  	}
	 130  
	 131  	if !supportsIPv4() || !*testIPv4 {
	 132  		t.Skip("IPv4 is required")
	 133  	}
	 134  
	 135  	attempts := 0
	 136  	for i := 0; i < len(lookupGmailMXTests); i++ {
	 137  		tt := lookupGmailMXTests[i]
	 138  		mxs, err := LookupMX(tt.name)
	 139  		if err != nil {
	 140  			testenv.SkipFlakyNet(t)
	 141  			if attempts < len(backoffDuration) {
	 142  				dur := backoffDuration[attempts]
	 143  				t.Logf("backoff %v after failure %v\n", dur, err)
	 144  				time.Sleep(dur)
	 145  				attempts++
	 146  				i--
	 147  				continue
	 148  			}
	 149  			t.Fatal(err)
	 150  		}
	 151  		if len(mxs) == 0 {
	 152  			t.Error("got no record")
	 153  		}
	 154  		for _, mx := range mxs {
	 155  			if !hasSuffixFold(mx.Host, tt.host) {
	 156  				t.Errorf("got %v; want a record containing %s", mx, tt.host)
	 157  			}
	 158  		}
	 159  	}
	 160  }
	 161  
	 162  var lookupGmailNSTests = []struct {
	 163  	name, host string
	 164  }{
	 165  	{"gmail.com", "google.com."},
	 166  	{"gmail.com.", "google.com."},
	 167  }
	 168  
	 169  func TestLookupGmailNS(t *testing.T) {
	 170  	t.Parallel()
	 171  	mustHaveExternalNetwork(t)
	 172  
	 173  	if iOS() {
	 174  		t.Skip("no resolv.conf on iOS")
	 175  	}
	 176  
	 177  	if !supportsIPv4() || !*testIPv4 {
	 178  		t.Skip("IPv4 is required")
	 179  	}
	 180  
	 181  	attempts := 0
	 182  	for i := 0; i < len(lookupGmailNSTests); i++ {
	 183  		tt := lookupGmailNSTests[i]
	 184  		nss, err := LookupNS(tt.name)
	 185  		if err != nil {
	 186  			testenv.SkipFlakyNet(t)
	 187  			if attempts < len(backoffDuration) {
	 188  				dur := backoffDuration[attempts]
	 189  				t.Logf("backoff %v after failure %v\n", dur, err)
	 190  				time.Sleep(dur)
	 191  				attempts++
	 192  				i--
	 193  				continue
	 194  			}
	 195  			t.Fatal(err)
	 196  		}
	 197  		if len(nss) == 0 {
	 198  			t.Error("got no record")
	 199  		}
	 200  		for _, ns := range nss {
	 201  			if !hasSuffixFold(ns.Host, tt.host) {
	 202  				t.Errorf("got %v; want a record containing %s", ns, tt.host)
	 203  			}
	 204  		}
	 205  	}
	 206  }
	 207  
	 208  var lookupGmailTXTTests = []struct {
	 209  	name, txt, host string
	 210  }{
	 211  	{"gmail.com", "spf", "google.com"},
	 212  	{"gmail.com.", "spf", "google.com"},
	 213  }
	 214  
	 215  func TestLookupGmailTXT(t *testing.T) {
	 216  	if runtime.GOOS == "plan9" {
	 217  		t.Skip("skipping on plan9; see https://golang.org/issue/29722")
	 218  	}
	 219  	t.Parallel()
	 220  	mustHaveExternalNetwork(t)
	 221  
	 222  	if iOS() {
	 223  		t.Skip("no resolv.conf on iOS")
	 224  	}
	 225  
	 226  	if !supportsIPv4() || !*testIPv4 {
	 227  		t.Skip("IPv4 is required")
	 228  	}
	 229  
	 230  	attempts := 0
	 231  	for i := 0; i < len(lookupGmailTXTTests); i++ {
	 232  		tt := lookupGmailTXTTests[i]
	 233  		txts, err := LookupTXT(tt.name)
	 234  		if err != nil {
	 235  			testenv.SkipFlakyNet(t)
	 236  			if attempts < len(backoffDuration) {
	 237  				dur := backoffDuration[attempts]
	 238  				t.Logf("backoff %v after failure %v\n", dur, err)
	 239  				time.Sleep(dur)
	 240  				attempts++
	 241  				i--
	 242  				continue
	 243  			}
	 244  			t.Fatal(err)
	 245  		}
	 246  		if len(txts) == 0 {
	 247  			t.Error("got no record")
	 248  		}
	 249  		found := false
	 250  		for _, txt := range txts {
	 251  			if strings.Contains(txt, tt.txt) && (strings.HasSuffix(txt, tt.host) || strings.HasSuffix(txt, tt.host+".")) {
	 252  				found = true
	 253  				break
	 254  			}
	 255  		}
	 256  		if !found {
	 257  			t.Errorf("got %v; want a record containing %s, %s", txts, tt.txt, tt.host)
	 258  		}
	 259  	}
	 260  }
	 261  
	 262  var lookupGooglePublicDNSAddrTests = []string{
	 263  	"8.8.8.8",
	 264  	"8.8.4.4",
	 265  	"2001:4860:4860::8888",
	 266  	"2001:4860:4860::8844",
	 267  }
	 268  
	 269  func TestLookupGooglePublicDNSAddr(t *testing.T) {
	 270  	mustHaveExternalNetwork(t)
	 271  
	 272  	if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 {
	 273  		t.Skip("both IPv4 and IPv6 are required")
	 274  	}
	 275  
	 276  	defer dnsWaitGroup.Wait()
	 277  
	 278  	for _, ip := range lookupGooglePublicDNSAddrTests {
	 279  		names, err := LookupAddr(ip)
	 280  		if err != nil {
	 281  			t.Fatal(err)
	 282  		}
	 283  		if len(names) == 0 {
	 284  			t.Error("got no record")
	 285  		}
	 286  		for _, name := range names {
	 287  			if !hasSuffixFold(name, ".google.com.") && !hasSuffixFold(name, ".google.") {
	 288  				t.Errorf("got %q; want a record ending in .google.com. or .google.", name)
	 289  			}
	 290  		}
	 291  	}
	 292  }
	 293  
	 294  func TestLookupIPv6LinkLocalAddr(t *testing.T) {
	 295  	if !supportsIPv6() || !*testIPv6 {
	 296  		t.Skip("IPv6 is required")
	 297  	}
	 298  
	 299  	defer dnsWaitGroup.Wait()
	 300  
	 301  	addrs, err := LookupHost("localhost")
	 302  	if err != nil {
	 303  		t.Fatal(err)
	 304  	}
	 305  	found := false
	 306  	for _, addr := range addrs {
	 307  		if addr == "fe80::1%lo0" {
	 308  			found = true
	 309  			break
	 310  		}
	 311  	}
	 312  	if !found {
	 313  		t.Skipf("not supported on %s", runtime.GOOS)
	 314  	}
	 315  	if _, err := LookupAddr("fe80::1%lo0"); err != nil {
	 316  		t.Error(err)
	 317  	}
	 318  }
	 319  
	 320  func TestLookupIPv6LinkLocalAddrWithZone(t *testing.T) {
	 321  	if !supportsIPv6() || !*testIPv6 {
	 322  		t.Skip("IPv6 is required")
	 323  	}
	 324  
	 325  	ipaddrs, err := DefaultResolver.LookupIPAddr(context.Background(), "fe80::1%lo0")
	 326  	if err != nil {
	 327  		t.Error(err)
	 328  	}
	 329  	for _, addr := range ipaddrs {
	 330  		if e, a := "lo0", addr.Zone; e != a {
	 331  			t.Errorf("wrong zone: want %q, got %q", e, a)
	 332  		}
	 333  	}
	 334  
	 335  	addrs, err := DefaultResolver.LookupHost(context.Background(), "fe80::1%lo0")
	 336  	if err != nil {
	 337  		t.Error(err)
	 338  	}
	 339  	for _, addr := range addrs {
	 340  		if e, a := "fe80::1%lo0", addr; e != a {
	 341  			t.Errorf("wrong host: want %q got %q", e, a)
	 342  		}
	 343  	}
	 344  }
	 345  
	 346  var lookupCNAMETests = []struct {
	 347  	name, cname string
	 348  }{
	 349  	{"www.iana.org", "icann.org."},
	 350  	{"www.iana.org.", "icann.org."},
	 351  	{"www.google.com", "google.com."},
	 352  }
	 353  
	 354  func TestLookupCNAME(t *testing.T) {
	 355  	mustHaveExternalNetwork(t)
	 356  
	 357  	if !supportsIPv4() || !*testIPv4 {
	 358  		t.Skip("IPv4 is required")
	 359  	}
	 360  
	 361  	defer dnsWaitGroup.Wait()
	 362  
	 363  	attempts := 0
	 364  	for i := 0; i < len(lookupCNAMETests); i++ {
	 365  		tt := lookupCNAMETests[i]
	 366  		cname, err := LookupCNAME(tt.name)
	 367  		if err != nil {
	 368  			testenv.SkipFlakyNet(t)
	 369  			if attempts < len(backoffDuration) {
	 370  				dur := backoffDuration[attempts]
	 371  				t.Logf("backoff %v after failure %v\n", dur, err)
	 372  				time.Sleep(dur)
	 373  				attempts++
	 374  				i--
	 375  				continue
	 376  			}
	 377  			t.Fatal(err)
	 378  		}
	 379  		if !hasSuffixFold(cname, tt.cname) {
	 380  			t.Errorf("got %s; want a record containing %s", cname, tt.cname)
	 381  		}
	 382  	}
	 383  }
	 384  
	 385  var lookupGoogleHostTests = []struct {
	 386  	name string
	 387  }{
	 388  	{"google.com"},
	 389  	{"google.com."},
	 390  }
	 391  
	 392  func TestLookupGoogleHost(t *testing.T) {
	 393  	mustHaveExternalNetwork(t)
	 394  
	 395  	if !supportsIPv4() || !*testIPv4 {
	 396  		t.Skip("IPv4 is required")
	 397  	}
	 398  
	 399  	defer dnsWaitGroup.Wait()
	 400  
	 401  	for _, tt := range lookupGoogleHostTests {
	 402  		addrs, err := LookupHost(tt.name)
	 403  		if err != nil {
	 404  			t.Fatal(err)
	 405  		}
	 406  		if len(addrs) == 0 {
	 407  			t.Error("got no record")
	 408  		}
	 409  		for _, addr := range addrs {
	 410  			if ParseIP(addr) == nil {
	 411  				t.Errorf("got %q; want a literal IP address", addr)
	 412  			}
	 413  		}
	 414  	}
	 415  }
	 416  
	 417  func TestLookupLongTXT(t *testing.T) {
	 418  	testenv.SkipFlaky(t, 22857)
	 419  	mustHaveExternalNetwork(t)
	 420  
	 421  	defer dnsWaitGroup.Wait()
	 422  
	 423  	txts, err := LookupTXT("golang.rsc.io")
	 424  	if err != nil {
	 425  		t.Fatal(err)
	 426  	}
	 427  	sort.Strings(txts)
	 428  	want := []string{
	 429  		strings.Repeat("abcdefghijklmnopqrstuvwxyABCDEFGHJIKLMNOPQRSTUVWXY", 10),
	 430  		"gophers rule",
	 431  	}
	 432  	if !reflect.DeepEqual(txts, want) {
	 433  		t.Fatalf("LookupTXT golang.rsc.io incorrect\nhave %q\nwant %q", txts, want)
	 434  	}
	 435  }
	 436  
	 437  var lookupGoogleIPTests = []struct {
	 438  	name string
	 439  }{
	 440  	{"google.com"},
	 441  	{"google.com."},
	 442  }
	 443  
	 444  func TestLookupGoogleIP(t *testing.T) {
	 445  	mustHaveExternalNetwork(t)
	 446  
	 447  	if !supportsIPv4() || !*testIPv4 {
	 448  		t.Skip("IPv4 is required")
	 449  	}
	 450  
	 451  	defer dnsWaitGroup.Wait()
	 452  
	 453  	for _, tt := range lookupGoogleIPTests {
	 454  		ips, err := LookupIP(tt.name)
	 455  		if err != nil {
	 456  			t.Fatal(err)
	 457  		}
	 458  		if len(ips) == 0 {
	 459  			t.Error("got no record")
	 460  		}
	 461  		for _, ip := range ips {
	 462  			if ip.To4() == nil && ip.To16() == nil {
	 463  				t.Errorf("got %v; want an IP address", ip)
	 464  			}
	 465  		}
	 466  	}
	 467  }
	 468  
	 469  var revAddrTests = []struct {
	 470  	Addr			string
	 471  	Reverse	 string
	 472  	ErrPrefix string
	 473  }{
	 474  	{"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
	 475  	{"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
	 476  	{"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
	 477  	{"::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.", ""},
	 478  	{"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.", ""},
	 479  	{"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.", ""},
	 480  	{"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.", ""},
	 481  	{"1.2.3", "", "unrecognized address"},
	 482  	{"1.2.3.4.5", "", "unrecognized address"},
	 483  	{"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
	 484  	{"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
	 485  }
	 486  
	 487  func TestReverseAddress(t *testing.T) {
	 488  	defer dnsWaitGroup.Wait()
	 489  	for i, tt := range revAddrTests {
	 490  		a, err := reverseaddr(tt.Addr)
	 491  		if len(tt.ErrPrefix) > 0 && err == nil {
	 492  			t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
	 493  			continue
	 494  		}
	 495  		if len(tt.ErrPrefix) == 0 && err != nil {
	 496  			t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
	 497  		}
	 498  		if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
	 499  			t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
	 500  		}
	 501  		if a != tt.Reverse {
	 502  			t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
	 503  		}
	 504  	}
	 505  }
	 506  
	 507  func TestDNSFlood(t *testing.T) {
	 508  	if !*testDNSFlood {
	 509  		t.Skip("test disabled; use -dnsflood to enable")
	 510  	}
	 511  
	 512  	defer dnsWaitGroup.Wait()
	 513  
	 514  	var N = 5000
	 515  	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
	 516  		// On Darwin this test consumes kernel threads much
	 517  		// than other platforms for some reason.
	 518  		// When we monitor the number of allocated Ms by
	 519  		// observing on runtime.newm calls, we can see that it
	 520  		// easily reaches the per process ceiling
	 521  		// kern.num_threads when CGO_ENABLED=1 and
	 522  		// GODEBUG=netdns=go.
	 523  		N = 500
	 524  	}
	 525  
	 526  	const timeout = 3 * time.Second
	 527  	ctxHalfTimeout, cancel := context.WithTimeout(context.Background(), timeout/2)
	 528  	defer cancel()
	 529  	ctxTimeout, cancel := context.WithTimeout(context.Background(), timeout)
	 530  	defer cancel()
	 531  
	 532  	c := make(chan error, 2*N)
	 533  	for i := 0; i < N; i++ {
	 534  		name := fmt.Sprintf("%d.net-test.golang.org", i)
	 535  		go func() {
	 536  			_, err := DefaultResolver.LookupIPAddr(ctxHalfTimeout, name)
	 537  			c <- err
	 538  		}()
	 539  		go func() {
	 540  			_, err := DefaultResolver.LookupIPAddr(ctxTimeout, name)
	 541  			c <- err
	 542  		}()
	 543  	}
	 544  	qstats := struct {
	 545  		succeeded, failed				 int
	 546  		timeout, temporary, other int
	 547  		unknown									 int
	 548  	}{}
	 549  	deadline := time.After(timeout + time.Second)
	 550  	for i := 0; i < 2*N; i++ {
	 551  		select {
	 552  		case <-deadline:
	 553  			t.Fatal("deadline exceeded")
	 554  		case err := <-c:
	 555  			switch err := err.(type) {
	 556  			case nil:
	 557  				qstats.succeeded++
	 558  			case Error:
	 559  				qstats.failed++
	 560  				if err.Timeout() {
	 561  					qstats.timeout++
	 562  				}
	 563  				if err.Temporary() {
	 564  					qstats.temporary++
	 565  				}
	 566  				if !err.Timeout() && !err.Temporary() {
	 567  					qstats.other++
	 568  				}
	 569  			default:
	 570  				qstats.failed++
	 571  				qstats.unknown++
	 572  			}
	 573  		}
	 574  	}
	 575  
	 576  	// A high volume of DNS queries for sub-domain of golang.org
	 577  	// would be coordinated by authoritative or recursive server,
	 578  	// or stub resolver which implements query-response rate
	 579  	// limitation, so we can expect some query successes and more
	 580  	// failures including timeout, temporary and other here.
	 581  	// As a rule, unknown must not be shown but it might possibly
	 582  	// happen due to issue 4856 for now.
	 583  	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)
	 584  }
	 585  
	 586  func TestLookupDotsWithLocalSource(t *testing.T) {
	 587  	if !supportsIPv4() || !*testIPv4 {
	 588  		t.Skip("IPv4 is required")
	 589  	}
	 590  
	 591  	mustHaveExternalNetwork(t)
	 592  
	 593  	defer dnsWaitGroup.Wait()
	 594  
	 595  	for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
	 596  		fixup := fn()
	 597  		if fixup == nil {
	 598  			continue
	 599  		}
	 600  		names, err := LookupAddr("127.0.0.1")
	 601  		fixup()
	 602  		if err != nil {
	 603  			t.Logf("#%d: %v", i, err)
	 604  			continue
	 605  		}
	 606  		mode := "netgo"
	 607  		if i == 1 {
	 608  			mode = "netcgo"
	 609  		}
	 610  	loop:
	 611  		for i, name := range names {
	 612  			if strings.Index(name, ".") == len(name)-1 { // "localhost" not "localhost."
	 613  				for j := range names {
	 614  					if j == i {
	 615  						continue
	 616  					}
	 617  					if names[j] == name[:len(name)-1] {
	 618  						// It's OK if we find the name without the dot,
	 619  						// as some systems say 127.0.0.1 localhost localhost.
	 620  						continue loop
	 621  					}
	 622  				}
	 623  				t.Errorf("%s: got %s; want %s", mode, name, name[:len(name)-1])
	 624  			} else if strings.Contains(name, ".") && !strings.HasSuffix(name, ".") { // "localhost.localdomain." not "localhost.localdomain"
	 625  				t.Errorf("%s: got %s; want name ending with trailing dot", mode, name)
	 626  			}
	 627  		}
	 628  	}
	 629  }
	 630  
	 631  func TestLookupDotsWithRemoteSource(t *testing.T) {
	 632  	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
	 633  		testenv.SkipFlaky(t, 27992)
	 634  	}
	 635  	mustHaveExternalNetwork(t)
	 636  
	 637  	if !supportsIPv4() || !*testIPv4 {
	 638  		t.Skip("IPv4 is required")
	 639  	}
	 640  
	 641  	if iOS() {
	 642  		t.Skip("no resolv.conf on iOS")
	 643  	}
	 644  
	 645  	defer dnsWaitGroup.Wait()
	 646  
	 647  	if fixup := forceGoDNS(); fixup != nil {
	 648  		testDots(t, "go")
	 649  		fixup()
	 650  	}
	 651  	if fixup := forceCgoDNS(); fixup != nil {
	 652  		testDots(t, "cgo")
	 653  		fixup()
	 654  	}
	 655  }
	 656  
	 657  func testDots(t *testing.T, mode string) {
	 658  	names, err := LookupAddr("8.8.8.8") // Google dns server
	 659  	if err != nil {
	 660  		testenv.SkipFlakyNet(t)
	 661  		t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
	 662  	} else {
	 663  		for _, name := range names {
	 664  			if !hasSuffixFold(name, ".google.com.") && !hasSuffixFold(name, ".google.") {
	 665  				t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com or .google with trailing dot (mode=%v)", names, mode)
	 666  				break
	 667  			}
	 668  		}
	 669  	}
	 670  
	 671  	cname, err := LookupCNAME("www.mit.edu")
	 672  	if err != nil {
	 673  		testenv.SkipFlakyNet(t)
	 674  		t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
	 675  	} else if !strings.HasSuffix(cname, ".") {
	 676  		t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
	 677  	}
	 678  
	 679  	mxs, err := LookupMX("google.com")
	 680  	if err != nil {
	 681  		testenv.SkipFlakyNet(t)
	 682  		t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
	 683  	} else {
	 684  		for _, mx := range mxs {
	 685  			if !hasSuffixFold(mx.Host, ".google.com.") {
	 686  				t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
	 687  				break
	 688  			}
	 689  		}
	 690  	}
	 691  
	 692  	nss, err := LookupNS("google.com")
	 693  	if err != nil {
	 694  		testenv.SkipFlakyNet(t)
	 695  		t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
	 696  	} else {
	 697  		for _, ns := range nss {
	 698  			if !hasSuffixFold(ns.Host, ".google.com.") {
	 699  				t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
	 700  				break
	 701  			}
	 702  		}
	 703  	}
	 704  
	 705  	cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
	 706  	if err != nil {
	 707  		testenv.SkipFlakyNet(t)
	 708  		t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
	 709  	} else {
	 710  		if !hasSuffixFold(cname, ".google.com.") {
	 711  			t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
	 712  		}
	 713  		for _, srv := range srvs {
	 714  			if !hasSuffixFold(srv.Target, ".google.com.") {
	 715  				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)
	 716  				break
	 717  			}
	 718  		}
	 719  	}
	 720  }
	 721  
	 722  func mxString(mxs []*MX) string {
	 723  	var buf bytes.Buffer
	 724  	sep := ""
	 725  	fmt.Fprintf(&buf, "[")
	 726  	for _, mx := range mxs {
	 727  		fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
	 728  		sep = " "
	 729  	}
	 730  	fmt.Fprintf(&buf, "]")
	 731  	return buf.String()
	 732  }
	 733  
	 734  func nsString(nss []*NS) string {
	 735  	var buf bytes.Buffer
	 736  	sep := ""
	 737  	fmt.Fprintf(&buf, "[")
	 738  	for _, ns := range nss {
	 739  		fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
	 740  		sep = " "
	 741  	}
	 742  	fmt.Fprintf(&buf, "]")
	 743  	return buf.String()
	 744  }
	 745  
	 746  func srvString(srvs []*SRV) string {
	 747  	var buf bytes.Buffer
	 748  	sep := ""
	 749  	fmt.Fprintf(&buf, "[")
	 750  	for _, srv := range srvs {
	 751  		fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
	 752  		sep = " "
	 753  	}
	 754  	fmt.Fprintf(&buf, "]")
	 755  	return buf.String()
	 756  }
	 757  
	 758  func TestLookupPort(t *testing.T) {
	 759  	// See https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
	 760  	//
	 761  	// Please be careful about adding new test cases.
	 762  	// There are platforms which have incomplete mappings for
	 763  	// restricted resource access and security reasons.
	 764  	type test struct {
	 765  		network string
	 766  		name		string
	 767  		port		int
	 768  		ok			bool
	 769  	}
	 770  	var tests = []test{
	 771  		{"tcp", "0", 0, true},
	 772  		{"udp", "0", 0, true},
	 773  		{"udp", "domain", 53, true},
	 774  
	 775  		{"--badnet--", "zzz", 0, false},
	 776  		{"tcp", "--badport--", 0, false},
	 777  		{"tcp", "-1", 0, false},
	 778  		{"tcp", "65536", 0, false},
	 779  		{"udp", "-1", 0, false},
	 780  		{"udp", "65536", 0, false},
	 781  		{"tcp", "123456789", 0, false},
	 782  
	 783  		// Issue 13610: LookupPort("tcp", "")
	 784  		{"tcp", "", 0, true},
	 785  		{"tcp4", "", 0, true},
	 786  		{"tcp6", "", 0, true},
	 787  		{"udp", "", 0, true},
	 788  		{"udp4", "", 0, true},
	 789  		{"udp6", "", 0, true},
	 790  	}
	 791  
	 792  	switch runtime.GOOS {
	 793  	case "android":
	 794  		if netGo {
	 795  			t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
	 796  		}
	 797  	default:
	 798  		tests = append(tests, test{"tcp", "http", 80, true})
	 799  	}
	 800  
	 801  	for _, tt := range tests {
	 802  		port, err := LookupPort(tt.network, tt.name)
	 803  		if port != tt.port || (err == nil) != tt.ok {
	 804  			t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=%t", tt.network, tt.name, port, err, tt.port, !tt.ok)
	 805  		}
	 806  		if err != nil {
	 807  			if perr := parseLookupPortError(err); perr != nil {
	 808  				t.Error(perr)
	 809  			}
	 810  		}
	 811  	}
	 812  }
	 813  
	 814  // Like TestLookupPort but with minimal tests that should always pass
	 815  // because the answers are baked-in to the net package.
	 816  func TestLookupPort_Minimal(t *testing.T) {
	 817  	type test struct {
	 818  		network string
	 819  		name		string
	 820  		port		int
	 821  	}
	 822  	var tests = []test{
	 823  		{"tcp", "http", 80},
	 824  		{"tcp", "HTTP", 80}, // case shouldn't matter
	 825  		{"tcp", "https", 443},
	 826  		{"tcp", "ssh", 22},
	 827  		{"tcp", "gopher", 70},
	 828  		{"tcp4", "http", 80},
	 829  		{"tcp6", "http", 80},
	 830  	}
	 831  
	 832  	for _, tt := range tests {
	 833  		port, err := LookupPort(tt.network, tt.name)
	 834  		if port != tt.port || err != nil {
	 835  			t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=nil", tt.network, tt.name, port, err, tt.port)
	 836  		}
	 837  	}
	 838  }
	 839  
	 840  func TestLookupProtocol_Minimal(t *testing.T) {
	 841  	type test struct {
	 842  		name string
	 843  		want int
	 844  	}
	 845  	var tests = []test{
	 846  		{"tcp", 6},
	 847  		{"TcP", 6}, // case shouldn't matter
	 848  		{"icmp", 1},
	 849  		{"igmp", 2},
	 850  		{"udp", 17},
	 851  		{"ipv6-icmp", 58},
	 852  	}
	 853  
	 854  	for _, tt := range tests {
	 855  		got, err := lookupProtocol(context.Background(), tt.name)
	 856  		if got != tt.want || err != nil {
	 857  			t.Errorf("LookupProtocol(%q) = %d, %v; want %d, error=nil", tt.name, got, err, tt.want)
	 858  		}
	 859  	}
	 860  
	 861  }
	 862  
	 863  func TestLookupNonLDH(t *testing.T) {
	 864  	defer dnsWaitGroup.Wait()
	 865  
	 866  	if fixup := forceGoDNS(); fixup != nil {
	 867  		defer fixup()
	 868  	}
	 869  
	 870  	// "LDH" stands for letters, digits, and hyphens and is the usual
	 871  	// description of standard DNS names.
	 872  	// This test is checking that other kinds of names are reported
	 873  	// as not found, not reported as invalid names.
	 874  	addrs, err := LookupHost("!!!.###.bogus..domain.")
	 875  	if err == nil {
	 876  		t.Fatalf("lookup succeeded: %v", addrs)
	 877  	}
	 878  	if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) {
	 879  		t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost)
	 880  	}
	 881  	if !err.(*DNSError).IsNotFound {
	 882  		t.Fatalf("lookup error = %v, want true", err.(*DNSError).IsNotFound)
	 883  	}
	 884  }
	 885  
	 886  func TestLookupContextCancel(t *testing.T) {
	 887  	mustHaveExternalNetwork(t)
	 888  	defer dnsWaitGroup.Wait()
	 889  
	 890  	ctx, ctxCancel := context.WithCancel(context.Background())
	 891  	ctxCancel()
	 892  	_, err := DefaultResolver.LookupIPAddr(ctx, "google.com")
	 893  	if err != errCanceled {
	 894  		testenv.SkipFlakyNet(t)
	 895  		t.Fatal(err)
	 896  	}
	 897  	ctx = context.Background()
	 898  	_, err = DefaultResolver.LookupIPAddr(ctx, "google.com")
	 899  	if err != nil {
	 900  		testenv.SkipFlakyNet(t)
	 901  		t.Fatal(err)
	 902  	}
	 903  }
	 904  
	 905  // Issue 24330: treat the nil *Resolver like a zero value. Verify nothing
	 906  // crashes if nil is used.
	 907  func TestNilResolverLookup(t *testing.T) {
	 908  	mustHaveExternalNetwork(t)
	 909  	var r *Resolver = nil
	 910  	ctx := context.Background()
	 911  
	 912  	// Don't care about the results, just that nothing panics:
	 913  	r.LookupAddr(ctx, "8.8.8.8")
	 914  	r.LookupCNAME(ctx, "google.com")
	 915  	r.LookupHost(ctx, "google.com")
	 916  	r.LookupIPAddr(ctx, "google.com")
	 917  	r.LookupIP(ctx, "ip", "google.com")
	 918  	r.LookupMX(ctx, "gmail.com")
	 919  	r.LookupNS(ctx, "google.com")
	 920  	r.LookupPort(ctx, "tcp", "smtp")
	 921  	r.LookupSRV(ctx, "service", "proto", "name")
	 922  	r.LookupTXT(ctx, "gmail.com")
	 923  }
	 924  
	 925  // TestLookupHostCancel verifies that lookup works even after many
	 926  // canceled lookups (see golang.org/issue/24178 for details).
	 927  func TestLookupHostCancel(t *testing.T) {
	 928  	mustHaveExternalNetwork(t)
	 929  	const (
	 930  		google				= "www.google.com"
	 931  		invalidDomain = "invalid.invalid" // RFC 2606 reserves .invalid
	 932  		n						 = 600							 // this needs to be larger than threadLimit size
	 933  	)
	 934  
	 935  	_, err := LookupHost(google)
	 936  	if err != nil {
	 937  		t.Fatal(err)
	 938  	}
	 939  
	 940  	ctx, cancel := context.WithCancel(context.Background())
	 941  	cancel()
	 942  	for i := 0; i < n; i++ {
	 943  		addr, err := DefaultResolver.LookupHost(ctx, invalidDomain)
	 944  		if err == nil {
	 945  			t.Fatalf("LookupHost(%q): returns %v, but should fail", invalidDomain, addr)
	 946  		}
	 947  		if !strings.Contains(err.Error(), "canceled") {
	 948  			t.Fatalf("LookupHost(%q): failed with unexpected error: %v", invalidDomain, err)
	 949  		}
	 950  		time.Sleep(time.Millisecond * 1)
	 951  	}
	 952  
	 953  	_, err = LookupHost(google)
	 954  	if err != nil {
	 955  		t.Fatal(err)
	 956  	}
	 957  }
	 958  
	 959  type lookupCustomResolver struct {
	 960  	*Resolver
	 961  	mu		 sync.RWMutex
	 962  	dialed bool
	 963  }
	 964  
	 965  func (lcr *lookupCustomResolver) dial() func(ctx context.Context, network, address string) (Conn, error) {
	 966  	return func(ctx context.Context, network, address string) (Conn, error) {
	 967  		lcr.mu.Lock()
	 968  		lcr.dialed = true
	 969  		lcr.mu.Unlock()
	 970  		return Dial(network, address)
	 971  	}
	 972  }
	 973  
	 974  // TestConcurrentPreferGoResolversDial tests that multiple resolvers with the
	 975  // PreferGo option used concurrently are all dialed properly.
	 976  func TestConcurrentPreferGoResolversDial(t *testing.T) {
	 977  	// The windows and plan9 implementation of the resolver does not use
	 978  	// the Dial function.
	 979  	switch runtime.GOOS {
	 980  	case "windows", "plan9":
	 981  		t.Skipf("skip on %v", runtime.GOOS)
	 982  	}
	 983  
	 984  	testenv.MustHaveExternalNetwork(t)
	 985  	testenv.SkipFlakyNet(t)
	 986  
	 987  	defer dnsWaitGroup.Wait()
	 988  
	 989  	resolvers := make([]*lookupCustomResolver, 2)
	 990  	for i := range resolvers {
	 991  		cs := lookupCustomResolver{Resolver: &Resolver{PreferGo: true}}
	 992  		cs.Dial = cs.dial()
	 993  		resolvers[i] = &cs
	 994  	}
	 995  
	 996  	var wg sync.WaitGroup
	 997  	wg.Add(len(resolvers))
	 998  	for i, resolver := range resolvers {
	 999  		go func(r *Resolver, index int) {
	1000  			defer wg.Done()
	1001  			_, err := r.LookupIPAddr(context.Background(), "google.com")
	1002  			if err != nil {
	1003  				t.Errorf("lookup failed for resolver %d: %q", index, err)
	1004  			}
	1005  		}(resolver.Resolver, i)
	1006  	}
	1007  	wg.Wait()
	1008  
	1009  	if t.Failed() {
	1010  		t.FailNow()
	1011  	}
	1012  
	1013  	for i, resolver := range resolvers {
	1014  		if !resolver.dialed {
	1015  			t.Errorf("custom resolver %d not dialed during lookup", i)
	1016  		}
	1017  	}
	1018  }
	1019  
	1020  var ipVersionTests = []struct {
	1021  	network string
	1022  	version byte
	1023  }{
	1024  	{"tcp", 0},
	1025  	{"tcp4", '4'},
	1026  	{"tcp6", '6'},
	1027  	{"udp", 0},
	1028  	{"udp4", '4'},
	1029  	{"udp6", '6'},
	1030  	{"ip", 0},
	1031  	{"ip4", '4'},
	1032  	{"ip6", '6'},
	1033  	{"ip7", 0},
	1034  	{"", 0},
	1035  }
	1036  
	1037  func TestIPVersion(t *testing.T) {
	1038  	for _, tt := range ipVersionTests {
	1039  		if version := ipVersion(tt.network); version != tt.version {
	1040  			t.Errorf("Family for: %s. Expected: %s, Got: %s", tt.network,
	1041  				string(tt.version), string(version))
	1042  		}
	1043  	}
	1044  }
	1045  
	1046  // Issue 28600: The context that is used to lookup ips should always
	1047  // preserve the values from the context that was passed into LookupIPAddr.
	1048  func TestLookupIPAddrPreservesContextValues(t *testing.T) {
	1049  	origTestHookLookupIP := testHookLookupIP
	1050  	defer func() { testHookLookupIP = origTestHookLookupIP }()
	1051  
	1052  	keyValues := []struct {
	1053  		key, value interface{}
	1054  	}{
	1055  		{"key-1", 12},
	1056  		{384, "value2"},
	1057  		{new(float64), 137},
	1058  	}
	1059  	ctx := context.Background()
	1060  	for _, kv := range keyValues {
	1061  		ctx = context.WithValue(ctx, kv.key, kv.value)
	1062  	}
	1063  
	1064  	wantIPs := []IPAddr{
	1065  		{IP: IPv4(127, 0, 0, 1)},
	1066  		{IP: IPv6loopback},
	1067  	}
	1068  
	1069  	checkCtxValues := func(ctx_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
	1070  		for _, kv := range keyValues {
	1071  			g, w := ctx_.Value(kv.key), kv.value
	1072  			if !reflect.DeepEqual(g, w) {
	1073  				t.Errorf("Value lookup:\n\tGot:	%v\n\tWant: %v", g, w)
	1074  			}
	1075  		}
	1076  		return wantIPs, nil
	1077  	}
	1078  	testHookLookupIP = checkCtxValues
	1079  
	1080  	resolvers := []*Resolver{
	1081  		nil,
	1082  		new(Resolver),
	1083  	}
	1084  
	1085  	for i, resolver := range resolvers {
	1086  		gotIPs, err := resolver.LookupIPAddr(ctx, "golang.org")
	1087  		if err != nil {
	1088  			t.Errorf("Resolver #%d: unexpected error: %v", i, err)
	1089  		}
	1090  		if !reflect.DeepEqual(gotIPs, wantIPs) {
	1091  			t.Errorf("#%d: mismatched IPAddr results\n\tGot: %v\n\tWant: %v", i, gotIPs, wantIPs)
	1092  		}
	1093  	}
	1094  }
	1095  
	1096  // Issue 30521: The lookup group should call the resolver for each network.
	1097  func TestLookupIPAddrConcurrentCallsForNetworks(t *testing.T) {
	1098  	origTestHookLookupIP := testHookLookupIP
	1099  	defer func() { testHookLookupIP = origTestHookLookupIP }()
	1100  
	1101  	queries := [][]string{
	1102  		{"udp", "golang.org"},
	1103  		{"udp4", "golang.org"},
	1104  		{"udp6", "golang.org"},
	1105  		{"udp", "golang.org"},
	1106  		{"udp", "golang.org"},
	1107  	}
	1108  	results := map[[2]string][]IPAddr{
	1109  		{"udp", "golang.org"}: {
	1110  			{IP: IPv4(127, 0, 0, 1)},
	1111  			{IP: IPv6loopback},
	1112  		},
	1113  		{"udp4", "golang.org"}: {
	1114  			{IP: IPv4(127, 0, 0, 1)},
	1115  		},
	1116  		{"udp6", "golang.org"}: {
	1117  			{IP: IPv6loopback},
	1118  		},
	1119  	}
	1120  	calls := int32(0)
	1121  	waitCh := make(chan struct{})
	1122  	testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
	1123  		// We'll block until this is called one time for each different
	1124  		// expected result. This will ensure that the lookup group would wait
	1125  		// for the existing call if it was to be reused.
	1126  		if atomic.AddInt32(&calls, 1) == int32(len(results)) {
	1127  			close(waitCh)
	1128  		}
	1129  		select {
	1130  		case <-waitCh:
	1131  		case <-ctx.Done():
	1132  			return nil, ctx.Err()
	1133  		}
	1134  		return results[[2]string{network, host}], nil
	1135  	}
	1136  
	1137  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	1138  	defer cancel()
	1139  	wg := sync.WaitGroup{}
	1140  	for _, q := range queries {
	1141  		network := q[0]
	1142  		host := q[1]
	1143  		wg.Add(1)
	1144  		go func() {
	1145  			defer wg.Done()
	1146  			gotIPs, err := DefaultResolver.lookupIPAddr(ctx, network, host)
	1147  			if err != nil {
	1148  				t.Errorf("lookupIPAddr(%v, %v): unexpected error: %v", network, host, err)
	1149  			}
	1150  			wantIPs := results[[2]string{network, host}]
	1151  			if !reflect.DeepEqual(gotIPs, wantIPs) {
	1152  				t.Errorf("lookupIPAddr(%v, %v): mismatched IPAddr results\n\tGot: %v\n\tWant: %v", network, host, gotIPs, wantIPs)
	1153  			}
	1154  		}()
	1155  	}
	1156  	wg.Wait()
	1157  }
	1158  
	1159  func TestWithUnexpiredValuesPreserved(t *testing.T) {
	1160  	ctx, cancel := context.WithCancel(context.Background())
	1161  
	1162  	// Insert a value into it.
	1163  	key, value := "key-1", 2
	1164  	ctx = context.WithValue(ctx, key, value)
	1165  
	1166  	// Now use the "values preserving context" like
	1167  	// we would for LookupIPAddr. See Issue 28600.
	1168  	ctx = withUnexpiredValuesPreserved(ctx)
	1169  
	1170  	// Lookup before expiry.
	1171  	if g, w := ctx.Value(key), value; g != w {
	1172  		t.Errorf("Lookup before expiry: Got %v Want %v", g, w)
	1173  	}
	1174  
	1175  	// Cancel the context.
	1176  	cancel()
	1177  
	1178  	// Lookup after expiry should return nil
	1179  	if g := ctx.Value(key); g != nil {
	1180  		t.Errorf("Lookup after expiry: Got %v want nil", g)
	1181  	}
	1182  }
	1183  
	1184  // Issue 31597: don't panic on null byte in name
	1185  func TestLookupNullByte(t *testing.T) {
	1186  	testenv.MustHaveExternalNetwork(t)
	1187  	testenv.SkipFlakyNet(t)
	1188  	LookupHost("foo\x00bar") // check that it doesn't panic; it used to on Windows
	1189  }
	1190  
	1191  func TestResolverLookupIP(t *testing.T) {
	1192  	testenv.MustHaveExternalNetwork(t)
	1193  
	1194  	v4Ok := supportsIPv4() && *testIPv4
	1195  	v6Ok := supportsIPv6() && *testIPv6
	1196  
	1197  	defer dnsWaitGroup.Wait()
	1198  
	1199  	for _, impl := range []struct {
	1200  		name string
	1201  		fn	 func() func()
	1202  	}{
	1203  		{"go", forceGoDNS},
	1204  		{"cgo", forceCgoDNS},
	1205  	} {
	1206  		t.Run("implementation: "+impl.name, func(t *testing.T) {
	1207  			fixup := impl.fn()
	1208  			if fixup == nil {
	1209  				t.Skip("not supported")
	1210  			}
	1211  			defer fixup()
	1212  
	1213  			for _, network := range []string{"ip", "ip4", "ip6"} {
	1214  				t.Run("network: "+network, func(t *testing.T) {
	1215  					switch {
	1216  					case network == "ip4" && !v4Ok:
	1217  						t.Skip("IPv4 is not supported")
	1218  					case network == "ip6" && !v6Ok:
	1219  						t.Skip("IPv6 is not supported")
	1220  					}
	1221  
	1222  					// google.com has both A and AAAA records.
	1223  					const host = "google.com"
	1224  					ips, err := DefaultResolver.LookupIP(context.Background(), network, host)
	1225  					if err != nil {
	1226  						testenv.SkipFlakyNet(t)
	1227  						t.Fatalf("DefaultResolver.LookupIP(%q, %q): failed with unexpected error: %v", network, host, err)
	1228  					}
	1229  
	1230  					var v4Addrs []IP
	1231  					var v6Addrs []IP
	1232  					for _, ip := range ips {
	1233  						switch {
	1234  						case ip.To4() != nil:
	1235  							// We need to skip the test below because To16 will
	1236  							// convent an IPv4 address to an IPv4-mapped IPv6
	1237  							// address.
	1238  							v4Addrs = append(v4Addrs, ip)
	1239  						case ip.To16() != nil:
	1240  							v6Addrs = append(v6Addrs, ip)
	1241  						default:
	1242  							t.Fatalf("IP=%q is neither IPv4 nor IPv6", ip)
	1243  						}
	1244  					}
	1245  
	1246  					// Check that we got the expected addresses.
	1247  					if network == "ip4" || network == "ip" && v4Ok {
	1248  						if len(v4Addrs) == 0 {
	1249  							t.Errorf("DefaultResolver.LookupIP(%q, %q): no IPv4 addresses", network, host)
	1250  						}
	1251  					}
	1252  					if network == "ip6" || network == "ip" && v6Ok {
	1253  						if len(v6Addrs) == 0 {
	1254  							t.Errorf("DefaultResolver.LookupIP(%q, %q): no IPv6 addresses", network, host)
	1255  						}
	1256  					}
	1257  
	1258  					// Check that we didn't get any unexpected addresses.
	1259  					if network == "ip6" && len(v4Addrs) > 0 {
	1260  						t.Errorf("DefaultResolver.LookupIP(%q, %q): unexpected IPv4 addresses: %v", network, host, v4Addrs)
	1261  					}
	1262  					if network == "ip4" && len(v6Addrs) > 0 {
	1263  						t.Errorf("DefaultResolver.LookupIP(%q, %q): unexpected IPv6 addresses: %v", network, host, v6Addrs)
	1264  					}
	1265  				})
	1266  			}
	1267  		})
	1268  	}
	1269  }
	1270  

View as plain text