* gcc-interface/decl.c (warn_on_field_placement): Issue the warning
[official-gcc.git] / libgo / go / net / lookup_test.go
blob36db56acd03741da35a113bf93e4e0097e37f9a3
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 package net
7 import (
8 "bytes"
9 "context"
10 "fmt"
11 "internal/testenv"
12 "runtime"
13 "strings"
14 "testing"
15 "time"
18 func lookupLocalhost(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
19 switch host {
20 case "localhost":
21 return []IPAddr{
22 {IP: IPv4(127, 0, 0, 1)},
23 {IP: IPv6loopback},
24 }, nil
25 default:
26 return fn(ctx, host)
30 // The Lookup APIs use various sources such as local database, DNS or
31 // mDNS, and may use platform-dependent DNS stub resolver if possible.
32 // The APIs accept any of forms for a query; host name in various
33 // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
34 // FQDN, but the result would be one of the forms and it depends on
35 // the circumstances.
37 var lookupGoogleSRVTests = []struct {
38 service, proto, name string
39 cname, target string
42 "xmpp-server", "tcp", "google.com",
43 "google.com.", "google.com.",
46 "xmpp-server", "tcp", "google.com.",
47 "google.com.", "google.com.",
50 // non-standard back door
52 "", "", "_xmpp-server._tcp.google.com",
53 "google.com.", "google.com.",
56 "", "", "_xmpp-server._tcp.google.com.",
57 "google.com.", "google.com.",
61 func TestLookupGoogleSRV(t *testing.T) {
62 if testenv.Builder() == "" {
63 testenv.MustHaveExternalNetwork(t)
66 if !supportsIPv4 || !*testIPv4 {
67 t.Skip("IPv4 is required")
70 for _, tt := range lookupGoogleSRVTests {
71 cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
72 if err != nil {
73 testenv.SkipFlakyNet(t)
74 t.Fatal(err)
76 if len(srvs) == 0 {
77 t.Error("got no record")
79 if !strings.HasSuffix(cname, tt.cname) {
80 t.Errorf("got %s; want %s", cname, tt.cname)
82 for _, srv := range srvs {
83 if !strings.HasSuffix(srv.Target, tt.target) {
84 t.Errorf("got %v; want a record containing %s", srv, tt.target)
90 var lookupGmailMXTests = []struct {
91 name, host string
93 {"gmail.com", "google.com."},
94 {"gmail.com.", "google.com."},
97 func TestLookupGmailMX(t *testing.T) {
98 if testenv.Builder() == "" {
99 testenv.MustHaveExternalNetwork(t)
102 if !supportsIPv4 || !*testIPv4 {
103 t.Skip("IPv4 is required")
106 for _, tt := range lookupGmailMXTests {
107 mxs, err := LookupMX(tt.name)
108 if err != nil {
109 t.Fatal(err)
111 if len(mxs) == 0 {
112 t.Error("got no record")
114 for _, mx := range mxs {
115 if !strings.HasSuffix(mx.Host, tt.host) {
116 t.Errorf("got %v; want a record containing %s", mx, tt.host)
122 var lookupGmailNSTests = []struct {
123 name, host string
125 {"gmail.com", "google.com."},
126 {"gmail.com.", "google.com."},
129 func TestLookupGmailNS(t *testing.T) {
130 if testenv.Builder() == "" {
131 testenv.MustHaveExternalNetwork(t)
134 if !supportsIPv4 || !*testIPv4 {
135 t.Skip("IPv4 is required")
138 for _, tt := range lookupGmailNSTests {
139 nss, err := LookupNS(tt.name)
140 if err != nil {
141 testenv.SkipFlakyNet(t)
142 t.Fatal(err)
144 if len(nss) == 0 {
145 t.Error("got no record")
147 for _, ns := range nss {
148 if !strings.HasSuffix(ns.Host, tt.host) {
149 t.Errorf("got %v; want a record containing %s", ns, tt.host)
155 var lookupGmailTXTTests = []struct {
156 name, txt, host string
158 {"gmail.com", "spf", "google.com"},
159 {"gmail.com.", "spf", "google.com"},
162 func TestLookupGmailTXT(t *testing.T) {
163 if testenv.Builder() == "" {
164 testenv.MustHaveExternalNetwork(t)
167 if !supportsIPv4 || !*testIPv4 {
168 t.Skip("IPv4 is required")
171 for _, tt := range lookupGmailTXTTests {
172 txts, err := LookupTXT(tt.name)
173 if err != nil {
174 t.Fatal(err)
176 if len(txts) == 0 {
177 t.Error("got no record")
179 for _, txt := range txts {
180 if !strings.Contains(txt, tt.txt) || (!strings.HasSuffix(txt, tt.host) && !strings.HasSuffix(txt, tt.host+".")) {
181 t.Errorf("got %s; want a record containing %s, %s", txt, tt.txt, tt.host)
187 var lookupGooglePublicDNSAddrTests = []struct {
188 addr, name string
190 {"8.8.8.8", ".google.com."},
191 {"8.8.4.4", ".google.com."},
193 {"2001:4860:4860::8888", ".google.com."},
194 {"2001:4860:4860::8844", ".google.com."},
197 func TestLookupGooglePublicDNSAddr(t *testing.T) {
198 if testenv.Builder() == "" {
199 testenv.MustHaveExternalNetwork(t)
202 if !supportsIPv4 || !supportsIPv6 || !*testIPv4 || !*testIPv6 {
203 t.Skip("both IPv4 and IPv6 are required")
206 for _, tt := range lookupGooglePublicDNSAddrTests {
207 names, err := LookupAddr(tt.addr)
208 if err != nil {
209 t.Fatal(err)
211 if len(names) == 0 {
212 t.Error("got no record")
214 for _, name := range names {
215 if !strings.HasSuffix(name, tt.name) {
216 t.Errorf("got %s; want a record containing %s", name, tt.name)
222 func TestLookupIPv6LinkLocalAddr(t *testing.T) {
223 if !supportsIPv6 || !*testIPv6 {
224 t.Skip("IPv6 is required")
227 addrs, err := LookupHost("localhost")
228 if err != nil {
229 t.Fatal(err)
231 found := false
232 for _, addr := range addrs {
233 if addr == "fe80::1%lo0" {
234 found = true
235 break
238 if !found {
239 t.Skipf("not supported on %s", runtime.GOOS)
241 if _, err := LookupAddr("fe80::1%lo0"); err != nil {
242 t.Error(err)
246 var lookupCNAMETests = []struct {
247 name, cname string
249 {"www.iana.org", "icann.org."},
250 {"www.iana.org.", "icann.org."},
251 {"www.google.com", "google.com."},
254 func TestLookupCNAME(t *testing.T) {
255 if testenv.Builder() == "" {
256 testenv.MustHaveExternalNetwork(t)
259 if !supportsIPv4 || !*testIPv4 {
260 t.Skip("IPv4 is required")
263 for _, tt := range lookupCNAMETests {
264 cname, err := LookupCNAME(tt.name)
265 if err != nil {
266 t.Fatal(err)
268 if !strings.HasSuffix(cname, tt.cname) {
269 t.Errorf("got %s; want a record containing %s", cname, tt.cname)
274 var lookupGoogleHostTests = []struct {
275 name string
277 {"google.com"},
278 {"google.com."},
281 func TestLookupGoogleHost(t *testing.T) {
282 if testenv.Builder() == "" {
283 testenv.MustHaveExternalNetwork(t)
286 if !supportsIPv4 || !*testIPv4 {
287 t.Skip("IPv4 is required")
290 for _, tt := range lookupGoogleHostTests {
291 addrs, err := LookupHost(tt.name)
292 if err != nil {
293 t.Fatal(err)
295 if len(addrs) == 0 {
296 t.Error("got no record")
298 for _, addr := range addrs {
299 if ParseIP(addr) == nil {
300 t.Errorf("got %q; want a literal IP address", addr)
306 var lookupGoogleIPTests = []struct {
307 name string
309 {"google.com"},
310 {"google.com."},
313 func TestLookupGoogleIP(t *testing.T) {
314 if testenv.Builder() == "" {
315 testenv.MustHaveExternalNetwork(t)
318 if !supportsIPv4 || !*testIPv4 {
319 t.Skip("IPv4 is required")
322 for _, tt := range lookupGoogleIPTests {
323 ips, err := LookupIP(tt.name)
324 if err != nil {
325 t.Fatal(err)
327 if len(ips) == 0 {
328 t.Error("got no record")
330 for _, ip := range ips {
331 if ip.To4() == nil && ip.To16() == nil {
332 t.Errorf("got %v; want an IP address", ip)
338 var revAddrTests = []struct {
339 Addr string
340 Reverse string
341 ErrPrefix string
343 {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
344 {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
345 {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
346 {"::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.", ""},
347 {"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.", ""},
348 {"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.", ""},
349 {"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.", ""},
350 {"1.2.3", "", "unrecognized address"},
351 {"1.2.3.4.5", "", "unrecognized address"},
352 {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
353 {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
356 func TestReverseAddress(t *testing.T) {
357 for i, tt := range revAddrTests {
358 a, err := reverseaddr(tt.Addr)
359 if len(tt.ErrPrefix) > 0 && err == nil {
360 t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
361 continue
363 if len(tt.ErrPrefix) == 0 && err != nil {
364 t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
366 if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
367 t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
369 if a != tt.Reverse {
370 t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
375 func TestDNSFlood(t *testing.T) {
376 if !*testDNSFlood {
377 t.Skip("test disabled; use -dnsflood to enable")
380 var N = 5000
381 if runtime.GOOS == "darwin" {
382 // On Darwin this test consumes kernel threads much
383 // than other platforms for some reason.
384 // When we monitor the number of allocated Ms by
385 // observing on runtime.newm calls, we can see that it
386 // easily reaches the per process ceiling
387 // kern.num_threads when CGO_ENABLED=1 and
388 // GODEBUG=netdns=go.
389 N = 500
392 const timeout = 3 * time.Second
393 ctxHalfTimeout, cancel := context.WithTimeout(context.Background(), timeout/2)
394 defer cancel()
395 ctxTimeout, cancel := context.WithTimeout(context.Background(), timeout)
396 defer cancel()
398 c := make(chan error, 2*N)
399 for i := 0; i < N; i++ {
400 name := fmt.Sprintf("%d.net-test.golang.org", i)
401 go func() {
402 _, err := DefaultResolver.LookupIPAddr(ctxHalfTimeout, name)
403 c <- err
405 go func() {
406 _, err := DefaultResolver.LookupIPAddr(ctxTimeout, name)
407 c <- err
410 qstats := struct {
411 succeeded, failed int
412 timeout, temporary, other int
413 unknown int
415 deadline := time.After(timeout + time.Second)
416 for i := 0; i < 2*N; i++ {
417 select {
418 case <-deadline:
419 t.Fatal("deadline exceeded")
420 case err := <-c:
421 switch err := err.(type) {
422 case nil:
423 qstats.succeeded++
424 case Error:
425 qstats.failed++
426 if err.Timeout() {
427 qstats.timeout++
429 if err.Temporary() {
430 qstats.temporary++
432 if !err.Timeout() && !err.Temporary() {
433 qstats.other++
435 default:
436 qstats.failed++
437 qstats.unknown++
442 // A high volume of DNS queries for sub-domain of golang.org
443 // would be coordinated by authoritative or recursive server,
444 // or stub resolver which implements query-response rate
445 // limitation, so we can expect some query successes and more
446 // failures including timeout, temporary and other here.
447 // As a rule, unknown must not be shown but it might possibly
448 // happen due to issue 4856 for now.
449 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)
452 func TestLookupDotsWithLocalSource(t *testing.T) {
453 if !supportsIPv4 || !*testIPv4 {
454 t.Skip("IPv4 is required")
457 if testenv.Builder() == "" {
458 testenv.MustHaveExternalNetwork(t)
461 for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
462 fixup := fn()
463 if fixup == nil {
464 continue
466 names, err := LookupAddr("127.0.0.1")
467 fixup()
468 if err != nil {
469 t.Logf("#%d: %v", i, err)
470 continue
472 mode := "netgo"
473 if i == 1 {
474 mode = "netcgo"
476 loop:
477 for i, name := range names {
478 if strings.Index(name, ".") == len(name)-1 { // "localhost" not "localhost."
479 for j := range names {
480 if j == i {
481 continue
483 if names[j] == name[:len(name)-1] {
484 // It's OK if we find the name without the dot,
485 // as some systems say 127.0.0.1 localhost localhost.
486 continue loop
489 t.Errorf("%s: got %s; want %s", mode, name, name[:len(name)-1])
490 } else if strings.Contains(name, ".") && !strings.HasSuffix(name, ".") { // "localhost.localdomain." not "localhost.localdomain"
491 t.Errorf("%s: got %s; want name ending with trailing dot", mode, name)
497 func TestLookupDotsWithRemoteSource(t *testing.T) {
498 if testenv.Builder() == "" {
499 testenv.MustHaveExternalNetwork(t)
502 if !supportsIPv4 || !*testIPv4 {
503 t.Skip("IPv4 is required")
506 if fixup := forceGoDNS(); fixup != nil {
507 testDots(t, "go")
508 fixup()
510 if fixup := forceCgoDNS(); fixup != nil {
511 testDots(t, "cgo")
512 fixup()
516 func testDots(t *testing.T, mode string) {
517 names, err := LookupAddr("8.8.8.8") // Google dns server
518 if err != nil {
519 testenv.SkipFlakyNet(t)
520 t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
521 } else {
522 for _, name := range names {
523 if !strings.HasSuffix(name, ".google.com.") {
524 t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
525 break
530 cname, err := LookupCNAME("www.mit.edu")
531 if err != nil {
532 testenv.SkipFlakyNet(t)
533 t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
534 } else if !strings.HasSuffix(cname, ".") {
535 t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
538 mxs, err := LookupMX("google.com")
539 if err != nil {
540 testenv.SkipFlakyNet(t)
541 t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
542 } else {
543 for _, mx := range mxs {
544 if !strings.HasSuffix(mx.Host, ".google.com.") {
545 t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
546 break
551 nss, err := LookupNS("google.com")
552 if err != nil {
553 testenv.SkipFlakyNet(t)
554 t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
555 } else {
556 for _, ns := range nss {
557 if !strings.HasSuffix(ns.Host, ".google.com.") {
558 t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
559 break
564 cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
565 if err != nil {
566 testenv.SkipFlakyNet(t)
567 t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
568 } else {
569 if !strings.HasSuffix(cname, ".google.com.") {
570 t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
572 for _, srv := range srvs {
573 if !strings.HasSuffix(srv.Target, ".google.com.") {
574 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)
575 break
581 func mxString(mxs []*MX) string {
582 var buf bytes.Buffer
583 sep := ""
584 fmt.Fprintf(&buf, "[")
585 for _, mx := range mxs {
586 fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
587 sep = " "
589 fmt.Fprintf(&buf, "]")
590 return buf.String()
593 func nsString(nss []*NS) string {
594 var buf bytes.Buffer
595 sep := ""
596 fmt.Fprintf(&buf, "[")
597 for _, ns := range nss {
598 fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
599 sep = " "
601 fmt.Fprintf(&buf, "]")
602 return buf.String()
605 func srvString(srvs []*SRV) string {
606 var buf bytes.Buffer
607 sep := ""
608 fmt.Fprintf(&buf, "[")
609 for _, srv := range srvs {
610 fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
611 sep = " "
613 fmt.Fprintf(&buf, "]")
614 return buf.String()
617 func TestLookupPort(t *testing.T) {
618 // See http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
620 // Please be careful about adding new test cases.
621 // There are platforms having incomplete mappings for
622 // restricted resource access and security reasons.
623 type test struct {
624 network string
625 name string
626 port int
627 ok bool
629 var tests = []test{
630 {"tcp", "0", 0, true},
631 {"udp", "0", 0, true},
632 {"udp", "domain", 53, true},
634 {"--badnet--", "zzz", 0, false},
635 {"tcp", "--badport--", 0, false},
636 {"tcp", "-1", 0, false},
637 {"tcp", "65536", 0, false},
638 {"udp", "-1", 0, false},
639 {"udp", "65536", 0, false},
640 {"tcp", "123456789", 0, false},
642 // Issue 13610: LookupPort("tcp", "")
643 {"tcp", "", 0, true},
644 {"tcp4", "", 0, true},
645 {"tcp6", "", 0, true},
646 {"udp", "", 0, true},
647 {"udp4", "", 0, true},
648 {"udp6", "", 0, true},
651 switch runtime.GOOS {
652 case "android":
653 if netGo {
654 t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
656 default:
657 tests = append(tests, test{"tcp", "http", 80, true})
660 for _, tt := range tests {
661 port, err := LookupPort(tt.network, tt.name)
662 if port != tt.port || (err == nil) != tt.ok {
663 t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=%t", tt.network, tt.name, port, err, tt.port, !tt.ok)
665 if err != nil {
666 if perr := parseLookupPortError(err); perr != nil {
667 t.Error(perr)
673 // Like TestLookupPort but with minimal tests that should always pass
674 // because the answers are baked-in to the net package.
675 func TestLookupPort_Minimal(t *testing.T) {
676 type test struct {
677 network string
678 name string
679 port int
681 var tests = []test{
682 {"tcp", "http", 80},
683 {"tcp", "HTTP", 80}, // case shouldn't matter
684 {"tcp", "https", 443},
685 {"tcp", "ssh", 22},
686 {"tcp", "gopher", 70},
687 {"tcp4", "http", 80},
688 {"tcp6", "http", 80},
691 for _, tt := range tests {
692 port, err := LookupPort(tt.network, tt.name)
693 if port != tt.port || err != nil {
694 t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=nil", tt.network, tt.name, port, err, tt.port)
699 func TestLookupProtocol_Minimal(t *testing.T) {
700 type test struct {
701 name string
702 want int
704 var tests = []test{
705 {"tcp", 6},
706 {"TcP", 6}, // case shouldn't matter
707 {"icmp", 1},
708 {"igmp", 2},
709 {"udp", 17},
710 {"ipv6-icmp", 58},
713 for _, tt := range tests {
714 got, err := lookupProtocol(context.Background(), tt.name)
715 if got != tt.want || err != nil {
716 t.Errorf("LookupProtocol(%q) = %d, %v; want %d, error=nil", tt.name, got, err, tt.want)
722 func TestLookupNonLDH(t *testing.T) {
723 if runtime.GOOS == "nacl" {
724 t.Skip("skip on nacl")
726 if fixup := forceGoDNS(); fixup != nil {
727 defer fixup()
730 // "LDH" stands for letters, digits, and hyphens and is the usual
731 // description of standard DNS names.
732 // This test is checking that other kinds of names are reported
733 // as not found, not reported as invalid names.
734 addrs, err := LookupHost("!!!.###.bogus..domain.")
735 if err == nil {
736 t.Fatalf("lookup succeeded: %v", addrs)
738 if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) {
739 t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost)