1 // Copyright 2013 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 darwin dragonfly freebsd linux netbsd openbsd solaris
19 var dnsTransportFallbackTests
= []struct {
26 // Querying "com." with qtype=255 usually makes an answer
27 // which requires more than 512 bytes.
28 {"8.8.8.8:53", "com.", dnsTypeALL
, 2, dnsRcodeSuccess
},
29 {"8.8.4.4:53", "com.", dnsTypeALL
, 4, dnsRcodeSuccess
},
32 func TestDNSTransportFallback(t
*testing
.T
) {
33 if testing
.Short() ||
!*testExternal
{
34 t
.Skip("skipping test to avoid external network")
37 for _
, tt
:= range dnsTransportFallbackTests
{
38 timeout
:= time
.Duration(tt
.timeout
) * time
.Second
39 msg
, err
:= exchange(tt
.server
, tt
.name
, tt
.qtype
, timeout
)
45 case tt
.rcode
, dnsRcodeServerFailure
:
47 t
.Errorf("got %v from %v; want %v", msg
.rcode
, tt
.server
, tt
.rcode
)
53 // See RFC 6761 for further information about the reserved, pseudo
55 var specialDomainNameTests
= []struct {
60 // Name resoltion APIs and libraries should not recongnize the
61 // followings as special.
62 {"1.0.168.192.in-addr.arpa.", dnsTypePTR
, dnsRcodeNameError
},
63 {"test.", dnsTypeALL
, dnsRcodeNameError
},
64 {"example.com.", dnsTypeALL
, dnsRcodeSuccess
},
66 // Name resoltion APIs and libraries should recongnize the
67 // followings as special and should not send any queries.
68 // Though, we test those names here for verifying nagative
69 // answers at DNS query-response interaction level.
70 {"localhost.", dnsTypeALL
, dnsRcodeNameError
},
71 {"invalid.", dnsTypeALL
, dnsRcodeNameError
},
74 func TestSpecialDomainName(t
*testing
.T
) {
75 if testing
.Short() ||
!*testExternal
{
76 t
.Skip("skipping test to avoid external network")
79 server
:= "8.8.8.8:53"
80 for _
, tt
:= range specialDomainNameTests
{
81 msg
, err
:= exchange(server
, tt
.name
, tt
.qtype
, 0)
87 case tt
.rcode
, dnsRcodeServerFailure
:
89 t
.Errorf("got %v from %v; want %v", msg
.rcode
, server
, tt
.rcode
)
95 type resolvConfTest
struct {
100 quitc
chan chan struct{}
103 func newResolvConfTest(t
*testing
.T
) *resolvConfTest
{
104 dir
, err
:= ioutil
.TempDir("", "resolvConfTest")
106 t
.Fatalf("could not create temp dir: %v", err
)
109 // Disable the default loadConfig
110 onceLoadConfig
.Do(func() {})
112 r
:= &resolvConfTest
{
115 path
: path
.Join(dir
, "resolv.conf"),
116 quitc
: make(chan chan struct{}),
122 func (r
*resolvConfTest
) Start() {
123 loadConfig(r
.path
, 100*time
.Millisecond
, r
.quitc
)
127 func (r
*resolvConfTest
) SetConf(s
string) {
128 // Make sure the file mtime will be different once we're done here,
129 // even on systems with coarse (1s) mtime resolution.
130 time
.Sleep(time
.Second
)
132 f
, err
:= os
.OpenFile(r
.path
, os
.O_CREATE|os
.O_TRUNC|os
.O_WRONLY
, 0600)
134 r
.Fatalf("failed to create temp file %s: %v", r
.path
, err
)
136 if _
, err
:= io
.WriteString(f
, s
); err
!= nil {
138 r
.Fatalf("failed to write temp file: %v", err
)
143 cfg
.ch
<- struct{}{} // fill buffer
144 cfg
.ch
<- struct{}{} // wait for reload to begin
145 cfg
.ch
<- struct{}{} // wait for reload to complete
149 func (r
*resolvConfTest
) WantServers(want
[]string) {
151 defer cfg
.mu
.RUnlock()
152 if got
:= cfg
.dnsConfig
.servers
; !reflect
.DeepEqual(got
, want
) {
153 r
.Fatalf("Unexpected dns server loaded, got %v want %v", got
, want
)
157 func (r
*resolvConfTest
) Close() {
158 resp
:= make(chan struct{})
161 if err
:= os
.RemoveAll(r
.dir
); err
!= nil {
162 r
.Logf("failed to remove temp dir %s: %v", r
.dir
, err
)
166 func TestReloadResolvConfFail(t
*testing
.T
) {
167 if testing
.Short() ||
!*testExternal
{
168 t
.Skip("skipping test to avoid external network")
171 r
:= newResolvConfTest(t
)
174 // resolv.conf.tmp does not exist yet
176 if _
, err
:= goLookupIP("golang.org"); err
== nil {
177 t
.Fatal("goLookupIP(missing) succeeded")
180 r
.SetConf("nameserver 8.8.8.8")
181 if _
, err
:= goLookupIP("golang.org"); err
!= nil {
182 t
.Fatalf("goLookupIP(missing; good) failed: %v", err
)
185 // Using a bad resolv.conf while we had a good
186 // one before should not update the config
188 if _
, err
:= goLookupIP("golang.org"); err
!= nil {
189 t
.Fatalf("goLookupIP(missing; good; bad) failed: %v", err
)
193 func TestReloadResolvConfChange(t
*testing
.T
) {
194 if testing
.Short() ||
!*testExternal
{
195 t
.Skip("skipping test to avoid external network")
198 r
:= newResolvConfTest(t
)
201 r
.SetConf("nameserver 8.8.8.8")
204 if _
, err
:= goLookupIP("golang.org"); err
!= nil {
205 t
.Fatalf("goLookupIP(good) failed: %v", err
)
207 r
.WantServers([]string{"8.8.8.8"})
209 // Using a bad resolv.conf when we had a good one
210 // before should not update the config
212 if _
, err
:= goLookupIP("golang.org"); err
!= nil {
213 t
.Fatalf("goLookupIP(good; bad) failed: %v", err
)
216 // A new good config should get picked up
217 r
.SetConf("nameserver 8.8.4.4")
218 r
.WantServers([]string{"8.8.4.4"})
221 func BenchmarkGoLookupIP(b
*testing
.B
) {
222 for i
:= 0; i
< b
.N
; i
++ {
223 goLookupIP("www.example.com")
227 func BenchmarkGoLookupIPNoSuchHost(b
*testing
.B
) {
228 for i
:= 0; i
< b
.N
; i
++ {
229 goLookupIP("some.nonexistent")
233 func BenchmarkGoLookupIPWithBrokenNameServer(b
*testing
.B
) {
234 onceLoadConfig
.Do(loadDefaultConfig
)
235 if cfg
.dnserr
!= nil || cfg
.dnsConfig
== nil {
236 b
.Fatalf("loadConfig failed: %v", cfg
.dnserr
)
238 // This looks ugly but it's safe as long as benchmarks are run
239 // sequentially in package testing.
240 orig
:= cfg
.dnsConfig
241 cfg
.dnsConfig
.servers
= append([]string{"203.0.113.254"}, cfg
.dnsConfig
.servers
...) // use TEST-NET-3 block, see RFC 5737
242 for i
:= 0; i
< b
.N
; i
++ {
243 goLookupIP("www.example.com")