2013-08-13 10:44:12 -06:00
|
|
|
// Copyright 2013 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2014-04-30 08:26:07 -06:00
|
|
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
2013-08-13 14:44:57 -06:00
|
|
|
|
2013-08-13 10:44:12 -06:00
|
|
|
package net
|
|
|
|
|
|
|
|
import (
|
2014-05-14 18:11:00 -06:00
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"reflect"
|
2013-08-13 10:44:12 -06:00
|
|
|
"testing"
|
2014-05-14 18:11:00 -06:00
|
|
|
"time"
|
2013-08-13 10:44:12 -06:00
|
|
|
)
|
|
|
|
|
2014-08-05 18:58:47 -06:00
|
|
|
var dnsTransportFallbackTests = []struct {
|
|
|
|
server string
|
|
|
|
name string
|
|
|
|
qtype uint16
|
|
|
|
timeout int
|
|
|
|
rcode int
|
|
|
|
}{
|
|
|
|
// Querying "com." with qtype=255 usually makes an answer
|
|
|
|
// which requires more than 512 bytes.
|
|
|
|
{"8.8.8.8:53", "com.", dnsTypeALL, 2, dnsRcodeSuccess},
|
|
|
|
{"8.8.4.4:53", "com.", dnsTypeALL, 4, dnsRcodeSuccess},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDNSTransportFallback(t *testing.T) {
|
2013-08-13 10:44:12 -06:00
|
|
|
if testing.Short() || !*testExternal {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Skip("avoid external network")
|
2013-08-13 10:44:12 -06:00
|
|
|
}
|
2014-08-05 18:58:47 -06:00
|
|
|
|
|
|
|
for _, tt := range dnsTransportFallbackTests {
|
|
|
|
timeout := time.Duration(tt.timeout) * time.Second
|
|
|
|
msg, err := exchange(tt.server, tt.name, tt.qtype, timeout)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch msg.rcode {
|
|
|
|
case tt.rcode, dnsRcodeServerFailure:
|
|
|
|
default:
|
|
|
|
t.Errorf("got %v from %v; want %v", msg.rcode, tt.server, tt.rcode)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// See RFC 6761 for further information about the reserved, pseudo
|
|
|
|
// domain names.
|
|
|
|
var specialDomainNameTests = []struct {
|
|
|
|
name string
|
|
|
|
qtype uint16
|
|
|
|
rcode int
|
|
|
|
}{
|
2015-01-14 22:25:26 -07:00
|
|
|
// Name resolution APIs and libraries should not recognize the
|
2014-08-05 18:58:47 -06:00
|
|
|
// followings as special.
|
|
|
|
{"1.0.168.192.in-addr.arpa.", dnsTypePTR, dnsRcodeNameError},
|
|
|
|
{"test.", dnsTypeALL, dnsRcodeNameError},
|
|
|
|
{"example.com.", dnsTypeALL, dnsRcodeSuccess},
|
|
|
|
|
2015-01-14 22:25:26 -07:00
|
|
|
// Name resolution APIs and libraries should recognize the
|
2014-08-05 18:58:47 -06:00
|
|
|
// followings as special and should not send any queries.
|
|
|
|
// Though, we test those names here for verifying nagative
|
|
|
|
// answers at DNS query-response interaction level.
|
|
|
|
{"localhost.", dnsTypeALL, dnsRcodeNameError},
|
|
|
|
{"invalid.", dnsTypeALL, dnsRcodeNameError},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSpecialDomainName(t *testing.T) {
|
|
|
|
if testing.Short() || !*testExternal {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Skip("avoid external network")
|
2013-08-13 10:44:12 -06:00
|
|
|
}
|
2014-08-05 18:58:47 -06:00
|
|
|
|
|
|
|
server := "8.8.8.8:53"
|
|
|
|
for _, tt := range specialDomainNameTests {
|
|
|
|
msg, err := exchange(server, tt.name, tt.qtype, 0)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch msg.rcode {
|
|
|
|
case tt.rcode, dnsRcodeServerFailure:
|
|
|
|
default:
|
|
|
|
t.Errorf("got %v from %v; want %v", msg.rcode, server, tt.rcode)
|
|
|
|
continue
|
|
|
|
}
|
2013-08-13 10:44:12 -06:00
|
|
|
}
|
|
|
|
}
|
2014-05-14 18:11:00 -06:00
|
|
|
|
|
|
|
type resolvConfTest struct {
|
|
|
|
*testing.T
|
|
|
|
dir string
|
|
|
|
path string
|
|
|
|
started bool
|
|
|
|
quitc chan chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newResolvConfTest(t *testing.T) *resolvConfTest {
|
2015-05-05 19:41:01 -06:00
|
|
|
dir, err := ioutil.TempDir("", "go-resolvconftest")
|
2014-05-14 18:11:00 -06:00
|
|
|
if err != nil {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Fatal(err)
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Disable the default loadConfig
|
|
|
|
onceLoadConfig.Do(func() {})
|
|
|
|
|
|
|
|
r := &resolvConfTest{
|
|
|
|
T: t,
|
|
|
|
dir: dir,
|
|
|
|
path: path.Join(dir, "resolv.conf"),
|
|
|
|
quitc: make(chan chan struct{}),
|
|
|
|
}
|
|
|
|
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *resolvConfTest) Start() {
|
|
|
|
loadConfig(r.path, 100*time.Millisecond, r.quitc)
|
|
|
|
r.started = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *resolvConfTest) SetConf(s string) {
|
|
|
|
// Make sure the file mtime will be different once we're done here,
|
|
|
|
// even on systems with coarse (1s) mtime resolution.
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
|
|
|
|
f, err := os.OpenFile(r.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
|
|
|
if err != nil {
|
|
|
|
r.Fatalf("failed to create temp file %s: %v", r.path, err)
|
|
|
|
}
|
|
|
|
if _, err := io.WriteString(f, s); err != nil {
|
|
|
|
f.Close()
|
|
|
|
r.Fatalf("failed to write temp file: %v", err)
|
|
|
|
}
|
|
|
|
f.Close()
|
|
|
|
|
|
|
|
if r.started {
|
|
|
|
cfg.ch <- struct{}{} // fill buffer
|
|
|
|
cfg.ch <- struct{}{} // wait for reload to begin
|
|
|
|
cfg.ch <- struct{}{} // wait for reload to complete
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *resolvConfTest) WantServers(want []string) {
|
|
|
|
cfg.mu.RLock()
|
|
|
|
defer cfg.mu.RUnlock()
|
|
|
|
if got := cfg.dnsConfig.servers; !reflect.DeepEqual(got, want) {
|
2015-04-30 21:38:42 -06:00
|
|
|
r.Fatalf("unexpected dns server loaded, got %v want %v", got, want)
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *resolvConfTest) Close() {
|
|
|
|
resp := make(chan struct{})
|
|
|
|
r.quitc <- resp
|
|
|
|
<-resp
|
|
|
|
if err := os.RemoveAll(r.dir); err != nil {
|
|
|
|
r.Logf("failed to remove temp dir %s: %v", r.dir, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReloadResolvConfFail(t *testing.T) {
|
|
|
|
if testing.Short() || !*testExternal {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Skip("avoid external network")
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
r := newResolvConfTest(t)
|
|
|
|
defer r.Close()
|
|
|
|
|
|
|
|
r.Start()
|
|
|
|
r.SetConf("nameserver 8.8.8.8")
|
2015-04-25 18:50:21 -06:00
|
|
|
|
2014-05-14 18:11:00 -06:00
|
|
|
if _, err := goLookupIP("golang.org"); err != nil {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Fatal(err)
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
2015-04-25 18:50:21 -06:00
|
|
|
// Using an empty resolv.conf should use localhost as servers
|
2014-05-14 18:11:00 -06:00
|
|
|
r.SetConf("")
|
2015-04-25 18:50:21 -06:00
|
|
|
|
|
|
|
if len(cfg.dnsConfig.servers) != len(defaultNS) {
|
|
|
|
t.Fatalf("goLookupIP(missing; good; bad) failed: servers=%v, want: %v", cfg.dnsConfig.servers, defaultNS)
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
2015-04-25 18:50:21 -06:00
|
|
|
|
|
|
|
for i := range cfg.dnsConfig.servers {
|
|
|
|
if cfg.dnsConfig.servers[i] != defaultNS[i] {
|
|
|
|
t.Fatalf("goLookupIP(missing; good; bad) failed: servers=%v, want: %v", cfg.dnsConfig.servers, defaultNS)
|
|
|
|
}
|
|
|
|
}
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestReloadResolvConfChange(t *testing.T) {
|
|
|
|
if testing.Short() || !*testExternal {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Skip("avoid external network")
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
r := newResolvConfTest(t)
|
|
|
|
defer r.Close()
|
|
|
|
|
|
|
|
r.Start()
|
2015-04-25 18:50:21 -06:00
|
|
|
r.SetConf("nameserver 8.8.8.8")
|
2014-05-14 18:11:00 -06:00
|
|
|
|
|
|
|
if _, err := goLookupIP("golang.org"); err != nil {
|
2015-04-30 21:38:42 -06:00
|
|
|
t.Fatal(err)
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
2014-09-03 19:00:30 -06:00
|
|
|
r.WantServers([]string{"8.8.8.8"})
|
2014-05-14 18:11:00 -06:00
|
|
|
|
2015-04-25 18:50:21 -06:00
|
|
|
// Using an empty resolv.conf should use localhost as servers
|
2014-05-14 18:11:00 -06:00
|
|
|
r.SetConf("")
|
2015-04-25 18:50:21 -06:00
|
|
|
|
|
|
|
if len(cfg.dnsConfig.servers) != len(defaultNS) {
|
|
|
|
t.Fatalf("goLookupIP(missing; good; bad) failed: servers=%v, want: %v", cfg.dnsConfig.servers, defaultNS)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range cfg.dnsConfig.servers {
|
|
|
|
if cfg.dnsConfig.servers[i] != defaultNS[i] {
|
|
|
|
t.Fatalf("goLookupIP(missing; good; bad) failed: servers=%v, want: %v", cfg.dnsConfig.servers, defaultNS)
|
|
|
|
}
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// A new good config should get picked up
|
|
|
|
r.SetConf("nameserver 8.8.4.4")
|
2014-09-03 19:00:30 -06:00
|
|
|
r.WantServers([]string{"8.8.4.4"})
|
2014-05-14 18:11:00 -06:00
|
|
|
}
|
2014-08-29 16:50:50 -06:00
|
|
|
|
2014-08-29 22:12:28 -06:00
|
|
|
func BenchmarkGoLookupIP(b *testing.B) {
|
2015-05-13 18:25:24 -06:00
|
|
|
testHookUninstaller.Do(uninstallTestHooks)
|
net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
/go/src/net/timeout_test.go:247 +0xc9
(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2015-02-28 20:27:01 -07:00
|
|
|
|
2014-08-29 22:12:28 -06:00
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
goLookupIP("www.example.com")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-29 16:50:50 -06:00
|
|
|
func BenchmarkGoLookupIPNoSuchHost(b *testing.B) {
|
2015-05-13 18:25:24 -06:00
|
|
|
testHookUninstaller.Do(uninstallTestHooks)
|
net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
/go/src/net/timeout_test.go:247 +0xc9
(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2015-02-28 20:27:01 -07:00
|
|
|
|
2014-08-29 16:50:50 -06:00
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
goLookupIP("some.nonexistent")
|
|
|
|
}
|
|
|
|
}
|
2014-08-29 22:12:28 -06:00
|
|
|
|
|
|
|
func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
|
2015-05-13 18:25:24 -06:00
|
|
|
testHookUninstaller.Do(uninstallTestHooks)
|
net: add socket system call hooks for testing
This change adds socket system call hooks to existing test cases for
simulating a bit complicated network conditions to help making timeout
and dual IP stack test cases work more properly in followup changes.
Also test cases print debugging information in non-short mode like the
following:
Leaked goroutines:
net.TestWriteTimeout.func2(0xc20802a5a0, 0xc20801d000, 0x1000, 0x1000, 0xc2081d2ae0)
/go/src/net/timeout_test.go:170 +0x98
created by net.TestWriteTimeout
/go/src/net/timeout_test.go:173 +0x745
net.runDatagramPacketConnServer(0xc2080730e0, 0x2bd270, 0x3, 0x2c1770, 0xb, 0xc2081d2ba0, 0xc2081d2c00)
/go/src/net/server_test.go:398 +0x667
created by net.TestTimeoutUDP
/go/src/net/timeout_test.go:247 +0xc9
(snip)
Leaked sockets:
3: {Cookie:615726511685632 Err:<nil> SocketErr:0}
5: {Cookie:7934075906097152 Err:<nil> SocketErr:0}
Socket statistical information:
{Family:1 Type:805306370 Protocol:0 Opened:17 Accepted:0 Connected:5 Closed:17}
{Family:2 Type:805306369 Protocol:0 Opened:450 Accepted:234 Connected:279 Closed:636}
{Family:1 Type:805306369 Protocol:0 Opened:11 Accepted:5 Connected:5 Closed:16}
{Family:28 Type:805306369 Protocol:0 Opened:95 Accepted:22 Connected:16 Closed:116}
{Family:2 Type:805306370 Protocol:0 Opened:84 Accepted:0 Connected:34 Closed:83}
{Family:28 Type:805306370 Protocol:0 Opened:52 Accepted:0 Connected:4 Closed:52}
Change-Id: I0e84be59a0699bc31245c78e2249423459b8cdda
Reviewed-on: https://go-review.googlesource.com/6390
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2015-02-28 20:27:01 -07:00
|
|
|
|
2014-08-29 22:12:28 -06:00
|
|
|
onceLoadConfig.Do(loadDefaultConfig)
|
2015-04-25 18:50:21 -06:00
|
|
|
|
2014-08-29 22:12:28 -06:00
|
|
|
// This looks ugly but it's safe as long as benchmarks are run
|
|
|
|
// sequentially in package testing.
|
|
|
|
orig := cfg.dnsConfig
|
|
|
|
cfg.dnsConfig.servers = append([]string{"203.0.113.254"}, cfg.dnsConfig.servers...) // use TEST-NET-3 block, see RFC 5737
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
goLookupIP("www.example.com")
|
|
|
|
}
|
|
|
|
cfg.dnsConfig = orig
|
|
|
|
}
|