libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / lookup_test.go
blob5c66dfa2603ad902c3b0a608277dd817a76d974f
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.
5 // +build !js
7 package net
9 import (
10 "bytes"
11 "context"
12 "fmt"
13 "internal/testenv"
14 "reflect"
15 "runtime"
16 "sort"
17 "strings"
18 "sync"
19 "testing"
20 "time"
23 func lookupLocalhost(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
24 switch host {
25 case "localhost":
26 return []IPAddr{
27 {IP: IPv4(127, 0, 0, 1)},
28 {IP: IPv6loopback},
29 }, nil
30 default:
31 return fn(ctx, host)
35 // The Lookup APIs use various sources such as local database, DNS or
36 // mDNS, and may use platform-dependent DNS stub resolver if possible.
37 // The APIs accept any of forms for a query; host name in various
38 // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
39 // FQDN, but the result would be one of the forms and it depends on
40 // the circumstances.
42 var lookupGoogleSRVTests = []struct {
43 service, proto, name string
44 cname, target string
47 "xmpp-server", "tcp", "google.com",
48 "google.com.", "google.com.",
51 "xmpp-server", "tcp", "google.com.",
52 "google.com.", "google.com.",
55 // non-standard back door
57 "", "", "_xmpp-server._tcp.google.com",
58 "google.com.", "google.com.",
61 "", "", "_xmpp-server._tcp.google.com.",
62 "google.com.", "google.com.",
66 var backoffDuration = [...]time.Duration{time.Second, 5 * time.Second, 30 * time.Second}
68 func TestLookupGoogleSRV(t *testing.T) {
69 t.Parallel()
70 mustHaveExternalNetwork(t)
72 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
73 t.Skip("no resolv.conf on iOS")
76 if !supportsIPv4() || !*testIPv4 {
77 t.Skip("IPv4 is required")
80 attempts := 0
81 for i := 0; i < len(lookupGoogleSRVTests); i++ {
82 tt := lookupGoogleSRVTests[i]
83 cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
84 if err != nil {
85 testenv.SkipFlakyNet(t)
86 if attempts < len(backoffDuration) {
87 dur := backoffDuration[attempts]
88 t.Logf("backoff %v after failure %v\n", dur, err)
89 time.Sleep(dur)
90 attempts++
91 i--
92 continue
94 t.Fatal(err)
96 if len(srvs) == 0 {
97 t.Error("got no record")
99 if !strings.HasSuffix(cname, tt.cname) {
100 t.Errorf("got %s; want %s", cname, tt.cname)
102 for _, srv := range srvs {
103 if !strings.HasSuffix(srv.Target, tt.target) {
104 t.Errorf("got %v; want a record containing %s", srv, tt.target)
110 var lookupGmailMXTests = []struct {
111 name, host string
113 {"gmail.com", "google.com."},
114 {"gmail.com.", "google.com."},
117 func TestLookupGmailMX(t *testing.T) {
118 t.Parallel()
119 mustHaveExternalNetwork(t)
121 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
122 t.Skip("no resolv.conf on iOS")
125 if !supportsIPv4() || !*testIPv4 {
126 t.Skip("IPv4 is required")
129 attempts := 0
130 for i := 0; i < len(lookupGmailMXTests); i++ {
131 tt := lookupGmailMXTests[i]
132 mxs, err := LookupMX(tt.name)
133 if err != nil {
134 testenv.SkipFlakyNet(t)
135 if attempts < len(backoffDuration) {
136 dur := backoffDuration[attempts]
137 t.Logf("backoff %v after failure %v\n", dur, err)
138 time.Sleep(dur)
139 attempts++
141 continue
143 t.Fatal(err)
145 if len(mxs) == 0 {
146 t.Error("got no record")
148 for _, mx := range mxs {
149 if !strings.HasSuffix(mx.Host, tt.host) {
150 t.Errorf("got %v; want a record containing %s", mx, tt.host)
156 var lookupGmailNSTests = []struct {
157 name, host string
159 {"gmail.com", "google.com."},
160 {"gmail.com.", "google.com."},
163 func TestLookupGmailNS(t *testing.T) {
164 t.Parallel()
165 mustHaveExternalNetwork(t)
167 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
168 t.Skip("no resolv.conf on iOS")
171 if !supportsIPv4() || !*testIPv4 {
172 t.Skip("IPv4 is required")
175 attempts := 0
176 for i := 0; i < len(lookupGmailNSTests); i++ {
177 tt := lookupGmailNSTests[i]
178 nss, err := LookupNS(tt.name)
179 if err != nil {
180 testenv.SkipFlakyNet(t)
181 if attempts < len(backoffDuration) {
182 dur := backoffDuration[attempts]
183 t.Logf("backoff %v after failure %v\n", dur, err)
184 time.Sleep(dur)
185 attempts++
187 continue
189 t.Fatal(err)
191 if len(nss) == 0 {
192 t.Error("got no record")
194 for _, ns := range nss {
195 if !strings.HasSuffix(ns.Host, tt.host) {
196 t.Errorf("got %v; want a record containing %s", ns, tt.host)
202 var lookupGmailTXTTests = []struct {
203 name, txt, host string
205 {"gmail.com", "spf", "google.com"},
206 {"gmail.com.", "spf", "google.com"},
209 func TestLookupGmailTXT(t *testing.T) {
210 t.Parallel()
211 mustHaveExternalNetwork(t)
213 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
214 t.Skip("no resolv.conf on iOS")
217 if !supportsIPv4() || !*testIPv4 {
218 t.Skip("IPv4 is required")
221 attempts := 0
222 for i := 0; i < len(lookupGmailTXTTests); i++ {
223 tt := lookupGmailTXTTests[i]
224 txts, err := LookupTXT(tt.name)
225 if err != nil {
226 testenv.SkipFlakyNet(t)
227 if attempts < len(backoffDuration) {
228 dur := backoffDuration[attempts]
229 t.Logf("backoff %v after failure %v\n", dur, err)
230 time.Sleep(dur)
231 attempts++
233 continue
235 t.Fatal(err)
237 if len(txts) == 0 {
238 t.Error("got no record")
240 for _, txt := range txts {
241 if !strings.Contains(txt, tt.txt) || (!strings.HasSuffix(txt, tt.host) && !strings.HasSuffix(txt, tt.host+".")) {
242 t.Errorf("got %s; want a record containing %s, %s", txt, tt.txt, tt.host)
248 var lookupGooglePublicDNSAddrTests = []struct {
249 addr, name string
251 {"8.8.8.8", ".google.com."},
252 {"8.8.4.4", ".google.com."},
254 {"2001:4860:4860::8888", ".google.com."},
255 {"2001:4860:4860::8844", ".google.com."},
258 func TestLookupGooglePublicDNSAddr(t *testing.T) {
259 mustHaveExternalNetwork(t)
261 if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 {
262 t.Skip("both IPv4 and IPv6 are required")
265 defer dnsWaitGroup.Wait()
267 for _, tt := range lookupGooglePublicDNSAddrTests {
268 names, err := LookupAddr(tt.addr)
269 if err != nil {
270 t.Fatal(err)
272 if len(names) == 0 {
273 t.Error("got no record")
275 for _, name := range names {
276 if !strings.HasSuffix(name, tt.name) {
277 t.Errorf("got %s; want a record containing %s", name, tt.name)
283 func TestLookupIPv6LinkLocalAddr(t *testing.T) {
284 if !supportsIPv6() || !*testIPv6 {
285 t.Skip("IPv6 is required")
288 defer dnsWaitGroup.Wait()
290 addrs, err := LookupHost("localhost")
291 if err != nil {
292 t.Fatal(err)
294 found := false
295 for _, addr := range addrs {
296 if addr == "fe80::1%lo0" {
297 found = true
298 break
301 if !found {
302 t.Skipf("not supported on %s", runtime.GOOS)
304 if _, err := LookupAddr("fe80::1%lo0"); err != nil {
305 t.Error(err)
309 func TestLookupIPv6LinkLocalAddrWithZone(t *testing.T) {
310 if !supportsIPv6() || !*testIPv6 {
311 t.Skip("IPv6 is required")
314 ipaddrs, err := DefaultResolver.LookupIPAddr(context.Background(), "fe80::1%lo0")
315 if err != nil {
316 t.Error(err)
318 for _, addr := range ipaddrs {
319 if e, a := "lo0", addr.Zone; e != a {
320 t.Errorf("wrong zone: want %q, got %q", e, a)
324 addrs, err := DefaultResolver.LookupHost(context.Background(), "fe80::1%lo0")
325 if err != nil {
326 t.Error(err)
328 for _, addr := range addrs {
329 if e, a := "fe80::1%lo0", addr; e != a {
330 t.Errorf("wrong host: want %q got %q", e, a)
335 var lookupCNAMETests = []struct {
336 name, cname string
338 {"www.iana.org", "icann.org."},
339 {"www.iana.org.", "icann.org."},
340 {"www.google.com", "google.com."},
343 func TestLookupCNAME(t *testing.T) {
344 mustHaveExternalNetwork(t)
346 if !supportsIPv4() || !*testIPv4 {
347 t.Skip("IPv4 is required")
350 defer dnsWaitGroup.Wait()
352 attempts := 0
353 for i := 0; i < len(lookupCNAMETests); i++ {
354 tt := lookupCNAMETests[i]
355 cname, err := LookupCNAME(tt.name)
356 if err != nil {
357 testenv.SkipFlakyNet(t)
358 if attempts < len(backoffDuration) {
359 dur := backoffDuration[attempts]
360 t.Logf("backoff %v after failure %v\n", dur, err)
361 time.Sleep(dur)
362 attempts++
364 continue
366 t.Fatal(err)
368 if !strings.HasSuffix(cname, tt.cname) {
369 t.Errorf("got %s; want a record containing %s", cname, tt.cname)
374 var lookupGoogleHostTests = []struct {
375 name string
377 {"google.com"},
378 {"google.com."},
381 func TestLookupGoogleHost(t *testing.T) {
382 mustHaveExternalNetwork(t)
384 if !supportsIPv4() || !*testIPv4 {
385 t.Skip("IPv4 is required")
388 defer dnsWaitGroup.Wait()
390 for _, tt := range lookupGoogleHostTests {
391 addrs, err := LookupHost(tt.name)
392 if err != nil {
393 t.Fatal(err)
395 if len(addrs) == 0 {
396 t.Error("got no record")
398 for _, addr := range addrs {
399 if ParseIP(addr) == nil {
400 t.Errorf("got %q; want a literal IP address", addr)
406 func TestLookupLongTXT(t *testing.T) {
407 testenv.SkipFlaky(t, 22857)
408 mustHaveExternalNetwork(t)
410 defer dnsWaitGroup.Wait()
412 txts, err := LookupTXT("golang.rsc.io")
413 if err != nil {
414 t.Fatal(err)
416 sort.Strings(txts)
417 want := []string{
418 strings.Repeat("abcdefghijklmnopqrstuvwxyABCDEFGHJIKLMNOPQRSTUVWXY", 10),
419 "gophers rule",
421 if !reflect.DeepEqual(txts, want) {
422 t.Fatalf("LookupTXT golang.rsc.io incorrect\nhave %q\nwant %q", txts, want)
426 var lookupGoogleIPTests = []struct {
427 name string
429 {"google.com"},
430 {"google.com."},
433 func TestLookupGoogleIP(t *testing.T) {
434 mustHaveExternalNetwork(t)
436 if !supportsIPv4() || !*testIPv4 {
437 t.Skip("IPv4 is required")
440 defer dnsWaitGroup.Wait()
442 for _, tt := range lookupGoogleIPTests {
443 ips, err := LookupIP(tt.name)
444 if err != nil {
445 t.Fatal(err)
447 if len(ips) == 0 {
448 t.Error("got no record")
450 for _, ip := range ips {
451 if ip.To4() == nil && ip.To16() == nil {
452 t.Errorf("got %v; want an IP address", ip)
458 var revAddrTests = []struct {
459 Addr string
460 Reverse string
461 ErrPrefix string
463 {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
464 {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
465 {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
466 {"::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.", ""},
467 {"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.", ""},
468 {"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.", ""},
469 {"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.", ""},
470 {"1.2.3", "", "unrecognized address"},
471 {"1.2.3.4.5", "", "unrecognized address"},
472 {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
473 {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
476 func TestReverseAddress(t *testing.T) {
477 defer dnsWaitGroup.Wait()
478 for i, tt := range revAddrTests {
479 a, err := reverseaddr(tt.Addr)
480 if len(tt.ErrPrefix) > 0 && err == nil {
481 t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
482 continue
484 if len(tt.ErrPrefix) == 0 && err != nil {
485 t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
487 if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
488 t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
490 if a != tt.Reverse {
491 t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
496 func TestDNSFlood(t *testing.T) {
497 if !*testDNSFlood {
498 t.Skip("test disabled; use -dnsflood to enable")
501 defer dnsWaitGroup.Wait()
503 var N = 5000
504 if runtime.GOOS == "darwin" {
505 // On Darwin this test consumes kernel threads much
506 // than other platforms for some reason.
507 // When we monitor the number of allocated Ms by
508 // observing on runtime.newm calls, we can see that it
509 // easily reaches the per process ceiling
510 // kern.num_threads when CGO_ENABLED=1 and
511 // GODEBUG=netdns=go.
512 N = 500
515 const timeout = 3 * time.Second
516 ctxHalfTimeout, cancel := context.WithTimeout(context.Background(), timeout/2)
517 defer cancel()
518 ctxTimeout, cancel := context.WithTimeout(context.Background(), timeout)
519 defer cancel()
521 c := make(chan error, 2*N)
522 for i := 0; i < N; i++ {
523 name := fmt.Sprintf("%d.net-test.golang.org", i)
524 go func() {
525 _, err := DefaultResolver.LookupIPAddr(ctxHalfTimeout, name)
526 c <- err
528 go func() {
529 _, err := DefaultResolver.LookupIPAddr(ctxTimeout, name)
530 c <- err
533 qstats := struct {
534 succeeded, failed int
535 timeout, temporary, other int
536 unknown int
538 deadline := time.After(timeout + time.Second)
539 for i := 0; i < 2*N; i++ {
540 select {
541 case <-deadline:
542 t.Fatal("deadline exceeded")
543 case err := <-c:
544 switch err := err.(type) {
545 case nil:
546 qstats.succeeded++
547 case Error:
548 qstats.failed++
549 if err.Timeout() {
550 qstats.timeout++
552 if err.Temporary() {
553 qstats.temporary++
555 if !err.Timeout() && !err.Temporary() {
556 qstats.other++
558 default:
559 qstats.failed++
560 qstats.unknown++
565 // A high volume of DNS queries for sub-domain of golang.org
566 // would be coordinated by authoritative or recursive server,
567 // or stub resolver which implements query-response rate
568 // limitation, so we can expect some query successes and more
569 // failures including timeout, temporary and other here.
570 // As a rule, unknown must not be shown but it might possibly
571 // happen due to issue 4856 for now.
572 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)
575 func TestLookupDotsWithLocalSource(t *testing.T) {
576 if !supportsIPv4() || !*testIPv4 {
577 t.Skip("IPv4 is required")
580 mustHaveExternalNetwork(t)
582 defer dnsWaitGroup.Wait()
584 for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
585 fixup := fn()
586 if fixup == nil {
587 continue
589 names, err := LookupAddr("127.0.0.1")
590 fixup()
591 if err != nil {
592 t.Logf("#%d: %v", i, err)
593 continue
595 mode := "netgo"
596 if i == 1 {
597 mode = "netcgo"
599 loop:
600 for i, name := range names {
601 if strings.Index(name, ".") == len(name)-1 { // "localhost" not "localhost."
602 for j := range names {
603 if j == i {
604 continue
606 if names[j] == name[:len(name)-1] {
607 // It's OK if we find the name without the dot,
608 // as some systems say 127.0.0.1 localhost localhost.
609 continue loop
612 t.Errorf("%s: got %s; want %s", mode, name, name[:len(name)-1])
613 } else if strings.Contains(name, ".") && !strings.HasSuffix(name, ".") { // "localhost.localdomain." not "localhost.localdomain"
614 t.Errorf("%s: got %s; want name ending with trailing dot", mode, name)
620 func TestLookupDotsWithRemoteSource(t *testing.T) {
621 mustHaveExternalNetwork(t)
623 if !supportsIPv4() || !*testIPv4 {
624 t.Skip("IPv4 is required")
627 if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
628 t.Skip("no resolv.conf on iOS")
631 defer dnsWaitGroup.Wait()
633 if fixup := forceGoDNS(); fixup != nil {
634 testDots(t, "go")
635 fixup()
637 if fixup := forceCgoDNS(); fixup != nil {
638 testDots(t, "cgo")
639 fixup()
643 func testDots(t *testing.T, mode string) {
644 names, err := LookupAddr("8.8.8.8") // Google dns server
645 if err != nil {
646 testenv.SkipFlakyNet(t)
647 t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
648 } else {
649 for _, name := range names {
650 if !strings.HasSuffix(name, ".google.com.") {
651 t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
652 break
657 cname, err := LookupCNAME("www.mit.edu")
658 if err != nil {
659 testenv.SkipFlakyNet(t)
660 t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
661 } else if !strings.HasSuffix(cname, ".") {
662 t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
665 mxs, err := LookupMX("google.com")
666 if err != nil {
667 testenv.SkipFlakyNet(t)
668 t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
669 } else {
670 for _, mx := range mxs {
671 if !strings.HasSuffix(mx.Host, ".google.com.") {
672 t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
673 break
678 nss, err := LookupNS("google.com")
679 if err != nil {
680 testenv.SkipFlakyNet(t)
681 t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
682 } else {
683 for _, ns := range nss {
684 if !strings.HasSuffix(ns.Host, ".google.com.") {
685 t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
686 break
691 cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
692 if err != nil {
693 testenv.SkipFlakyNet(t)
694 t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
695 } else {
696 if !strings.HasSuffix(cname, ".google.com.") {
697 t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
699 for _, srv := range srvs {
700 if !strings.HasSuffix(srv.Target, ".google.com.") {
701 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)
702 break
708 func mxString(mxs []*MX) string {
709 var buf bytes.Buffer
710 sep := ""
711 fmt.Fprintf(&buf, "[")
712 for _, mx := range mxs {
713 fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
714 sep = " "
716 fmt.Fprintf(&buf, "]")
717 return buf.String()
720 func nsString(nss []*NS) string {
721 var buf bytes.Buffer
722 sep := ""
723 fmt.Fprintf(&buf, "[")
724 for _, ns := range nss {
725 fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
726 sep = " "
728 fmt.Fprintf(&buf, "]")
729 return buf.String()
732 func srvString(srvs []*SRV) string {
733 var buf bytes.Buffer
734 sep := ""
735 fmt.Fprintf(&buf, "[")
736 for _, srv := range srvs {
737 fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
738 sep = " "
740 fmt.Fprintf(&buf, "]")
741 return buf.String()
744 func TestLookupPort(t *testing.T) {
745 // See https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
747 // Please be careful about adding new test cases.
748 // There are platforms which have incomplete mappings for
749 // restricted resource access and security reasons.
750 type test struct {
751 network string
752 name string
753 port int
754 ok bool
756 var tests = []test{
757 {"tcp", "0", 0, true},
758 {"udp", "0", 0, true},
759 {"udp", "domain", 53, true},
761 {"--badnet--", "zzz", 0, false},
762 {"tcp", "--badport--", 0, false},
763 {"tcp", "-1", 0, false},
764 {"tcp", "65536", 0, false},
765 {"udp", "-1", 0, false},
766 {"udp", "65536", 0, false},
767 {"tcp", "123456789", 0, false},
769 // Issue 13610: LookupPort("tcp", "")
770 {"tcp", "", 0, true},
771 {"tcp4", "", 0, true},
772 {"tcp6", "", 0, true},
773 {"udp", "", 0, true},
774 {"udp4", "", 0, true},
775 {"udp6", "", 0, true},
778 switch runtime.GOOS {
779 case "android":
780 if netGo {
781 t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
783 default:
784 tests = append(tests, test{"tcp", "http", 80, true})
787 for _, tt := range tests {
788 port, err := LookupPort(tt.network, tt.name)
789 if port != tt.port || (err == nil) != tt.ok {
790 t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=%t", tt.network, tt.name, port, err, tt.port, !tt.ok)
792 if err != nil {
793 if perr := parseLookupPortError(err); perr != nil {
794 t.Error(perr)
800 // Like TestLookupPort but with minimal tests that should always pass
801 // because the answers are baked-in to the net package.
802 func TestLookupPort_Minimal(t *testing.T) {
803 type test struct {
804 network string
805 name string
806 port int
808 var tests = []test{
809 {"tcp", "http", 80},
810 {"tcp", "HTTP", 80}, // case shouldn't matter
811 {"tcp", "https", 443},
812 {"tcp", "ssh", 22},
813 {"tcp", "gopher", 70},
814 {"tcp4", "http", 80},
815 {"tcp6", "http", 80},
818 for _, tt := range tests {
819 port, err := LookupPort(tt.network, tt.name)
820 if port != tt.port || err != nil {
821 t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=nil", tt.network, tt.name, port, err, tt.port)
826 func TestLookupProtocol_Minimal(t *testing.T) {
827 type test struct {
828 name string
829 want int
831 var tests = []test{
832 {"tcp", 6},
833 {"TcP", 6}, // case shouldn't matter
834 {"icmp", 1},
835 {"igmp", 2},
836 {"udp", 17},
837 {"ipv6-icmp", 58},
840 for _, tt := range tests {
841 got, err := lookupProtocol(context.Background(), tt.name)
842 if got != tt.want || err != nil {
843 t.Errorf("LookupProtocol(%q) = %d, %v; want %d, error=nil", tt.name, got, err, tt.want)
849 func TestLookupNonLDH(t *testing.T) {
850 if runtime.GOOS == "nacl" {
851 t.Skip("skip on nacl")
854 defer dnsWaitGroup.Wait()
856 if fixup := forceGoDNS(); fixup != nil {
857 defer fixup()
860 // "LDH" stands for letters, digits, and hyphens and is the usual
861 // description of standard DNS names.
862 // This test is checking that other kinds of names are reported
863 // as not found, not reported as invalid names.
864 addrs, err := LookupHost("!!!.###.bogus..domain.")
865 if err == nil {
866 t.Fatalf("lookup succeeded: %v", addrs)
868 if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) {
869 t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost)
873 func TestLookupContextCancel(t *testing.T) {
874 mustHaveExternalNetwork(t)
875 if runtime.GOOS == "nacl" {
876 t.Skip("skip on nacl")
879 defer dnsWaitGroup.Wait()
881 ctx, ctxCancel := context.WithCancel(context.Background())
882 ctxCancel()
883 _, err := DefaultResolver.LookupIPAddr(ctx, "google.com")
884 if err != errCanceled {
885 testenv.SkipFlakyNet(t)
886 t.Fatal(err)
888 ctx = context.Background()
889 _, err = DefaultResolver.LookupIPAddr(ctx, "google.com")
890 if err != nil {
891 testenv.SkipFlakyNet(t)
892 t.Fatal(err)
896 // Issue 24330: treat the nil *Resolver like a zero value. Verify nothing
897 // crashes if nil is used.
898 func TestNilResolverLookup(t *testing.T) {
899 mustHaveExternalNetwork(t)
900 if runtime.GOOS == "nacl" {
901 t.Skip("skip on nacl")
903 var r *Resolver = nil
904 ctx := context.Background()
906 // Don't care about the results, just that nothing panics:
907 r.LookupAddr(ctx, "8.8.8.8")
908 r.LookupCNAME(ctx, "google.com")
909 r.LookupHost(ctx, "google.com")
910 r.LookupIPAddr(ctx, "google.com")
911 r.LookupMX(ctx, "gmail.com")
912 r.LookupNS(ctx, "google.com")
913 r.LookupPort(ctx, "tcp", "smtp")
914 r.LookupSRV(ctx, "service", "proto", "name")
915 r.LookupTXT(ctx, "gmail.com")
918 // TestLookupHostCancel verifies that lookup works even after many
919 // canceled lookups (see golang.org/issue/24178 for details).
920 func TestLookupHostCancel(t *testing.T) {
921 mustHaveExternalNetwork(t)
922 if runtime.GOOS == "nacl" {
923 t.Skip("skip on nacl")
926 const (
927 google = "www.google.com"
928 invalidDomain = "nonexistentdomain.golang.org"
929 n = 600 // this needs to be larger than threadLimit size
932 _, err := LookupHost(google)
933 if err != nil {
934 t.Fatal(err)
937 ctx, cancel := context.WithCancel(context.Background())
938 cancel()
939 for i := 0; i < n; i++ {
940 addr, err := DefaultResolver.LookupHost(ctx, invalidDomain)
941 if err == nil {
942 t.Fatalf("LookupHost(%q): returns %v, but should fail", invalidDomain, addr)
944 if !strings.Contains(err.Error(), "canceled") {
945 t.Fatalf("LookupHost(%q): failed with unexpected error: %v", invalidDomain, err)
947 time.Sleep(time.Millisecond * 1)
950 _, err = LookupHost(google)
951 if err != nil {
952 t.Fatal(err)
956 type lookupCustomResolver struct {
957 *Resolver
958 mu sync.RWMutex
959 dialed bool
962 func (lcr *lookupCustomResolver) dial() func(ctx context.Context, network, address string) (Conn, error) {
963 return func(ctx context.Context, network, address string) (Conn, error) {
964 lcr.mu.Lock()
965 lcr.dialed = true
966 lcr.mu.Unlock()
967 return Dial(network, address)
971 // TestConcurrentPreferGoResolversDial tests that multiple resolvers with the
972 // PreferGo option used concurrently are all dialed properly.
973 func TestConcurrentPreferGoResolversDial(t *testing.T) {
974 // The windows implementation of the resolver does not use the Dial
975 // function.
976 if runtime.GOOS == "windows" {
977 t.Skip("skip on windows")
980 testenv.MustHaveExternalNetwork(t)
981 testenv.SkipFlakyNet(t)
983 defer dnsWaitGroup.Wait()
985 resolvers := make([]*lookupCustomResolver, 2)
986 for i := range resolvers {
987 cs := lookupCustomResolver{Resolver: &Resolver{PreferGo: true}}
988 cs.Dial = cs.dial()
989 resolvers[i] = &cs
992 var wg sync.WaitGroup
993 wg.Add(len(resolvers))
994 for i, resolver := range resolvers {
995 go func(r *Resolver, index int) {
996 defer wg.Done()
997 _, err := r.LookupIPAddr(context.Background(), "google.com")
998 if err != nil {
999 t.Fatalf("lookup failed for resolver %d: %q", index, err)
1001 }(resolver.Resolver, i)
1003 wg.Wait()
1005 for i, resolver := range resolvers {
1006 if !resolver.dialed {
1007 t.Errorf("custom resolver %d not dialed during lookup", i)