github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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 "bytes" 9 "context" 10 "fmt" 11 "internal/testenv" 12 "runtime" 13 "strings" 14 "testing" 15 "time" 16 ) 17 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) 27 } 28 } 29 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. 36 37 var lookupGoogleSRVTests = []struct { 38 service, proto, name string 39 cname, target string 40 }{ 41 { 42 "xmpp-server", "tcp", "google.com", 43 "google.com.", "google.com.", 44 }, 45 { 46 "xmpp-server", "tcp", "google.com.", 47 "google.com.", "google.com.", 48 }, 49 50 // non-standard back door 51 { 52 "", "", "_xmpp-server._tcp.google.com", 53 "google.com.", "google.com.", 54 }, 55 { 56 "", "", "_xmpp-server._tcp.google.com.", 57 "google.com.", "google.com.", 58 }, 59 } 60 61 func TestLookupGoogleSRV(t *testing.T) { 62 if testenv.Builder() == "" { 63 testenv.MustHaveExternalNetwork(t) 64 } 65 66 if !supportsIPv4() || !*testIPv4 { 67 t.Skip("IPv4 is required") 68 } 69 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) 75 } 76 if len(srvs) == 0 { 77 t.Error("got no record") 78 } 79 if !strings.HasSuffix(cname, tt.cname) { 80 t.Errorf("got %s; want %s", cname, tt.cname) 81 } 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) 85 } 86 } 87 } 88 } 89 90 var lookupGmailMXTests = []struct { 91 name, host string 92 }{ 93 {"gmail.com", "google.com."}, 94 {"gmail.com.", "google.com."}, 95 } 96 97 func TestLookupGmailMX(t *testing.T) { 98 if testenv.Builder() == "" { 99 testenv.MustHaveExternalNetwork(t) 100 } 101 102 if !supportsIPv4() || !*testIPv4 { 103 t.Skip("IPv4 is required") 104 } 105 106 for _, tt := range lookupGmailMXTests { 107 mxs, err := LookupMX(tt.name) 108 if err != nil { 109 t.Fatal(err) 110 } 111 if len(mxs) == 0 { 112 t.Error("got no record") 113 } 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) 117 } 118 } 119 } 120 } 121 122 var lookupGmailNSTests = []struct { 123 name, host string 124 }{ 125 {"gmail.com", "google.com."}, 126 {"gmail.com.", "google.com."}, 127 } 128 129 func TestLookupGmailNS(t *testing.T) { 130 if testenv.Builder() == "" { 131 testenv.MustHaveExternalNetwork(t) 132 } 133 134 if !supportsIPv4() || !*testIPv4 { 135 t.Skip("IPv4 is required") 136 } 137 138 for _, tt := range lookupGmailNSTests { 139 nss, err := LookupNS(tt.name) 140 if err != nil { 141 testenv.SkipFlakyNet(t) 142 t.Fatal(err) 143 } 144 if len(nss) == 0 { 145 t.Error("got no record") 146 } 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) 150 } 151 } 152 } 153 } 154 155 var lookupGmailTXTTests = []struct { 156 name, txt, host string 157 }{ 158 {"gmail.com", "spf", "google.com"}, 159 {"gmail.com.", "spf", "google.com"}, 160 } 161 162 func TestLookupGmailTXT(t *testing.T) { 163 if testenv.Builder() == "" { 164 testenv.MustHaveExternalNetwork(t) 165 } 166 167 if !supportsIPv4() || !*testIPv4 { 168 t.Skip("IPv4 is required") 169 } 170 171 for _, tt := range lookupGmailTXTTests { 172 txts, err := LookupTXT(tt.name) 173 if err != nil { 174 t.Fatal(err) 175 } 176 if len(txts) == 0 { 177 t.Error("got no record") 178 } 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) 182 } 183 } 184 } 185 } 186 187 var lookupGooglePublicDNSAddrTests = []struct { 188 addr, name string 189 }{ 190 {"8.8.8.8", ".google.com."}, 191 {"8.8.4.4", ".google.com."}, 192 193 {"2001:4860:4860::8888", ".google.com."}, 194 {"2001:4860:4860::8844", ".google.com."}, 195 } 196 197 func TestLookupGooglePublicDNSAddr(t *testing.T) { 198 if testenv.Builder() == "" { 199 testenv.MustHaveExternalNetwork(t) 200 } 201 202 if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 { 203 t.Skip("both IPv4 and IPv6 are required") 204 } 205 206 for _, tt := range lookupGooglePublicDNSAddrTests { 207 names, err := LookupAddr(tt.addr) 208 if err != nil { 209 t.Fatal(err) 210 } 211 if len(names) == 0 { 212 t.Error("got no record") 213 } 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) 217 } 218 } 219 } 220 } 221 222 func TestLookupIPv6LinkLocalAddr(t *testing.T) { 223 if !supportsIPv6() || !*testIPv6 { 224 t.Skip("IPv6 is required") 225 } 226 227 addrs, err := LookupHost("localhost") 228 if err != nil { 229 t.Fatal(err) 230 } 231 found := false 232 for _, addr := range addrs { 233 if addr == "fe80::1%lo0" { 234 found = true 235 break 236 } 237 } 238 if !found { 239 t.Skipf("not supported on %s", runtime.GOOS) 240 } 241 if _, err := LookupAddr("fe80::1%lo0"); err != nil { 242 t.Error(err) 243 } 244 } 245 246 var lookupCNAMETests = []struct { 247 name, cname string 248 }{ 249 {"www.iana.org", "icann.org."}, 250 {"www.iana.org.", "icann.org."}, 251 {"www.google.com", "google.com."}, 252 } 253 254 func TestLookupCNAME(t *testing.T) { 255 if testenv.Builder() == "" { 256 testenv.MustHaveExternalNetwork(t) 257 } 258 259 if !supportsIPv4() || !*testIPv4 { 260 t.Skip("IPv4 is required") 261 } 262 263 for _, tt := range lookupCNAMETests { 264 cname, err := LookupCNAME(tt.name) 265 if err != nil { 266 t.Fatal(err) 267 } 268 if !strings.HasSuffix(cname, tt.cname) { 269 t.Errorf("got %s; want a record containing %s", cname, tt.cname) 270 } 271 } 272 } 273 274 var lookupGoogleHostTests = []struct { 275 name string 276 }{ 277 {"google.com"}, 278 {"google.com."}, 279 } 280 281 func TestLookupGoogleHost(t *testing.T) { 282 if testenv.Builder() == "" { 283 testenv.MustHaveExternalNetwork(t) 284 } 285 286 if !supportsIPv4() || !*testIPv4 { 287 t.Skip("IPv4 is required") 288 } 289 290 for _, tt := range lookupGoogleHostTests { 291 addrs, err := LookupHost(tt.name) 292 if err != nil { 293 t.Fatal(err) 294 } 295 if len(addrs) == 0 { 296 t.Error("got no record") 297 } 298 for _, addr := range addrs { 299 if ParseIP(addr) == nil { 300 t.Errorf("got %q; want a literal IP address", addr) 301 } 302 } 303 } 304 } 305 306 var lookupGoogleIPTests = []struct { 307 name string 308 }{ 309 {"google.com"}, 310 {"google.com."}, 311 } 312 313 func TestLookupGoogleIP(t *testing.T) { 314 if testenv.Builder() == "" { 315 testenv.MustHaveExternalNetwork(t) 316 } 317 318 if !supportsIPv4() || !*testIPv4 { 319 t.Skip("IPv4 is required") 320 } 321 322 for _, tt := range lookupGoogleIPTests { 323 ips, err := LookupIP(tt.name) 324 if err != nil { 325 t.Fatal(err) 326 } 327 if len(ips) == 0 { 328 t.Error("got no record") 329 } 330 for _, ip := range ips { 331 if ip.To4() == nil && ip.To16() == nil { 332 t.Errorf("got %v; want an IP address", ip) 333 } 334 } 335 } 336 } 337 338 var revAddrTests = []struct { 339 Addr string 340 Reverse string 341 ErrPrefix string 342 }{ 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"}, 354 } 355 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 362 } 363 if len(tt.ErrPrefix) == 0 && err != nil { 364 t.Errorf("#%d: expected <nil>, got %q (error)", i, err) 365 } 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) 368 } 369 if a != tt.Reverse { 370 t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a) 371 } 372 } 373 } 374 375 func TestDNSFlood(t *testing.T) { 376 if !*testDNSFlood { 377 t.Skip("test disabled; use -dnsflood to enable") 378 } 379 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 390 } 391 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() 397 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 404 }() 405 go func() { 406 _, err := DefaultResolver.LookupIPAddr(ctxTimeout, name) 407 c <- err 408 }() 409 } 410 qstats := struct { 411 succeeded, failed int 412 timeout, temporary, other int 413 unknown int 414 }{} 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++ 428 } 429 if err.Temporary() { 430 qstats.temporary++ 431 } 432 if !err.Timeout() && !err.Temporary() { 433 qstats.other++ 434 } 435 default: 436 qstats.failed++ 437 qstats.unknown++ 438 } 439 } 440 } 441 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) 450 } 451 452 func TestLookupDotsWithLocalSource(t *testing.T) { 453 if !supportsIPv4() || !*testIPv4 { 454 t.Skip("IPv4 is required") 455 } 456 457 if testenv.Builder() == "" { 458 testenv.MustHaveExternalNetwork(t) 459 } 460 461 for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} { 462 fixup := fn() 463 if fixup == nil { 464 continue 465 } 466 names, err := LookupAddr("127.0.0.1") 467 fixup() 468 if err != nil { 469 t.Logf("#%d: %v", i, err) 470 continue 471 } 472 mode := "netgo" 473 if i == 1 { 474 mode = "netcgo" 475 } 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 482 } 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 487 } 488 } 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) 492 } 493 } 494 } 495 } 496 497 func TestLookupDotsWithRemoteSource(t *testing.T) { 498 if testenv.Builder() == "" { 499 testenv.MustHaveExternalNetwork(t) 500 } 501 502 if !supportsIPv4() || !*testIPv4 { 503 t.Skip("IPv4 is required") 504 } 505 506 if fixup := forceGoDNS(); fixup != nil { 507 testDots(t, "go") 508 fixup() 509 } 510 if fixup := forceCgoDNS(); fixup != nil { 511 testDots(t, "cgo") 512 fixup() 513 } 514 } 515 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 526 } 527 } 528 } 529 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) 536 } 537 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 547 } 548 } 549 } 550 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 560 } 561 } 562 } 563 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) 571 } 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 576 } 577 } 578 } 579 } 580 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 = " " 588 } 589 fmt.Fprintf(&buf, "]") 590 return buf.String() 591 } 592 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 = " " 600 } 601 fmt.Fprintf(&buf, "]") 602 return buf.String() 603 } 604 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 = " " 612 } 613 fmt.Fprintf(&buf, "]") 614 return buf.String() 615 } 616 617 func TestLookupPort(t *testing.T) { 618 // See http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml 619 // 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 628 } 629 var tests = []test{ 630 {"tcp", "0", 0, true}, 631 {"udp", "0", 0, true}, 632 {"udp", "domain", 53, true}, 633 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}, 641 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}, 649 } 650 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) 655 } 656 default: 657 tests = append(tests, test{"tcp", "http", 80, true}) 658 } 659 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) 664 } 665 if err != nil { 666 if perr := parseLookupPortError(err); perr != nil { 667 t.Error(perr) 668 } 669 } 670 } 671 } 672 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 680 } 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}, 689 } 690 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) 695 } 696 } 697 } 698 699 func TestLookupProtocol_Minimal(t *testing.T) { 700 type test struct { 701 name string 702 want int 703 } 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}, 711 } 712 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) 717 } 718 } 719 720 } 721 722 func TestLookupNonLDH(t *testing.T) { 723 if runtime.GOOS == "nacl" { 724 t.Skip("skip on nacl") 725 } 726 if fixup := forceGoDNS(); fixup != nil { 727 defer fixup() 728 } 729 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) 737 } 738 if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) { 739 t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost) 740 } 741 }