github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libgo/go/net/dnsclient_unix_test.go (about) 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. 4 5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "io" 11 "io/ioutil" 12 "os" 13 "path" 14 "reflect" 15 "testing" 16 "time" 17 ) 18 19 var dnsTransportFallbackTests = []struct { 20 server string 21 name string 22 qtype uint16 23 timeout int 24 rcode int 25 }{ 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}, 30 } 31 32 func TestDNSTransportFallback(t *testing.T) { 33 if testing.Short() || !*testExternal { 34 t.Skip("skipping test to avoid external network") 35 } 36 37 for _, tt := range dnsTransportFallbackTests { 38 timeout := time.Duration(tt.timeout) * time.Second 39 msg, err := exchange(tt.server, tt.name, tt.qtype, timeout) 40 if err != nil { 41 t.Error(err) 42 continue 43 } 44 switch msg.rcode { 45 case tt.rcode, dnsRcodeServerFailure: 46 default: 47 t.Errorf("got %v from %v; want %v", msg.rcode, tt.server, tt.rcode) 48 continue 49 } 50 } 51 } 52 53 // See RFC 6761 for further information about the reserved, pseudo 54 // domain names. 55 var specialDomainNameTests = []struct { 56 name string 57 qtype uint16 58 rcode int 59 }{ 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}, 65 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}, 72 } 73 74 func TestSpecialDomainName(t *testing.T) { 75 if testing.Short() || !*testExternal { 76 t.Skip("skipping test to avoid external network") 77 } 78 79 server := "8.8.8.8:53" 80 for _, tt := range specialDomainNameTests { 81 msg, err := exchange(server, tt.name, tt.qtype, 0) 82 if err != nil { 83 t.Error(err) 84 continue 85 } 86 switch msg.rcode { 87 case tt.rcode, dnsRcodeServerFailure: 88 default: 89 t.Errorf("got %v from %v; want %v", msg.rcode, server, tt.rcode) 90 continue 91 } 92 } 93 } 94 95 type resolvConfTest struct { 96 *testing.T 97 dir string 98 path string 99 started bool 100 quitc chan chan struct{} 101 } 102 103 func newResolvConfTest(t *testing.T) *resolvConfTest { 104 dir, err := ioutil.TempDir("", "resolvConfTest") 105 if err != nil { 106 t.Fatalf("could not create temp dir: %v", err) 107 } 108 109 // Disable the default loadConfig 110 onceLoadConfig.Do(func() {}) 111 112 r := &resolvConfTest{ 113 T: t, 114 dir: dir, 115 path: path.Join(dir, "resolv.conf"), 116 quitc: make(chan chan struct{}), 117 } 118 119 return r 120 } 121 122 func (r *resolvConfTest) Start() { 123 loadConfig(r.path, 100*time.Millisecond, r.quitc) 124 r.started = true 125 } 126 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) 131 132 f, err := os.OpenFile(r.path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) 133 if err != nil { 134 r.Fatalf("failed to create temp file %s: %v", r.path, err) 135 } 136 if _, err := io.WriteString(f, s); err != nil { 137 f.Close() 138 r.Fatalf("failed to write temp file: %v", err) 139 } 140 f.Close() 141 142 if r.started { 143 cfg.ch <- struct{}{} // fill buffer 144 cfg.ch <- struct{}{} // wait for reload to begin 145 cfg.ch <- struct{}{} // wait for reload to complete 146 } 147 } 148 149 func (r *resolvConfTest) WantServers(want []string) { 150 cfg.mu.RLock() 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) 154 } 155 } 156 157 func (r *resolvConfTest) Close() { 158 resp := make(chan struct{}) 159 r.quitc <- resp 160 <-resp 161 if err := os.RemoveAll(r.dir); err != nil { 162 r.Logf("failed to remove temp dir %s: %v", r.dir, err) 163 } 164 } 165 166 func TestReloadResolvConfFail(t *testing.T) { 167 if testing.Short() || !*testExternal { 168 t.Skip("skipping test to avoid external network") 169 } 170 171 r := newResolvConfTest(t) 172 defer r.Close() 173 174 // resolv.conf.tmp does not exist yet 175 r.Start() 176 if _, err := goLookupIP("golang.org"); err == nil { 177 t.Fatal("goLookupIP(missing) succeeded") 178 } 179 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) 183 } 184 185 // Using a bad resolv.conf while we had a good 186 // one before should not update the config 187 r.SetConf("") 188 if _, err := goLookupIP("golang.org"); err != nil { 189 t.Fatalf("goLookupIP(missing; good; bad) failed: %v", err) 190 } 191 } 192 193 func TestReloadResolvConfChange(t *testing.T) { 194 if testing.Short() || !*testExternal { 195 t.Skip("skipping test to avoid external network") 196 } 197 198 r := newResolvConfTest(t) 199 defer r.Close() 200 201 r.SetConf("nameserver 8.8.8.8") 202 r.Start() 203 204 if _, err := goLookupIP("golang.org"); err != nil { 205 t.Fatalf("goLookupIP(good) failed: %v", err) 206 } 207 r.WantServers([]string{"8.8.8.8"}) 208 209 // Using a bad resolv.conf when we had a good one 210 // before should not update the config 211 r.SetConf("") 212 if _, err := goLookupIP("golang.org"); err != nil { 213 t.Fatalf("goLookupIP(good; bad) failed: %v", err) 214 } 215 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"}) 219 } 220 221 func BenchmarkGoLookupIP(b *testing.B) { 222 for i := 0; i < b.N; i++ { 223 goLookupIP("www.example.com") 224 } 225 } 226 227 func BenchmarkGoLookupIPNoSuchHost(b *testing.B) { 228 for i := 0; i < b.N; i++ { 229 goLookupIP("some.nonexistent") 230 } 231 } 232 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) 237 } 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") 244 } 245 cfg.dnsConfig = orig 246 }