lookup_test.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  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. //go:build !js
  5. package net
  6. import (
  7. "bytes"
  8. "context"
  9. "fmt"
  10. "internal/testenv"
  11. "reflect"
  12. "runtime"
  13. "sort"
  14. "strings"
  15. "sync"
  16. "sync/atomic"
  17. "testing"
  18. "time"
  19. )
  20. func hasSuffixFold(s, suffix string) bool {
  21. return strings.HasSuffix(strings.ToLower(s), strings.ToLower(suffix))
  22. }
  23. func lookupLocalhost(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
  24. switch host {
  25. case "localhost":
  26. return []IPAddr{
  27. {IP: IPv4(127, 0, 0, 1)},
  28. {IP: IPv6loopback},
  29. }, nil
  30. default:
  31. return fn(ctx, network, host)
  32. }
  33. }
  34. // The Lookup APIs use various sources such as local database, DNS or
  35. // mDNS, and may use platform-dependent DNS stub resolver if possible.
  36. // The APIs accept any of forms for a query; host name in various
  37. // encodings, UTF-8 encoded net name, domain name, FQDN or absolute
  38. // FQDN, but the result would be one of the forms and it depends on
  39. // the circumstances.
  40. var lookupGoogleSRVTests = []struct {
  41. service, proto, name string
  42. cname, target string
  43. }{
  44. {
  45. "xmpp-server", "tcp", "google.com",
  46. "google.com.", "google.com.",
  47. },
  48. {
  49. "xmpp-server", "tcp", "google.com.",
  50. "google.com.", "google.com.",
  51. },
  52. // non-standard back door
  53. {
  54. "", "", "_xmpp-server._tcp.google.com",
  55. "google.com.", "google.com.",
  56. },
  57. {
  58. "", "", "_xmpp-server._tcp.google.com.",
  59. "google.com.", "google.com.",
  60. },
  61. }
  62. var backoffDuration = [...]time.Duration{time.Second, 5 * time.Second, 30 * time.Second}
  63. func TestLookupGoogleSRV(t *testing.T) {
  64. t.Parallel()
  65. mustHaveExternalNetwork(t)
  66. if iOS() {
  67. t.Skip("no resolv.conf on iOS")
  68. }
  69. if !supportsIPv4() || !*testIPv4 {
  70. t.Skip("IPv4 is required")
  71. }
  72. attempts := 0
  73. for i := 0; i < len(lookupGoogleSRVTests); i++ {
  74. tt := lookupGoogleSRVTests[i]
  75. cname, srvs, err := LookupSRV(tt.service, tt.proto, tt.name)
  76. if err != nil {
  77. testenv.SkipFlakyNet(t)
  78. if attempts < len(backoffDuration) {
  79. dur := backoffDuration[attempts]
  80. t.Logf("backoff %v after failure %v\n", dur, err)
  81. time.Sleep(dur)
  82. attempts++
  83. i--
  84. continue
  85. }
  86. t.Fatal(err)
  87. }
  88. if len(srvs) == 0 {
  89. t.Error("got no record")
  90. }
  91. if !hasSuffixFold(cname, tt.cname) {
  92. t.Errorf("got %s; want %s", cname, tt.cname)
  93. }
  94. for _, srv := range srvs {
  95. if !hasSuffixFold(srv.Target, tt.target) {
  96. t.Errorf("got %v; want a record containing %s", srv, tt.target)
  97. }
  98. }
  99. }
  100. }
  101. var lookupGmailMXTests = []struct {
  102. name, host string
  103. }{
  104. {"gmail.com", "google.com."},
  105. {"gmail.com.", "google.com."},
  106. }
  107. func TestLookupGmailMX(t *testing.T) {
  108. t.Parallel()
  109. mustHaveExternalNetwork(t)
  110. if iOS() {
  111. t.Skip("no resolv.conf on iOS")
  112. }
  113. if !supportsIPv4() || !*testIPv4 {
  114. t.Skip("IPv4 is required")
  115. }
  116. attempts := 0
  117. for i := 0; i < len(lookupGmailMXTests); i++ {
  118. tt := lookupGmailMXTests[i]
  119. mxs, err := LookupMX(tt.name)
  120. if err != nil {
  121. testenv.SkipFlakyNet(t)
  122. if attempts < len(backoffDuration) {
  123. dur := backoffDuration[attempts]
  124. t.Logf("backoff %v after failure %v\n", dur, err)
  125. time.Sleep(dur)
  126. attempts++
  127. i--
  128. continue
  129. }
  130. t.Fatal(err)
  131. }
  132. if len(mxs) == 0 {
  133. t.Error("got no record")
  134. }
  135. for _, mx := range mxs {
  136. if !hasSuffixFold(mx.Host, tt.host) {
  137. t.Errorf("got %v; want a record containing %s", mx, tt.host)
  138. }
  139. }
  140. }
  141. }
  142. var lookupGmailNSTests = []struct {
  143. name, host string
  144. }{
  145. {"gmail.com", "google.com."},
  146. {"gmail.com.", "google.com."},
  147. }
  148. func TestLookupGmailNS(t *testing.T) {
  149. t.Parallel()
  150. mustHaveExternalNetwork(t)
  151. if iOS() {
  152. t.Skip("no resolv.conf on iOS")
  153. }
  154. if !supportsIPv4() || !*testIPv4 {
  155. t.Skip("IPv4 is required")
  156. }
  157. attempts := 0
  158. for i := 0; i < len(lookupGmailNSTests); i++ {
  159. tt := lookupGmailNSTests[i]
  160. nss, err := LookupNS(tt.name)
  161. if err != nil {
  162. testenv.SkipFlakyNet(t)
  163. if attempts < len(backoffDuration) {
  164. dur := backoffDuration[attempts]
  165. t.Logf("backoff %v after failure %v\n", dur, err)
  166. time.Sleep(dur)
  167. attempts++
  168. i--
  169. continue
  170. }
  171. t.Fatal(err)
  172. }
  173. if len(nss) == 0 {
  174. t.Error("got no record")
  175. }
  176. for _, ns := range nss {
  177. if !hasSuffixFold(ns.Host, tt.host) {
  178. t.Errorf("got %v; want a record containing %s", ns, tt.host)
  179. }
  180. }
  181. }
  182. }
  183. var lookupGmailTXTTests = []struct {
  184. name, txt, host string
  185. }{
  186. {"gmail.com", "spf", "google.com"},
  187. {"gmail.com.", "spf", "google.com"},
  188. }
  189. func TestLookupGmailTXT(t *testing.T) {
  190. if runtime.GOOS == "plan9" {
  191. t.Skip("skipping on plan9; see https://golang.org/issue/29722")
  192. }
  193. t.Parallel()
  194. mustHaveExternalNetwork(t)
  195. if iOS() {
  196. t.Skip("no resolv.conf on iOS")
  197. }
  198. if !supportsIPv4() || !*testIPv4 {
  199. t.Skip("IPv4 is required")
  200. }
  201. attempts := 0
  202. for i := 0; i < len(lookupGmailTXTTests); i++ {
  203. tt := lookupGmailTXTTests[i]
  204. txts, err := LookupTXT(tt.name)
  205. if err != nil {
  206. testenv.SkipFlakyNet(t)
  207. if attempts < len(backoffDuration) {
  208. dur := backoffDuration[attempts]
  209. t.Logf("backoff %v after failure %v\n", dur, err)
  210. time.Sleep(dur)
  211. attempts++
  212. i--
  213. continue
  214. }
  215. t.Fatal(err)
  216. }
  217. if len(txts) == 0 {
  218. t.Error("got no record")
  219. }
  220. found := false
  221. for _, txt := range txts {
  222. if strings.Contains(txt, tt.txt) && (strings.HasSuffix(txt, tt.host) || strings.HasSuffix(txt, tt.host+".")) {
  223. found = true
  224. break
  225. }
  226. }
  227. if !found {
  228. t.Errorf("got %v; want a record containing %s, %s", txts, tt.txt, tt.host)
  229. }
  230. }
  231. }
  232. var lookupGooglePublicDNSAddrTests = []string{
  233. "8.8.8.8",
  234. "8.8.4.4",
  235. "2001:4860:4860::8888",
  236. "2001:4860:4860::8844",
  237. }
  238. func TestLookupGooglePublicDNSAddr(t *testing.T) {
  239. mustHaveExternalNetwork(t)
  240. if !supportsIPv4() || !supportsIPv6() || !*testIPv4 || !*testIPv6 {
  241. t.Skip("both IPv4 and IPv6 are required")
  242. }
  243. defer dnsWaitGroup.Wait()
  244. for _, ip := range lookupGooglePublicDNSAddrTests {
  245. names, err := LookupAddr(ip)
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. if len(names) == 0 {
  250. t.Error("got no record")
  251. }
  252. for _, name := range names {
  253. if !hasSuffixFold(name, ".google.com.") && !hasSuffixFold(name, ".google.") {
  254. t.Errorf("got %q; want a record ending in .google.com. or .google.", name)
  255. }
  256. }
  257. }
  258. }
  259. func TestLookupIPv6LinkLocalAddr(t *testing.T) {
  260. if !supportsIPv6() || !*testIPv6 {
  261. t.Skip("IPv6 is required")
  262. }
  263. defer dnsWaitGroup.Wait()
  264. addrs, err := LookupHost("localhost")
  265. if err != nil {
  266. t.Fatal(err)
  267. }
  268. found := false
  269. for _, addr := range addrs {
  270. if addr == "fe80::1%lo0" {
  271. found = true
  272. break
  273. }
  274. }
  275. if !found {
  276. t.Skipf("not supported on %s", runtime.GOOS)
  277. }
  278. if _, err := LookupAddr("fe80::1%lo0"); err != nil {
  279. t.Error(err)
  280. }
  281. }
  282. func TestLookupIPv6LinkLocalAddrWithZone(t *testing.T) {
  283. if !supportsIPv6() || !*testIPv6 {
  284. t.Skip("IPv6 is required")
  285. }
  286. ipaddrs, err := DefaultResolver.LookupIPAddr(context.Background(), "fe80::1%lo0")
  287. if err != nil {
  288. t.Error(err)
  289. }
  290. for _, addr := range ipaddrs {
  291. if e, a := "lo0", addr.Zone; e != a {
  292. t.Errorf("wrong zone: want %q, got %q", e, a)
  293. }
  294. }
  295. addrs, err := DefaultResolver.LookupHost(context.Background(), "fe80::1%lo0")
  296. if err != nil {
  297. t.Error(err)
  298. }
  299. for _, addr := range addrs {
  300. if e, a := "fe80::1%lo0", addr; e != a {
  301. t.Errorf("wrong host: want %q got %q", e, a)
  302. }
  303. }
  304. }
  305. var lookupCNAMETests = []struct {
  306. name, cname string
  307. }{
  308. {"www.iana.org", "icann.org."},
  309. {"www.iana.org.", "icann.org."},
  310. {"www.google.com", "google.com."},
  311. }
  312. func TestLookupCNAME(t *testing.T) {
  313. mustHaveExternalNetwork(t)
  314. testenv.SkipFlakyNet(t)
  315. if !supportsIPv4() || !*testIPv4 {
  316. t.Skip("IPv4 is required")
  317. }
  318. defer dnsWaitGroup.Wait()
  319. attempts := 0
  320. for i := 0; i < len(lookupCNAMETests); i++ {
  321. tt := lookupCNAMETests[i]
  322. cname, err := LookupCNAME(tt.name)
  323. if err != nil {
  324. testenv.SkipFlakyNet(t)
  325. if attempts < len(backoffDuration) {
  326. dur := backoffDuration[attempts]
  327. t.Logf("backoff %v after failure %v\n", dur, err)
  328. time.Sleep(dur)
  329. attempts++
  330. i--
  331. continue
  332. }
  333. t.Fatal(err)
  334. }
  335. if !hasSuffixFold(cname, tt.cname) {
  336. t.Errorf("got %s; want a record containing %s", cname, tt.cname)
  337. }
  338. }
  339. }
  340. var lookupGoogleHostTests = []struct {
  341. name string
  342. }{
  343. {"google.com"},
  344. {"google.com."},
  345. }
  346. func TestLookupGoogleHost(t *testing.T) {
  347. mustHaveExternalNetwork(t)
  348. testenv.SkipFlakyNet(t)
  349. if !supportsIPv4() || !*testIPv4 {
  350. t.Skip("IPv4 is required")
  351. }
  352. defer dnsWaitGroup.Wait()
  353. for _, tt := range lookupGoogleHostTests {
  354. addrs, err := LookupHost(tt.name)
  355. if err != nil {
  356. t.Fatal(err)
  357. }
  358. if len(addrs) == 0 {
  359. t.Error("got no record")
  360. }
  361. for _, addr := range addrs {
  362. if ParseIP(addr) == nil {
  363. t.Errorf("got %q; want a literal IP address", addr)
  364. }
  365. }
  366. }
  367. }
  368. func TestLookupLongTXT(t *testing.T) {
  369. testenv.SkipFlaky(t, 22857)
  370. mustHaveExternalNetwork(t)
  371. defer dnsWaitGroup.Wait()
  372. txts, err := LookupTXT("golang.rsc.io")
  373. if err != nil {
  374. t.Fatal(err)
  375. }
  376. sort.Strings(txts)
  377. want := []string{
  378. strings.Repeat("abcdefghijklmnopqrstuvwxyABCDEFGHJIKLMNOPQRSTUVWXY", 10),
  379. "gophers rule",
  380. }
  381. if !reflect.DeepEqual(txts, want) {
  382. t.Fatalf("LookupTXT golang.rsc.io incorrect\nhave %q\nwant %q", txts, want)
  383. }
  384. }
  385. var lookupGoogleIPTests = []struct {
  386. name string
  387. }{
  388. {"google.com"},
  389. {"google.com."},
  390. }
  391. func TestLookupGoogleIP(t *testing.T) {
  392. mustHaveExternalNetwork(t)
  393. testenv.SkipFlakyNet(t)
  394. if !supportsIPv4() || !*testIPv4 {
  395. t.Skip("IPv4 is required")
  396. }
  397. defer dnsWaitGroup.Wait()
  398. for _, tt := range lookupGoogleIPTests {
  399. ips, err := LookupIP(tt.name)
  400. if err != nil {
  401. t.Fatal(err)
  402. }
  403. if len(ips) == 0 {
  404. t.Error("got no record")
  405. }
  406. for _, ip := range ips {
  407. if ip.To4() == nil && ip.To16() == nil {
  408. t.Errorf("got %v; want an IP address", ip)
  409. }
  410. }
  411. }
  412. }
  413. var revAddrTests = []struct {
  414. Addr string
  415. Reverse string
  416. ErrPrefix string
  417. }{
  418. {"1.2.3.4", "4.3.2.1.in-addr.arpa.", ""},
  419. {"245.110.36.114", "114.36.110.245.in-addr.arpa.", ""},
  420. {"::ffff:12.34.56.78", "78.56.34.12.in-addr.arpa.", ""},
  421. {"::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.", ""},
  422. {"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.", ""},
  423. {"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.", ""},
  424. {"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.", ""},
  425. {"1.2.3", "", "unrecognized address"},
  426. {"1.2.3.4.5", "", "unrecognized address"},
  427. {"1234:567:bcbca::89a:bcde", "", "unrecognized address"},
  428. {"1234:567::bcbc:adad::89a:bcde", "", "unrecognized address"},
  429. }
  430. func TestReverseAddress(t *testing.T) {
  431. defer dnsWaitGroup.Wait()
  432. for i, tt := range revAddrTests {
  433. a, err := reverseaddr(tt.Addr)
  434. if len(tt.ErrPrefix) > 0 && err == nil {
  435. t.Errorf("#%d: expected %q, got <nil> (error)", i, tt.ErrPrefix)
  436. continue
  437. }
  438. if len(tt.ErrPrefix) == 0 && err != nil {
  439. t.Errorf("#%d: expected <nil>, got %q (error)", i, err)
  440. }
  441. if err != nil && err.(*DNSError).Err != tt.ErrPrefix {
  442. t.Errorf("#%d: expected %q, got %q (mismatched error)", i, tt.ErrPrefix, err.(*DNSError).Err)
  443. }
  444. if a != tt.Reverse {
  445. t.Errorf("#%d: expected %q, got %q (reverse address)", i, tt.Reverse, a)
  446. }
  447. }
  448. }
  449. func TestDNSFlood(t *testing.T) {
  450. if !*testDNSFlood {
  451. t.Skip("test disabled; use -dnsflood to enable")
  452. }
  453. defer dnsWaitGroup.Wait()
  454. var N = 5000
  455. if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
  456. // On Darwin this test consumes kernel threads much
  457. // than other platforms for some reason.
  458. // When we monitor the number of allocated Ms by
  459. // observing on runtime.newm calls, we can see that it
  460. // easily reaches the per process ceiling
  461. // kern.num_threads when CGO_ENABLED=1 and
  462. // GODEBUG=netdns=go.
  463. N = 500
  464. }
  465. const timeout = 3 * time.Second
  466. ctxHalfTimeout, cancel := context.WithTimeout(context.Background(), timeout/2)
  467. defer cancel()
  468. ctxTimeout, cancel := context.WithTimeout(context.Background(), timeout)
  469. defer cancel()
  470. c := make(chan error, 2*N)
  471. for i := 0; i < N; i++ {
  472. name := fmt.Sprintf("%d.net-test.golang.org", i)
  473. go func() {
  474. _, err := DefaultResolver.LookupIPAddr(ctxHalfTimeout, name)
  475. c <- err
  476. }()
  477. go func() {
  478. _, err := DefaultResolver.LookupIPAddr(ctxTimeout, name)
  479. c <- err
  480. }()
  481. }
  482. qstats := struct {
  483. succeeded, failed int
  484. timeout, temporary, other int
  485. unknown int
  486. }{}
  487. deadline := time.After(timeout + time.Second)
  488. for i := 0; i < 2*N; i++ {
  489. select {
  490. case <-deadline:
  491. t.Fatal("deadline exceeded")
  492. case err := <-c:
  493. switch err := err.(type) {
  494. case nil:
  495. qstats.succeeded++
  496. case Error:
  497. qstats.failed++
  498. if err.Timeout() {
  499. qstats.timeout++
  500. }
  501. if err.Temporary() {
  502. qstats.temporary++
  503. }
  504. if !err.Timeout() && !err.Temporary() {
  505. qstats.other++
  506. }
  507. default:
  508. qstats.failed++
  509. qstats.unknown++
  510. }
  511. }
  512. }
  513. // A high volume of DNS queries for sub-domain of golang.org
  514. // would be coordinated by authoritative or recursive server,
  515. // or stub resolver which implements query-response rate
  516. // limitation, so we can expect some query successes and more
  517. // failures including timeout, temporary and other here.
  518. // As a rule, unknown must not be shown but it might possibly
  519. // happen due to issue 4856 for now.
  520. 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)
  521. }
  522. func TestLookupDotsWithLocalSource(t *testing.T) {
  523. if !supportsIPv4() || !*testIPv4 {
  524. t.Skip("IPv4 is required")
  525. }
  526. mustHaveExternalNetwork(t)
  527. defer dnsWaitGroup.Wait()
  528. for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
  529. fixup := fn()
  530. if fixup == nil {
  531. continue
  532. }
  533. names, err := LookupAddr("127.0.0.1")
  534. fixup()
  535. if err != nil {
  536. t.Logf("#%d: %v", i, err)
  537. continue
  538. }
  539. mode := "netgo"
  540. if i == 1 {
  541. mode = "netcgo"
  542. }
  543. loop:
  544. for i, name := range names {
  545. if strings.Index(name, ".") == len(name)-1 { // "localhost" not "localhost."
  546. for j := range names {
  547. if j == i {
  548. continue
  549. }
  550. if names[j] == name[:len(name)-1] {
  551. // It's OK if we find the name without the dot,
  552. // as some systems say 127.0.0.1 localhost localhost.
  553. continue loop
  554. }
  555. }
  556. t.Errorf("%s: got %s; want %s", mode, name, name[:len(name)-1])
  557. } else if strings.Contains(name, ".") && !strings.HasSuffix(name, ".") { // "localhost.localdomain." not "localhost.localdomain"
  558. t.Errorf("%s: got %s; want name ending with trailing dot", mode, name)
  559. }
  560. }
  561. }
  562. }
  563. func TestLookupDotsWithRemoteSource(t *testing.T) {
  564. if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
  565. testenv.SkipFlaky(t, 27992)
  566. }
  567. mustHaveExternalNetwork(t)
  568. testenv.SkipFlakyNet(t)
  569. if !supportsIPv4() || !*testIPv4 {
  570. t.Skip("IPv4 is required")
  571. }
  572. if iOS() {
  573. t.Skip("no resolv.conf on iOS")
  574. }
  575. defer dnsWaitGroup.Wait()
  576. if fixup := forceGoDNS(); fixup != nil {
  577. testDots(t, "go")
  578. fixup()
  579. }
  580. if fixup := forceCgoDNS(); fixup != nil {
  581. testDots(t, "cgo")
  582. fixup()
  583. }
  584. }
  585. func testDots(t *testing.T, mode string) {
  586. names, err := LookupAddr("8.8.8.8") // Google dns server
  587. if err != nil {
  588. t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
  589. } else {
  590. for _, name := range names {
  591. if !hasSuffixFold(name, ".google.com.") && !hasSuffixFold(name, ".google.") {
  592. t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com or .google with trailing dot (mode=%v)", names, mode)
  593. break
  594. }
  595. }
  596. }
  597. cname, err := LookupCNAME("www.mit.edu")
  598. if err != nil {
  599. t.Errorf("LookupCNAME(www.mit.edu, mode=%v): %v", mode, err)
  600. } else if !strings.HasSuffix(cname, ".") {
  601. t.Errorf("LookupCNAME(www.mit.edu) = %v, want cname ending in . with trailing dot (mode=%v)", cname, mode)
  602. }
  603. mxs, err := LookupMX("google.com")
  604. if err != nil {
  605. t.Errorf("LookupMX(google.com): %v (mode=%v)", err, mode)
  606. } else {
  607. for _, mx := range mxs {
  608. if !hasSuffixFold(mx.Host, ".google.com.") {
  609. t.Errorf("LookupMX(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", mxString(mxs), mode)
  610. break
  611. }
  612. }
  613. }
  614. nss, err := LookupNS("google.com")
  615. if err != nil {
  616. t.Errorf("LookupNS(google.com): %v (mode=%v)", err, mode)
  617. } else {
  618. for _, ns := range nss {
  619. if !hasSuffixFold(ns.Host, ".google.com.") {
  620. t.Errorf("LookupNS(google.com) = %v, want names ending in .google.com. with trailing dot (mode=%v)", nsString(nss), mode)
  621. break
  622. }
  623. }
  624. }
  625. cname, srvs, err := LookupSRV("xmpp-server", "tcp", "google.com")
  626. if err != nil {
  627. t.Errorf("LookupSRV(xmpp-server, tcp, google.com): %v (mode=%v)", err, mode)
  628. } else {
  629. if !hasSuffixFold(cname, ".google.com.") {
  630. t.Errorf("LookupSRV(xmpp-server, tcp, google.com) returned cname=%v, want name ending in .google.com. with trailing dot (mode=%v)", cname, mode)
  631. }
  632. for _, srv := range srvs {
  633. if !hasSuffixFold(srv.Target, ".google.com.") {
  634. 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)
  635. break
  636. }
  637. }
  638. }
  639. }
  640. func mxString(mxs []*MX) string {
  641. var buf bytes.Buffer
  642. sep := ""
  643. fmt.Fprintf(&buf, "[")
  644. for _, mx := range mxs {
  645. fmt.Fprintf(&buf, "%s%s:%d", sep, mx.Host, mx.Pref)
  646. sep = " "
  647. }
  648. fmt.Fprintf(&buf, "]")
  649. return buf.String()
  650. }
  651. func nsString(nss []*NS) string {
  652. var buf bytes.Buffer
  653. sep := ""
  654. fmt.Fprintf(&buf, "[")
  655. for _, ns := range nss {
  656. fmt.Fprintf(&buf, "%s%s", sep, ns.Host)
  657. sep = " "
  658. }
  659. fmt.Fprintf(&buf, "]")
  660. return buf.String()
  661. }
  662. func srvString(srvs []*SRV) string {
  663. var buf bytes.Buffer
  664. sep := ""
  665. fmt.Fprintf(&buf, "[")
  666. for _, srv := range srvs {
  667. fmt.Fprintf(&buf, "%s%s:%d:%d:%d", sep, srv.Target, srv.Port, srv.Priority, srv.Weight)
  668. sep = " "
  669. }
  670. fmt.Fprintf(&buf, "]")
  671. return buf.String()
  672. }
  673. func TestLookupPort(t *testing.T) {
  674. // See https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
  675. //
  676. // Please be careful about adding new test cases.
  677. // There are platforms which have incomplete mappings for
  678. // restricted resource access and security reasons.
  679. type test struct {
  680. network string
  681. name string
  682. port int
  683. ok bool
  684. }
  685. var tests = []test{
  686. {"tcp", "0", 0, true},
  687. {"udp", "0", 0, true},
  688. {"udp", "domain", 53, true},
  689. {"--badnet--", "zzz", 0, false},
  690. {"tcp", "--badport--", 0, false},
  691. {"tcp", "-1", 0, false},
  692. {"tcp", "65536", 0, false},
  693. {"udp", "-1", 0, false},
  694. {"udp", "65536", 0, false},
  695. {"tcp", "123456789", 0, false},
  696. // Issue 13610: LookupPort("tcp", "")
  697. {"tcp", "", 0, true},
  698. {"tcp4", "", 0, true},
  699. {"tcp6", "", 0, true},
  700. {"udp", "", 0, true},
  701. {"udp4", "", 0, true},
  702. {"udp6", "", 0, true},
  703. }
  704. switch runtime.GOOS {
  705. case "android":
  706. if netGo {
  707. t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
  708. }
  709. default:
  710. tests = append(tests, test{"tcp", "http", 80, true})
  711. }
  712. for _, tt := range tests {
  713. port, err := LookupPort(tt.network, tt.name)
  714. if port != tt.port || (err == nil) != tt.ok {
  715. t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=%t", tt.network, tt.name, port, err, tt.port, !tt.ok)
  716. }
  717. if err != nil {
  718. if perr := parseLookupPortError(err); perr != nil {
  719. t.Error(perr)
  720. }
  721. }
  722. }
  723. }
  724. // Like TestLookupPort but with minimal tests that should always pass
  725. // because the answers are baked-in to the net package.
  726. func TestLookupPort_Minimal(t *testing.T) {
  727. type test struct {
  728. network string
  729. name string
  730. port int
  731. }
  732. var tests = []test{
  733. {"tcp", "http", 80},
  734. {"tcp", "HTTP", 80}, // case shouldn't matter
  735. {"tcp", "https", 443},
  736. {"tcp", "ssh", 22},
  737. {"tcp", "gopher", 70},
  738. {"tcp4", "http", 80},
  739. {"tcp6", "http", 80},
  740. }
  741. for _, tt := range tests {
  742. port, err := LookupPort(tt.network, tt.name)
  743. if port != tt.port || err != nil {
  744. t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=nil", tt.network, tt.name, port, err, tt.port)
  745. }
  746. }
  747. }
  748. func TestLookupProtocol_Minimal(t *testing.T) {
  749. type test struct {
  750. name string
  751. want int
  752. }
  753. var tests = []test{
  754. {"tcp", 6},
  755. {"TcP", 6}, // case shouldn't matter
  756. {"icmp", 1},
  757. {"igmp", 2},
  758. {"udp", 17},
  759. {"ipv6-icmp", 58},
  760. }
  761. for _, tt := range tests {
  762. got, err := lookupProtocol(context.Background(), tt.name)
  763. if got != tt.want || err != nil {
  764. t.Errorf("LookupProtocol(%q) = %d, %v; want %d, error=nil", tt.name, got, err, tt.want)
  765. }
  766. }
  767. }
  768. func TestLookupNonLDH(t *testing.T) {
  769. defer dnsWaitGroup.Wait()
  770. if fixup := forceGoDNS(); fixup != nil {
  771. defer fixup()
  772. }
  773. // "LDH" stands for letters, digits, and hyphens and is the usual
  774. // description of standard DNS names.
  775. // This test is checking that other kinds of names are reported
  776. // as not found, not reported as invalid names.
  777. addrs, err := LookupHost("!!!.###.bogus..domain.")
  778. if err == nil {
  779. t.Fatalf("lookup succeeded: %v", addrs)
  780. }
  781. if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) {
  782. t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost)
  783. }
  784. if !err.(*DNSError).IsNotFound {
  785. t.Fatalf("lookup error = %v, want true", err.(*DNSError).IsNotFound)
  786. }
  787. }
  788. func TestLookupContextCancel(t *testing.T) {
  789. mustHaveExternalNetwork(t)
  790. testenv.SkipFlakyNet(t)
  791. origTestHookLookupIP := testHookLookupIP
  792. defer func() {
  793. dnsWaitGroup.Wait()
  794. testHookLookupIP = origTestHookLookupIP
  795. }()
  796. lookupCtx, cancelLookup := context.WithCancel(context.Background())
  797. unblockLookup := make(chan struct{})
  798. // Set testHookLookupIP to start a new, concurrent call to LookupIPAddr
  799. // and cancel the original one, then block until the canceled call has returned
  800. // (ensuring that it has performed any synchronous cleanup).
  801. testHookLookupIP = func(
  802. ctx context.Context,
  803. fn func(context.Context, string, string) ([]IPAddr, error),
  804. network string,
  805. host string,
  806. ) ([]IPAddr, error) {
  807. select {
  808. case <-unblockLookup:
  809. default:
  810. // Start a concurrent LookupIPAddr for the same host while the caller is
  811. // still blocked, and sleep a little to give it time to be deduplicated
  812. // before we cancel (and unblock) the caller.
  813. // (If the timing doesn't quite work out, we'll end up testing sequential
  814. // calls instead of concurrent ones, but the test should still pass.)
  815. t.Logf("starting concurrent LookupIPAddr")
  816. dnsWaitGroup.Add(1)
  817. go func() {
  818. defer dnsWaitGroup.Done()
  819. _, err := DefaultResolver.LookupIPAddr(context.Background(), host)
  820. if err != nil {
  821. t.Error(err)
  822. }
  823. }()
  824. time.Sleep(1 * time.Millisecond)
  825. }
  826. cancelLookup()
  827. <-unblockLookup
  828. // If the concurrent lookup above is deduplicated to this one
  829. // (as we expect to happen most of the time), it is important
  830. // that the original call does not cancel the shared Context.
  831. // (See https://go.dev/issue/22724.) Explicitly check for
  832. // cancellation now, just in case fn itself doesn't notice it.
  833. if err := ctx.Err(); err != nil {
  834. t.Logf("testHookLookupIP canceled")
  835. return nil, err
  836. }
  837. t.Logf("testHookLookupIP performing lookup")
  838. return fn(ctx, network, host)
  839. }
  840. _, err := DefaultResolver.LookupIPAddr(lookupCtx, "google.com")
  841. if dnsErr, ok := err.(*DNSError); !ok || dnsErr.Err != errCanceled.Error() {
  842. t.Errorf("unexpected error from canceled, blocked LookupIPAddr: %v", err)
  843. }
  844. close(unblockLookup)
  845. }
  846. // Issue 24330: treat the nil *Resolver like a zero value. Verify nothing
  847. // crashes if nil is used.
  848. func TestNilResolverLookup(t *testing.T) {
  849. mustHaveExternalNetwork(t)
  850. var r *Resolver = nil
  851. ctx := context.Background()
  852. // Don't care about the results, just that nothing panics:
  853. r.LookupAddr(ctx, "8.8.8.8")
  854. r.LookupCNAME(ctx, "google.com")
  855. r.LookupHost(ctx, "google.com")
  856. r.LookupIPAddr(ctx, "google.com")
  857. r.LookupIP(ctx, "ip", "google.com")
  858. r.LookupMX(ctx, "gmail.com")
  859. r.LookupNS(ctx, "google.com")
  860. r.LookupPort(ctx, "tcp", "smtp")
  861. r.LookupSRV(ctx, "service", "proto", "name")
  862. r.LookupTXT(ctx, "gmail.com")
  863. }
  864. // TestLookupHostCancel verifies that lookup works even after many
  865. // canceled lookups (see golang.org/issue/24178 for details).
  866. func TestLookupHostCancel(t *testing.T) {
  867. mustHaveExternalNetwork(t)
  868. testenv.SkipFlakyNet(t)
  869. t.Parallel() // Executes 600ms worth of sequential sleeps.
  870. const (
  871. google = "www.google.com"
  872. invalidDomain = "invalid.invalid" // RFC 2606 reserves .invalid
  873. n = 600 // this needs to be larger than threadLimit size
  874. )
  875. _, err := LookupHost(google)
  876. if err != nil {
  877. t.Fatal(err)
  878. }
  879. ctx, cancel := context.WithCancel(context.Background())
  880. cancel()
  881. for i := 0; i < n; i++ {
  882. addr, err := DefaultResolver.LookupHost(ctx, invalidDomain)
  883. if err == nil {
  884. t.Fatalf("LookupHost(%q): returns %v, but should fail", invalidDomain, addr)
  885. }
  886. // Don't verify what the actual error is.
  887. // We know that it must be non-nil because the domain is invalid,
  888. // but we don't have any guarantee that LookupHost actually bothers
  889. // to check for cancellation on the fast path.
  890. // (For example, it could use a local cache to avoid blocking entirely.)
  891. // The lookup may deduplicate in-flight requests, so give it time to settle
  892. // in between.
  893. time.Sleep(time.Millisecond * 1)
  894. }
  895. _, err = LookupHost(google)
  896. if err != nil {
  897. t.Fatal(err)
  898. }
  899. }
  900. type lookupCustomResolver struct {
  901. *Resolver
  902. mu sync.RWMutex
  903. dialed bool
  904. }
  905. func (lcr *lookupCustomResolver) dial() func(ctx context.Context, network, address string) (Conn, error) {
  906. return func(ctx context.Context, network, address string) (Conn, error) {
  907. lcr.mu.Lock()
  908. lcr.dialed = true
  909. lcr.mu.Unlock()
  910. return Dial(network, address)
  911. }
  912. }
  913. // TestConcurrentPreferGoResolversDial tests that multiple resolvers with the
  914. // PreferGo option used concurrently are all dialed properly.
  915. func TestConcurrentPreferGoResolversDial(t *testing.T) {
  916. // The windows and plan9 implementation of the resolver does not use
  917. // the Dial function.
  918. switch runtime.GOOS {
  919. case "windows", "plan9":
  920. t.Skipf("skip on %v", runtime.GOOS)
  921. }
  922. testenv.MustHaveExternalNetwork(t)
  923. testenv.SkipFlakyNet(t)
  924. defer dnsWaitGroup.Wait()
  925. resolvers := make([]*lookupCustomResolver, 2)
  926. for i := range resolvers {
  927. cs := lookupCustomResolver{Resolver: &Resolver{PreferGo: true}}
  928. cs.Dial = cs.dial()
  929. resolvers[i] = &cs
  930. }
  931. var wg sync.WaitGroup
  932. wg.Add(len(resolvers))
  933. for i, resolver := range resolvers {
  934. go func(r *Resolver, index int) {
  935. defer wg.Done()
  936. _, err := r.LookupIPAddr(context.Background(), "google.com")
  937. if err != nil {
  938. t.Errorf("lookup failed for resolver %d: %q", index, err)
  939. }
  940. }(resolver.Resolver, i)
  941. }
  942. wg.Wait()
  943. if t.Failed() {
  944. t.FailNow()
  945. }
  946. for i, resolver := range resolvers {
  947. if !resolver.dialed {
  948. t.Errorf("custom resolver %d not dialed during lookup", i)
  949. }
  950. }
  951. }
  952. var ipVersionTests = []struct {
  953. network string
  954. version byte
  955. }{
  956. {"tcp", 0},
  957. {"tcp4", '4'},
  958. {"tcp6", '6'},
  959. {"udp", 0},
  960. {"udp4", '4'},
  961. {"udp6", '6'},
  962. {"ip", 0},
  963. {"ip4", '4'},
  964. {"ip6", '6'},
  965. {"ip7", 0},
  966. {"", 0},
  967. }
  968. func TestIPVersion(t *testing.T) {
  969. for _, tt := range ipVersionTests {
  970. if version := ipVersion(tt.network); version != tt.version {
  971. t.Errorf("Family for: %s. Expected: %s, Got: %s", tt.network,
  972. string(tt.version), string(version))
  973. }
  974. }
  975. }
  976. // Issue 28600: The context that is used to lookup ips should always
  977. // preserve the values from the context that was passed into LookupIPAddr.
  978. func TestLookupIPAddrPreservesContextValues(t *testing.T) {
  979. origTestHookLookupIP := testHookLookupIP
  980. defer func() { testHookLookupIP = origTestHookLookupIP }()
  981. keyValues := []struct {
  982. key, value any
  983. }{
  984. {"key-1", 12},
  985. {384, "value2"},
  986. {new(float64), 137},
  987. }
  988. ctx := context.Background()
  989. for _, kv := range keyValues {
  990. ctx = context.WithValue(ctx, kv.key, kv.value)
  991. }
  992. wantIPs := []IPAddr{
  993. {IP: IPv4(127, 0, 0, 1)},
  994. {IP: IPv6loopback},
  995. }
  996. checkCtxValues := func(ctx_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
  997. for _, kv := range keyValues {
  998. g, w := ctx_.Value(kv.key), kv.value
  999. if !reflect.DeepEqual(g, w) {
  1000. t.Errorf("Value lookup:\n\tGot: %v\n\tWant: %v", g, w)
  1001. }
  1002. }
  1003. return wantIPs, nil
  1004. }
  1005. testHookLookupIP = checkCtxValues
  1006. resolvers := []*Resolver{
  1007. nil,
  1008. new(Resolver),
  1009. }
  1010. for i, resolver := range resolvers {
  1011. gotIPs, err := resolver.LookupIPAddr(ctx, "golang.org")
  1012. if err != nil {
  1013. t.Errorf("Resolver #%d: unexpected error: %v", i, err)
  1014. }
  1015. if !reflect.DeepEqual(gotIPs, wantIPs) {
  1016. t.Errorf("#%d: mismatched IPAddr results\n\tGot: %v\n\tWant: %v", i, gotIPs, wantIPs)
  1017. }
  1018. }
  1019. }
  1020. // Issue 30521: The lookup group should call the resolver for each network.
  1021. func TestLookupIPAddrConcurrentCallsForNetworks(t *testing.T) {
  1022. origTestHookLookupIP := testHookLookupIP
  1023. defer func() { testHookLookupIP = origTestHookLookupIP }()
  1024. queries := [][]string{
  1025. {"udp", "golang.org"},
  1026. {"udp4", "golang.org"},
  1027. {"udp6", "golang.org"},
  1028. {"udp", "golang.org"},
  1029. {"udp", "golang.org"},
  1030. }
  1031. results := map[[2]string][]IPAddr{
  1032. {"udp", "golang.org"}: {
  1033. {IP: IPv4(127, 0, 0, 1)},
  1034. {IP: IPv6loopback},
  1035. },
  1036. {"udp4", "golang.org"}: {
  1037. {IP: IPv4(127, 0, 0, 1)},
  1038. },
  1039. {"udp6", "golang.org"}: {
  1040. {IP: IPv6loopback},
  1041. },
  1042. }
  1043. calls := int32(0)
  1044. waitCh := make(chan struct{})
  1045. testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
  1046. // We'll block until this is called one time for each different
  1047. // expected result. This will ensure that the lookup group would wait
  1048. // for the existing call if it was to be reused.
  1049. if atomic.AddInt32(&calls, 1) == int32(len(results)) {
  1050. close(waitCh)
  1051. }
  1052. select {
  1053. case <-waitCh:
  1054. case <-ctx.Done():
  1055. return nil, ctx.Err()
  1056. }
  1057. return results[[2]string{network, host}], nil
  1058. }
  1059. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  1060. defer cancel()
  1061. wg := sync.WaitGroup{}
  1062. for _, q := range queries {
  1063. network := q[0]
  1064. host := q[1]
  1065. wg.Add(1)
  1066. go func() {
  1067. defer wg.Done()
  1068. gotIPs, err := DefaultResolver.lookupIPAddr(ctx, network, host)
  1069. if err != nil {
  1070. t.Errorf("lookupIPAddr(%v, %v): unexpected error: %v", network, host, err)
  1071. }
  1072. wantIPs := results[[2]string{network, host}]
  1073. if !reflect.DeepEqual(gotIPs, wantIPs) {
  1074. t.Errorf("lookupIPAddr(%v, %v): mismatched IPAddr results\n\tGot: %v\n\tWant: %v", network, host, gotIPs, wantIPs)
  1075. }
  1076. }()
  1077. }
  1078. wg.Wait()
  1079. }
  1080. func TestWithUnexpiredValuesPreserved(t *testing.T) {
  1081. ctx, cancel := context.WithCancel(context.Background())
  1082. // Insert a value into it.
  1083. key, value := "key-1", 2
  1084. ctx = context.WithValue(ctx, key, value)
  1085. // Now use the "values preserving context" like
  1086. // we would for LookupIPAddr. See Issue 28600.
  1087. ctx = withUnexpiredValuesPreserved(ctx)
  1088. // Lookup before expiry.
  1089. if g, w := ctx.Value(key), value; g != w {
  1090. t.Errorf("Lookup before expiry: Got %v Want %v", g, w)
  1091. }
  1092. // Cancel the context.
  1093. cancel()
  1094. // Lookup after expiry should return nil
  1095. if g := ctx.Value(key); g != nil {
  1096. t.Errorf("Lookup after expiry: Got %v want nil", g)
  1097. }
  1098. }
  1099. // Issue 31597: don't panic on null byte in name
  1100. func TestLookupNullByte(t *testing.T) {
  1101. testenv.MustHaveExternalNetwork(t)
  1102. testenv.SkipFlakyNet(t)
  1103. LookupHost("foo\x00bar") // check that it doesn't panic; it used to on Windows
  1104. }
  1105. func TestResolverLookupIP(t *testing.T) {
  1106. testenv.MustHaveExternalNetwork(t)
  1107. v4Ok := supportsIPv4() && *testIPv4
  1108. v6Ok := supportsIPv6() && *testIPv6
  1109. defer dnsWaitGroup.Wait()
  1110. for _, impl := range []struct {
  1111. name string
  1112. fn func() func()
  1113. }{
  1114. {"go", forceGoDNS},
  1115. {"cgo", forceCgoDNS},
  1116. } {
  1117. t.Run("implementation: "+impl.name, func(t *testing.T) {
  1118. fixup := impl.fn()
  1119. if fixup == nil {
  1120. t.Skip("not supported")
  1121. }
  1122. defer fixup()
  1123. for _, network := range []string{"ip", "ip4", "ip6"} {
  1124. t.Run("network: "+network, func(t *testing.T) {
  1125. switch {
  1126. case network == "ip4" && !v4Ok:
  1127. t.Skip("IPv4 is not supported")
  1128. case network == "ip6" && !v6Ok:
  1129. t.Skip("IPv6 is not supported")
  1130. }
  1131. // google.com has both A and AAAA records.
  1132. const host = "google.com"
  1133. ips, err := DefaultResolver.LookupIP(context.Background(), network, host)
  1134. if err != nil {
  1135. testenv.SkipFlakyNet(t)
  1136. t.Fatalf("DefaultResolver.LookupIP(%q, %q): failed with unexpected error: %v", network, host, err)
  1137. }
  1138. var v4Addrs []IP
  1139. var v6Addrs []IP
  1140. for _, ip := range ips {
  1141. switch {
  1142. case ip.To4() != nil:
  1143. // We need to skip the test below because To16 will
  1144. // convent an IPv4 address to an IPv4-mapped IPv6
  1145. // address.
  1146. v4Addrs = append(v4Addrs, ip)
  1147. case ip.To16() != nil:
  1148. v6Addrs = append(v6Addrs, ip)
  1149. default:
  1150. t.Fatalf("IP=%q is neither IPv4 nor IPv6", ip)
  1151. }
  1152. }
  1153. // Check that we got the expected addresses.
  1154. if network == "ip4" || network == "ip" && v4Ok {
  1155. if len(v4Addrs) == 0 {
  1156. t.Errorf("DefaultResolver.LookupIP(%q, %q): no IPv4 addresses", network, host)
  1157. }
  1158. }
  1159. if network == "ip6" || network == "ip" && v6Ok {
  1160. if len(v6Addrs) == 0 {
  1161. t.Errorf("DefaultResolver.LookupIP(%q, %q): no IPv6 addresses", network, host)
  1162. }
  1163. }
  1164. // Check that we didn't get any unexpected addresses.
  1165. if network == "ip6" && len(v4Addrs) > 0 {
  1166. t.Errorf("DefaultResolver.LookupIP(%q, %q): unexpected IPv4 addresses: %v", network, host, v4Addrs)
  1167. }
  1168. if network == "ip4" && len(v6Addrs) > 0 {
  1169. t.Errorf("DefaultResolver.LookupIP(%q, %q): unexpected IPv6 addresses: %v", network, host, v6Addrs)
  1170. }
  1171. })
  1172. }
  1173. })
  1174. }
  1175. }
  1176. // A context timeout should still return a DNSError.
  1177. func TestDNSTimeout(t *testing.T) {
  1178. origTestHookLookupIP := testHookLookupIP
  1179. defer func() { testHookLookupIP = origTestHookLookupIP }()
  1180. defer dnsWaitGroup.Wait()
  1181. timeoutHookGo := make(chan bool, 1)
  1182. timeoutHook := func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
  1183. <-timeoutHookGo
  1184. return nil, context.DeadlineExceeded
  1185. }
  1186. testHookLookupIP = timeoutHook
  1187. checkErr := func(err error) {
  1188. t.Helper()
  1189. if err == nil {
  1190. t.Error("expected an error")
  1191. } else if dnserr, ok := err.(*DNSError); !ok {
  1192. t.Errorf("got error type %T, want %T", err, (*DNSError)(nil))
  1193. } else if !dnserr.IsTimeout {
  1194. t.Errorf("got error %#v, want IsTimeout == true", dnserr)
  1195. } else if isTimeout := dnserr.Timeout(); !isTimeout {
  1196. t.Errorf("got err.Timeout() == %t, want true", isTimeout)
  1197. }
  1198. }
  1199. // Single lookup.
  1200. timeoutHookGo <- true
  1201. _, err := LookupIP("golang.org")
  1202. checkErr(err)
  1203. // Double lookup.
  1204. var err1, err2 error
  1205. var wg sync.WaitGroup
  1206. wg.Add(2)
  1207. go func() {
  1208. defer wg.Done()
  1209. _, err1 = LookupIP("golang1.org")
  1210. }()
  1211. go func() {
  1212. defer wg.Done()
  1213. _, err2 = LookupIP("golang1.org")
  1214. }()
  1215. close(timeoutHookGo)
  1216. wg.Wait()
  1217. checkErr(err1)
  1218. checkErr(err2)
  1219. // Double lookup with context.
  1220. timeoutHookGo = make(chan bool)
  1221. ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
  1222. wg.Add(2)
  1223. go func() {
  1224. defer wg.Done()
  1225. _, err1 = DefaultResolver.LookupIPAddr(ctx, "golang2.org")
  1226. }()
  1227. go func() {
  1228. defer wg.Done()
  1229. _, err2 = DefaultResolver.LookupIPAddr(ctx, "golang2.org")
  1230. }()
  1231. time.Sleep(10 * time.Nanosecond)
  1232. close(timeoutHookGo)
  1233. wg.Wait()
  1234. checkErr(err1)
  1235. checkErr(err2)
  1236. cancel()
  1237. }