rsc.io/go@v0.0.0-20150416155037-e040fd465409/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 "fmt" 9 "strings" 10 "testing" 11 "time" 12 ) 13 14 func lookupLocalhost(fn func(string) ([]IPAddr, error), host string) ([]IPAddr, error) { 15 switch host { 16 case "localhost": 17 return []IPAddr{ 18 {IP: IPv4(127, 0, 0, 1)}, 19 {IP: IPv6loopback}, 20 }, nil 21 default: 22 return fn(host) 23 } 24 } 25 26 var lookupGoogleSRVTests = []struct { 27 service, proto, name string 28 cname, target string 29 }{ 30 { 31 "xmpp-server", "tcp", "google.com", 32 ".google.com", ".google.com", 33 }, 34 { 35 "", "", "_xmpp-server._tcp.google.com", // non-standard back door 36 ".google.com", ".google.com", 37 }, 38 } 39 40 func TestLookupGoogleSRV(t *testing.T) { 41 if testing.Short() || !*testExternal { 42 t.Skip("skipping test to avoid external network") 43 } 44 45 for _, tt := range lookupGoogleSRVTests { 46 cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name) 47 if err != nil { 48 t.Fatal(err) 49 } 50 if len(srvs) == 0 { 51 t.Error("got no record") 52 } 53 if !strings.Contains(cname, tt.cname) { 54 t.Errorf("got %q; want %q", cname, tt.cname) 55 } 56 for _, srv := range srvs { 57 if !strings.Contains(srv.Target, tt.target) { 58 t.Errorf("got %v; want a record containing %q", srv, tt.target) 59 } 60 } 61 } 62 } 63 64 func TestLookupGmailMX(t *testing.T) { 65 if testing.Short() || !*testExternal { 66 t.Skip("skipping test to avoid external network") 67 } 68 69 mxs, err := LookupMX("gmail.com") 70 if err != nil { 71 t.Fatal(err) 72 } 73 if len(mxs) == 0 { 74 t.Error("got no record") 75 } 76 for _, mx := range mxs { 77 if !strings.Contains(mx.Host, ".google.com") { 78 t.Errorf("got %v; want a record containing .google.com.", mx) 79 } 80 } 81 } 82 83 func TestLookupGmailNS(t *testing.T) { 84 if testing.Short() || !*testExternal { 85 t.Skip("skipping test to avoid external network") 86 } 87 88 nss, err := LookupNS("gmail.com") 89 if err != nil { 90 t.Fatal(err) 91 } 92 if len(nss) == 0 { 93 t.Error("got no record") 94 } 95 for _, ns := range nss { 96 if !strings.Contains(ns.Host, ".google.com") { 97 t.Errorf("got %v; want a record containing .google.com.", ns) 98 } 99 } 100 } 101 102 func TestLookupGmailTXT(t *testing.T) { 103 if testing.Short() || !*testExternal { 104 t.Skip("skipping test to avoid external network") 105 } 106 107 txts, err := LookupTXT("gmail.com") 108 if err != nil { 109 t.Fatal(err) 110 } 111 if len(txts) == 0 { 112 t.Error("got no record") 113 } 114 for _, txt := range txts { 115 if !strings.Contains(txt, "spf") { 116 t.Errorf("got %q; want a spf record", txt) 117 } 118 } 119 } 120 121 var lookupGooglePublicDNSAddrs = []struct { 122 addr string 123 name string 124 }{ 125 {"8.8.8.8", ".google.com."}, 126 {"8.8.4.4", ".google.com."}, 127 {"2001:4860:4860::8888", ".google.com."}, 128 {"2001:4860:4860::8844", ".google.com."}, 129 } 130 131 func TestLookupGooglePublicDNSAddr(t *testing.T) { 132 if testing.Short() || !*testExternal { 133 t.Skip("skipping test to avoid external network") 134 } 135 136 for _, tt := range lookupGooglePublicDNSAddrs { 137 names, err := LookupAddr(tt.addr) 138 if err != nil { 139 t.Fatal(err) 140 } 141 if len(names) == 0 { 142 t.Error("got no record") 143 } 144 for _, name := range names { 145 if !strings.HasSuffix(name, tt.name) { 146 t.Errorf("got %q; want a record containing %q", name, tt.name) 147 } 148 } 149 } 150 } 151 152 func TestLookupIANACNAME(t *testing.T) { 153 if testing.Short() || !*testExternal { 154 t.Skip("skipping test to avoid external network") 155 } 156 157 cname, err := LookupCNAME("www.iana.org") 158 if err != nil { 159 t.Fatal(err) 160 } 161 if !strings.HasSuffix(cname, ".icann.org.") { 162 t.Errorf("got %q; want a record containing .icann.org.", cname) 163 } 164 } 165 166 func TestLookupGoogleHost(t *testing.T) { 167 if testing.Short() || !*testExternal { 168 t.Skip("skipping test to avoid external network") 169 } 170 171 addrs, err := LookupHost("google.com") 172 if err != nil { 173 t.Fatal(err) 174 } 175 if len(addrs) == 0 { 176 t.Error("got no record") 177 } 178 for _, addr := range addrs { 179 if ParseIP(addr) == nil { 180 t.Errorf("got %q; want a literal ip address", addr) 181 } 182 } 183 } 184 185 func TestLookupGoogleIP(t *testing.T) { 186 if testing.Short() || !*testExternal { 187 t.Skip("skipping test to avoid external network") 188 } 189 190 ips, err := LookupIP("google.com") 191 if err != nil { 192 t.Fatal(err) 193 } 194 if len(ips) == 0 { 195 t.Error("got no record") 196 } 197 for _, ip := range ips { 198 if ip.To4() == nil && ip.To16() == nil { 199 t.Errorf("got %v; want an ip address", ip) 200 } 201 } 202 } 203 204 var revAddrTests = []struct { 205 Addr string 206 Reverse string 207 ErrPrefix string 208 }{ 209 {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""}, 210 {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""}, 211 {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""}, 212 {"::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.", ""}, 213 {"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.", ""}, 214 {"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.", ""}, 215 {"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.", ""}, 216 {"1.2.3", "", "unrecognized address"}, 217 {"1.2.3.4.5", "", "unrecognized address"}, 218 {"1234:567:bcbca::89a:bcde", "", "unrecognized address"}, 219 {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"}, 220 } 221 222 func TestReverseAddress(t *testing.T) { 223 for i, tt := range revAddrTests { 224 a, err := reverseaddr(tt.Addr) 225 if len(tt.ErrPrefix) > 0 && err == nil { 226 t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix) 227 continue 228 } 229 if len(tt.ErrPrefix) == 0 && err != nil { 230 t.Errorf("#%d: expected <nil>, got %q (error)", i, err) 231 } 232 if err != nil && err.(*DNSError).Err != tt.ErrPrefix { 233 t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err) 234 } 235 if a != tt.Reverse { 236 t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a) 237 } 238 } 239 } 240 241 func TestLookupIPDeadline(t *testing.T) { 242 if !*testDNSFlood { 243 t.Skip("test disabled; use -dnsflood to enable") 244 } 245 246 const N = 5000 247 const timeout = 3 * time.Second 248 c := make(chan error, 2*N) 249 for i := 0; i < N; i++ { 250 name := fmt.Sprintf("%d.net-test.golang.org", i) 251 go func() { 252 _, err := lookupIPDeadline(name, time.Now().Add(timeout/2)) 253 c <- err 254 }() 255 go func() { 256 _, err := lookupIPDeadline(name, time.Now().Add(timeout)) 257 c <- err 258 }() 259 } 260 qstats := struct { 261 succeeded, failed int 262 timeout, temporary, other int 263 unknown int 264 }{} 265 deadline := time.After(timeout + time.Second) 266 for i := 0; i < 2*N; i++ { 267 select { 268 case <-deadline: 269 t.Fatal("deadline exceeded") 270 case err := <-c: 271 switch err := err.(type) { 272 case nil: 273 qstats.succeeded++ 274 case Error: 275 qstats.failed++ 276 if err.Timeout() { 277 qstats.timeout++ 278 } 279 if err.Temporary() { 280 qstats.temporary++ 281 } 282 if !err.Timeout() && !err.Temporary() { 283 qstats.other++ 284 } 285 default: 286 qstats.failed++ 287 qstats.unknown++ 288 } 289 } 290 } 291 292 // A high volume of DNS queries for sub-domain of golang.org 293 // would be coordinated by authoritative or recursive server, 294 // or stub resolver which implements query-response rate 295 // limitation, so we can expect some query successes and more 296 // failures including timeout, temporary and other here. 297 // As a rule, unknown must not be shown but it might possibly 298 // happen due to issue 4856 for now. 299 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) 300 }