You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1125 regels
24 KiB

  1. /*
  2. *
  3. * Copyright 2018 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package dns
  19. import (
  20. "context"
  21. "errors"
  22. "fmt"
  23. "net"
  24. "os"
  25. "reflect"
  26. "sync"
  27. "testing"
  28. "time"
  29. "google.golang.org/grpc/internal/leakcheck"
  30. "google.golang.org/grpc/resolver"
  31. )
  32. func TestMain(m *testing.M) {
  33. cleanup := replaceNetFunc()
  34. code := m.Run()
  35. cleanup()
  36. os.Exit(code)
  37. }
  38. const (
  39. txtBytesLimit = 255
  40. )
  41. type testClientConn struct {
  42. target string
  43. m1 sync.Mutex
  44. addrs []resolver.Address
  45. a int // how many times NewAddress() has been called
  46. m2 sync.Mutex
  47. sc string
  48. s int
  49. }
  50. func (t *testClientConn) NewAddress(addresses []resolver.Address) {
  51. t.m1.Lock()
  52. defer t.m1.Unlock()
  53. t.addrs = addresses
  54. t.a++
  55. }
  56. func (t *testClientConn) getAddress() ([]resolver.Address, int) {
  57. t.m1.Lock()
  58. defer t.m1.Unlock()
  59. return t.addrs, t.a
  60. }
  61. func (t *testClientConn) NewServiceConfig(serviceConfig string) {
  62. t.m2.Lock()
  63. defer t.m2.Unlock()
  64. t.sc = serviceConfig
  65. t.s++
  66. }
  67. func (t *testClientConn) getSc() (string, int) {
  68. t.m2.Lock()
  69. defer t.m2.Unlock()
  70. return t.sc, t.s
  71. }
  72. type testResolver struct {
  73. }
  74. func (*testResolver) LookupHost(ctx context.Context, host string) ([]string, error) {
  75. return hostLookup(host)
  76. }
  77. func (*testResolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) {
  78. return srvLookup(service, proto, name)
  79. }
  80. func (*testResolver) LookupTXT(ctx context.Context, host string) ([]string, error) {
  81. return txtLookup(host)
  82. }
  83. func replaceNetFunc() func() {
  84. oldResolver := defaultResolver
  85. defaultResolver = &testResolver{}
  86. return func() {
  87. defaultResolver = oldResolver
  88. }
  89. }
  90. var hostLookupTbl = struct {
  91. sync.Mutex
  92. tbl map[string][]string
  93. }{
  94. tbl: map[string][]string{
  95. "foo.bar.com": {"1.2.3.4", "5.6.7.8"},
  96. "ipv4.single.fake": {"1.2.3.4"},
  97. "srv.ipv4.single.fake": {"2.4.6.8"},
  98. "ipv4.multi.fake": {"1.2.3.4", "5.6.7.8", "9.10.11.12"},
  99. "ipv6.single.fake": {"2607:f8b0:400a:801::1001"},
  100. "ipv6.multi.fake": {"2607:f8b0:400a:801::1001", "2607:f8b0:400a:801::1002", "2607:f8b0:400a:801::1003"},
  101. },
  102. }
  103. func hostLookup(host string) ([]string, error) {
  104. hostLookupTbl.Lock()
  105. defer hostLookupTbl.Unlock()
  106. if addrs, cnt := hostLookupTbl.tbl[host]; cnt {
  107. return addrs, nil
  108. }
  109. return nil, fmt.Errorf("failed to lookup host:%s resolution in hostLookupTbl", host)
  110. }
  111. var srvLookupTbl = struct {
  112. sync.Mutex
  113. tbl map[string][]*net.SRV
  114. }{
  115. tbl: map[string][]*net.SRV{
  116. "_grpclb._tcp.srv.ipv4.single.fake": {&net.SRV{Target: "ipv4.single.fake", Port: 1234}},
  117. "_grpclb._tcp.srv.ipv4.multi.fake": {&net.SRV{Target: "ipv4.multi.fake", Port: 1234}},
  118. "_grpclb._tcp.srv.ipv6.single.fake": {&net.SRV{Target: "ipv6.single.fake", Port: 1234}},
  119. "_grpclb._tcp.srv.ipv6.multi.fake": {&net.SRV{Target: "ipv6.multi.fake", Port: 1234}},
  120. },
  121. }
  122. func srvLookup(service, proto, name string) (string, []*net.SRV, error) {
  123. cname := "_" + service + "._" + proto + "." + name
  124. srvLookupTbl.Lock()
  125. defer srvLookupTbl.Unlock()
  126. if srvs, cnt := srvLookupTbl.tbl[cname]; cnt {
  127. return cname, srvs, nil
  128. }
  129. return "", nil, fmt.Errorf("failed to lookup srv record for %s in srvLookupTbl", cname)
  130. }
  131. // div divides a byte slice into a slice of strings, each of which is of maximum
  132. // 255 bytes length, which is the length limit per TXT record in DNS.
  133. func div(b []byte) []string {
  134. var r []string
  135. for i := 0; i < len(b); i += txtBytesLimit {
  136. if i+txtBytesLimit > len(b) {
  137. r = append(r, string(b[i:]))
  138. } else {
  139. r = append(r, string(b[i:i+txtBytesLimit]))
  140. }
  141. }
  142. return r
  143. }
  144. // scfs contains an array of service config file string in JSON format.
  145. // Notes about the scfs contents and usage:
  146. // scfs contains 4 service config file JSON strings for testing. Inside each
  147. // service config file, there are multiple choices. scfs[0:3] each contains 5
  148. // choices, and first 3 choices are nonmatching choices based on canarying rule,
  149. // while the last two are matched choices. scfs[3] only contains 3 choices, and
  150. // all of them are nonmatching based on canarying rule. For each of scfs[0:3],
  151. // the eventually returned service config, which is from the first of the two
  152. // matched choices, is stored in the corresponding scs element (e.g.
  153. // scfs[0]->scs[0]). scfs and scs elements are used in pair to test the dns
  154. // resolver functionality, with scfs as the input and scs used for validation of
  155. // the output. For scfs[3], it corresponds to empty service config, since there
  156. // isn't a matched choice.
  157. var scfs = []string{
  158. `[
  159. {
  160. "clientLanguage": [
  161. "CPP",
  162. "JAVA"
  163. ],
  164. "serviceConfig": {
  165. "loadBalancingPolicy": "grpclb",
  166. "methodConfig": [
  167. {
  168. "name": [
  169. {
  170. "service": "all"
  171. }
  172. ],
  173. "timeout": "1s"
  174. }
  175. ]
  176. }
  177. },
  178. {
  179. "percentage": 0,
  180. "serviceConfig": {
  181. "loadBalancingPolicy": "grpclb",
  182. "methodConfig": [
  183. {
  184. "name": [
  185. {
  186. "service": "all"
  187. }
  188. ],
  189. "timeout": "1s"
  190. }
  191. ]
  192. }
  193. },
  194. {
  195. "clientHostName": [
  196. "localhost"
  197. ],
  198. "serviceConfig": {
  199. "loadBalancingPolicy": "grpclb",
  200. "methodConfig": [
  201. {
  202. "name": [
  203. {
  204. "service": "all"
  205. }
  206. ],
  207. "timeout": "1s"
  208. }
  209. ]
  210. }
  211. },
  212. {
  213. "clientLanguage": [
  214. "GO"
  215. ],
  216. "percentage": 100,
  217. "serviceConfig": {
  218. "methodConfig": [
  219. {
  220. "name": [
  221. {
  222. "method": "bar"
  223. }
  224. ],
  225. "maxRequestMessageBytes": 1024,
  226. "maxResponseMessageBytes": 1024
  227. }
  228. ]
  229. }
  230. },
  231. {
  232. "serviceConfig": {
  233. "loadBalancingPolicy": "round_robin",
  234. "methodConfig": [
  235. {
  236. "name": [
  237. {
  238. "service": "foo",
  239. "method": "bar"
  240. }
  241. ],
  242. "waitForReady": true
  243. }
  244. ]
  245. }
  246. }
  247. ]`,
  248. `[
  249. {
  250. "clientLanguage": [
  251. "CPP",
  252. "JAVA"
  253. ],
  254. "serviceConfig": {
  255. "loadBalancingPolicy": "grpclb",
  256. "methodConfig": [
  257. {
  258. "name": [
  259. {
  260. "service": "all"
  261. }
  262. ],
  263. "timeout": "1s"
  264. }
  265. ]
  266. }
  267. },
  268. {
  269. "percentage": 0,
  270. "serviceConfig": {
  271. "loadBalancingPolicy": "grpclb",
  272. "methodConfig": [
  273. {
  274. "name": [
  275. {
  276. "service": "all"
  277. }
  278. ],
  279. "timeout": "1s"
  280. }
  281. ]
  282. }
  283. },
  284. {
  285. "clientHostName": [
  286. "localhost"
  287. ],
  288. "serviceConfig": {
  289. "loadBalancingPolicy": "grpclb",
  290. "methodConfig": [
  291. {
  292. "name": [
  293. {
  294. "service": "all"
  295. }
  296. ],
  297. "timeout": "1s"
  298. }
  299. ]
  300. }
  301. },
  302. {
  303. "clientLanguage": [
  304. "GO"
  305. ],
  306. "percentage": 100,
  307. "serviceConfig": {
  308. "methodConfig": [
  309. {
  310. "name": [
  311. {
  312. "service": "foo",
  313. "method": "bar"
  314. }
  315. ],
  316. "waitForReady": true,
  317. "timeout": "1s",
  318. "maxRequestMessageBytes": 1024,
  319. "maxResponseMessageBytes": 1024
  320. }
  321. ]
  322. }
  323. },
  324. {
  325. "serviceConfig": {
  326. "loadBalancingPolicy": "round_robin",
  327. "methodConfig": [
  328. {
  329. "name": [
  330. {
  331. "service": "foo",
  332. "method": "bar"
  333. }
  334. ],
  335. "waitForReady": true
  336. }
  337. ]
  338. }
  339. }
  340. ]`,
  341. `[
  342. {
  343. "clientLanguage": [
  344. "CPP",
  345. "JAVA"
  346. ],
  347. "serviceConfig": {
  348. "loadBalancingPolicy": "grpclb",
  349. "methodConfig": [
  350. {
  351. "name": [
  352. {
  353. "service": "all"
  354. }
  355. ],
  356. "timeout": "1s"
  357. }
  358. ]
  359. }
  360. },
  361. {
  362. "percentage": 0,
  363. "serviceConfig": {
  364. "loadBalancingPolicy": "grpclb",
  365. "methodConfig": [
  366. {
  367. "name": [
  368. {
  369. "service": "all"
  370. }
  371. ],
  372. "timeout": "1s"
  373. }
  374. ]
  375. }
  376. },
  377. {
  378. "clientHostName": [
  379. "localhost"
  380. ],
  381. "serviceConfig": {
  382. "loadBalancingPolicy": "grpclb",
  383. "methodConfig": [
  384. {
  385. "name": [
  386. {
  387. "service": "all"
  388. }
  389. ],
  390. "timeout": "1s"
  391. }
  392. ]
  393. }
  394. },
  395. {
  396. "clientLanguage": [
  397. "GO"
  398. ],
  399. "percentage": 100,
  400. "serviceConfig": {
  401. "loadBalancingPolicy": "round_robin",
  402. "methodConfig": [
  403. {
  404. "name": [
  405. {
  406. "service": "foo"
  407. }
  408. ],
  409. "waitForReady": true,
  410. "timeout": "1s"
  411. },
  412. {
  413. "name": [
  414. {
  415. "service": "bar"
  416. }
  417. ],
  418. "waitForReady": false
  419. }
  420. ]
  421. }
  422. },
  423. {
  424. "serviceConfig": {
  425. "loadBalancingPolicy": "round_robin",
  426. "methodConfig": [
  427. {
  428. "name": [
  429. {
  430. "service": "foo",
  431. "method": "bar"
  432. }
  433. ],
  434. "waitForReady": true
  435. }
  436. ]
  437. }
  438. }
  439. ]`,
  440. `[
  441. {
  442. "clientLanguage": [
  443. "CPP",
  444. "JAVA"
  445. ],
  446. "serviceConfig": {
  447. "loadBalancingPolicy": "grpclb",
  448. "methodConfig": [
  449. {
  450. "name": [
  451. {
  452. "service": "all"
  453. }
  454. ],
  455. "timeout": "1s"
  456. }
  457. ]
  458. }
  459. },
  460. {
  461. "percentage": 0,
  462. "serviceConfig": {
  463. "loadBalancingPolicy": "grpclb",
  464. "methodConfig": [
  465. {
  466. "name": [
  467. {
  468. "service": "all"
  469. }
  470. ],
  471. "timeout": "1s"
  472. }
  473. ]
  474. }
  475. },
  476. {
  477. "clientHostName": [
  478. "localhost"
  479. ],
  480. "serviceConfig": {
  481. "loadBalancingPolicy": "grpclb",
  482. "methodConfig": [
  483. {
  484. "name": [
  485. {
  486. "service": "all"
  487. }
  488. ],
  489. "timeout": "1s"
  490. }
  491. ]
  492. }
  493. }
  494. ]`,
  495. }
  496. // scs contains an array of service config string in JSON format.
  497. var scs = []string{
  498. `{
  499. "methodConfig": [
  500. {
  501. "name": [
  502. {
  503. "method": "bar"
  504. }
  505. ],
  506. "maxRequestMessageBytes": 1024,
  507. "maxResponseMessageBytes": 1024
  508. }
  509. ]
  510. }`,
  511. `{
  512. "methodConfig": [
  513. {
  514. "name": [
  515. {
  516. "service": "foo",
  517. "method": "bar"
  518. }
  519. ],
  520. "waitForReady": true,
  521. "timeout": "1s",
  522. "maxRequestMessageBytes": 1024,
  523. "maxResponseMessageBytes": 1024
  524. }
  525. ]
  526. }`,
  527. `{
  528. "loadBalancingPolicy": "round_robin",
  529. "methodConfig": [
  530. {
  531. "name": [
  532. {
  533. "service": "foo"
  534. }
  535. ],
  536. "waitForReady": true,
  537. "timeout": "1s"
  538. },
  539. {
  540. "name": [
  541. {
  542. "service": "bar"
  543. }
  544. ],
  545. "waitForReady": false
  546. }
  547. ]
  548. }`,
  549. }
  550. // scLookupTbl is a set, which contains targets that have service config. Target
  551. // not in this set should not have service config.
  552. var scLookupTbl = map[string]bool{
  553. txtPrefix + "foo.bar.com": true,
  554. txtPrefix + "srv.ipv4.single.fake": true,
  555. txtPrefix + "srv.ipv4.multi.fake": true,
  556. txtPrefix + "no.attribute": true,
  557. }
  558. // generateSCF generates a slice of strings (aggregately representing a single
  559. // service config file) for the input name, which mocks the result from a real
  560. // DNS TXT record lookup.
  561. func generateSCF(name string) []string {
  562. var b []byte
  563. switch name {
  564. case "foo.bar.com":
  565. b = []byte(scfs[0])
  566. case "srv.ipv4.single.fake":
  567. b = []byte(scfs[1])
  568. case "srv.ipv4.multi.fake":
  569. b = []byte(scfs[2])
  570. default:
  571. b = []byte(scfs[3])
  572. }
  573. if name == "no.attribute" {
  574. return div(b)
  575. }
  576. return div(append([]byte(txtAttribute), b...))
  577. }
  578. // generateSC returns a service config string in JSON format for the input name.
  579. func generateSC(name string) string {
  580. _, cnt := scLookupTbl[name]
  581. if !cnt || name == "no.attribute" {
  582. return ""
  583. }
  584. switch name {
  585. case "foo.bar.com":
  586. return scs[0]
  587. case "srv.ipv4.single.fake":
  588. return scs[1]
  589. case "srv.ipv4.multi.fake":
  590. return scs[2]
  591. default:
  592. return ""
  593. }
  594. }
  595. var txtLookupTbl = struct {
  596. sync.Mutex
  597. tbl map[string][]string
  598. }{
  599. tbl: map[string][]string{
  600. "foo.bar.com": generateSCF("foo.bar.com"),
  601. "srv.ipv4.single.fake": generateSCF("srv.ipv4.single.fake"),
  602. "srv.ipv4.multi.fake": generateSCF("srv.ipv4.multi.fake"),
  603. "srv.ipv6.single.fake": generateSCF("srv.ipv6.single.fake"),
  604. "srv.ipv6.multi.fake": generateSCF("srv.ipv6.multi.fake"),
  605. "no.attribute": generateSCF("no.attribute"),
  606. },
  607. }
  608. func txtLookup(host string) ([]string, error) {
  609. txtLookupTbl.Lock()
  610. defer txtLookupTbl.Unlock()
  611. if scs, cnt := txtLookupTbl.tbl[host]; cnt {
  612. return scs, nil
  613. }
  614. return nil, fmt.Errorf("failed to lookup TXT:%s resolution in txtLookupTbl", host)
  615. }
  616. func TestResolve(t *testing.T) {
  617. testDNSResolver(t)
  618. testDNSResolveNow(t)
  619. testIPResolver(t)
  620. }
  621. func testDNSResolver(t *testing.T) {
  622. defer leakcheck.Check(t)
  623. tests := []struct {
  624. target string
  625. addrWant []resolver.Address
  626. scWant string
  627. }{
  628. {
  629. "foo.bar.com",
  630. []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}},
  631. generateSC("foo.bar.com"),
  632. },
  633. {
  634. "foo.bar.com:1234",
  635. []resolver.Address{{Addr: "1.2.3.4:1234"}, {Addr: "5.6.7.8:1234"}},
  636. generateSC("foo.bar.com"),
  637. },
  638. {
  639. "srv.ipv4.single.fake",
  640. []resolver.Address{{Addr: "1.2.3.4:1234", Type: resolver.GRPCLB, ServerName: "ipv4.single.fake"}, {Addr: "2.4.6.8" + colonDefaultPort}},
  641. generateSC("srv.ipv4.single.fake"),
  642. },
  643. {
  644. "srv.ipv4.multi.fake",
  645. []resolver.Address{
  646. {Addr: "1.2.3.4:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"},
  647. {Addr: "5.6.7.8:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"},
  648. {Addr: "9.10.11.12:1234", Type: resolver.GRPCLB, ServerName: "ipv4.multi.fake"},
  649. },
  650. generateSC("srv.ipv4.multi.fake"),
  651. },
  652. {
  653. "srv.ipv6.single.fake",
  654. []resolver.Address{{Addr: "[2607:f8b0:400a:801::1001]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.single.fake"}},
  655. generateSC("srv.ipv6.single.fake"),
  656. },
  657. {
  658. "srv.ipv6.multi.fake",
  659. []resolver.Address{
  660. {Addr: "[2607:f8b0:400a:801::1001]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"},
  661. {Addr: "[2607:f8b0:400a:801::1002]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"},
  662. {Addr: "[2607:f8b0:400a:801::1003]:1234", Type: resolver.GRPCLB, ServerName: "ipv6.multi.fake"},
  663. },
  664. generateSC("srv.ipv6.multi.fake"),
  665. },
  666. {
  667. "no.attribute",
  668. nil,
  669. generateSC("no.attribute"),
  670. },
  671. }
  672. for _, a := range tests {
  673. b := NewBuilder()
  674. cc := &testClientConn{target: a.target}
  675. r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{})
  676. if err != nil {
  677. t.Fatalf("%v\n", err)
  678. }
  679. var addrs []resolver.Address
  680. var cnt int
  681. for {
  682. addrs, cnt = cc.getAddress()
  683. if cnt > 0 {
  684. break
  685. }
  686. time.Sleep(time.Millisecond)
  687. }
  688. var sc string
  689. for {
  690. sc, cnt = cc.getSc()
  691. if cnt > 0 {
  692. break
  693. }
  694. time.Sleep(time.Millisecond)
  695. }
  696. if !reflect.DeepEqual(a.addrWant, addrs) {
  697. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrWant)
  698. }
  699. if !reflect.DeepEqual(a.scWant, sc) {
  700. t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant)
  701. }
  702. r.Close()
  703. }
  704. }
  705. func mutateTbl(target string) func() {
  706. hostLookupTbl.Lock()
  707. oldHostTblEntry := hostLookupTbl.tbl[target]
  708. hostLookupTbl.tbl[target] = hostLookupTbl.tbl[target][:len(oldHostTblEntry)-1]
  709. hostLookupTbl.Unlock()
  710. txtLookupTbl.Lock()
  711. oldTxtTblEntry := txtLookupTbl.tbl[target]
  712. txtLookupTbl.tbl[target] = []string{""}
  713. txtLookupTbl.Unlock()
  714. return func() {
  715. hostLookupTbl.Lock()
  716. hostLookupTbl.tbl[target] = oldHostTblEntry
  717. hostLookupTbl.Unlock()
  718. txtLookupTbl.Lock()
  719. txtLookupTbl.tbl[target] = oldTxtTblEntry
  720. txtLookupTbl.Unlock()
  721. }
  722. }
  723. func testDNSResolveNow(t *testing.T) {
  724. defer leakcheck.Check(t)
  725. tests := []struct {
  726. target string
  727. addrWant []resolver.Address
  728. addrNext []resolver.Address
  729. scWant string
  730. scNext string
  731. }{
  732. {
  733. "foo.bar.com",
  734. []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}, {Addr: "5.6.7.8" + colonDefaultPort}},
  735. []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}},
  736. generateSC("foo.bar.com"),
  737. "",
  738. },
  739. }
  740. for _, a := range tests {
  741. b := NewBuilder()
  742. cc := &testClientConn{target: a.target}
  743. r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{})
  744. if err != nil {
  745. t.Fatalf("%v\n", err)
  746. }
  747. var addrs []resolver.Address
  748. var cnt int
  749. for {
  750. addrs, cnt = cc.getAddress()
  751. if cnt > 0 {
  752. break
  753. }
  754. time.Sleep(time.Millisecond)
  755. }
  756. var sc string
  757. for {
  758. sc, cnt = cc.getSc()
  759. if cnt > 0 {
  760. break
  761. }
  762. time.Sleep(time.Millisecond)
  763. }
  764. if !reflect.DeepEqual(a.addrWant, addrs) {
  765. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrWant)
  766. }
  767. if !reflect.DeepEqual(a.scWant, sc) {
  768. t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant)
  769. }
  770. revertTbl := mutateTbl(a.target)
  771. r.ResolveNow(resolver.ResolveNowOption{})
  772. for {
  773. addrs, cnt = cc.getAddress()
  774. if cnt == 2 {
  775. break
  776. }
  777. time.Sleep(time.Millisecond)
  778. }
  779. for {
  780. sc, cnt = cc.getSc()
  781. if cnt == 2 {
  782. break
  783. }
  784. time.Sleep(time.Millisecond)
  785. }
  786. if !reflect.DeepEqual(a.addrNext, addrs) {
  787. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", a.target, addrs, a.addrNext)
  788. }
  789. if !reflect.DeepEqual(a.scNext, sc) {
  790. t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scNext)
  791. }
  792. revertTbl()
  793. r.Close()
  794. }
  795. }
  796. const colonDefaultPort = ":" + defaultPort
  797. func testIPResolver(t *testing.T) {
  798. defer leakcheck.Check(t)
  799. tests := []struct {
  800. target string
  801. want []resolver.Address
  802. }{
  803. {"127.0.0.1", []resolver.Address{{Addr: "127.0.0.1" + colonDefaultPort}}},
  804. {"127.0.0.1:12345", []resolver.Address{{Addr: "127.0.0.1:12345"}}},
  805. {"::1", []resolver.Address{{Addr: "[::1]" + colonDefaultPort}}},
  806. {"[::1]:12345", []resolver.Address{{Addr: "[::1]:12345"}}},
  807. {"[::1]", []resolver.Address{{Addr: "[::1]:443"}}},
  808. {"2001:db8:85a3::8a2e:370:7334", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
  809. {"[2001:db8:85a3::8a2e:370:7334]", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
  810. {"[2001:db8:85a3::8a2e:370:7334]:12345", []resolver.Address{{Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}},
  811. {"[2001:db8::1]:http", []resolver.Address{{Addr: "[2001:db8::1]:http"}}},
  812. // TODO(yuxuanli): zone support?
  813. }
  814. for _, v := range tests {
  815. b := NewBuilder()
  816. cc := &testClientConn{target: v.target}
  817. r, err := b.Build(resolver.Target{Endpoint: v.target}, cc, resolver.BuildOption{})
  818. if err != nil {
  819. t.Fatalf("%v\n", err)
  820. }
  821. var addrs []resolver.Address
  822. var cnt int
  823. for {
  824. addrs, cnt = cc.getAddress()
  825. if cnt > 0 {
  826. break
  827. }
  828. time.Sleep(time.Millisecond)
  829. }
  830. if !reflect.DeepEqual(v.want, addrs) {
  831. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", v.target, addrs, v.want)
  832. }
  833. r.ResolveNow(resolver.ResolveNowOption{})
  834. for {
  835. addrs, cnt = cc.getAddress()
  836. if cnt == 2 {
  837. break
  838. }
  839. time.Sleep(time.Millisecond)
  840. }
  841. if !reflect.DeepEqual(v.want, addrs) {
  842. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", v.target, addrs, v.want)
  843. }
  844. r.Close()
  845. }
  846. }
  847. func TestResolveFunc(t *testing.T) {
  848. defer leakcheck.Check(t)
  849. tests := []struct {
  850. addr string
  851. want error
  852. }{
  853. // TODO(yuxuanli): More false cases?
  854. {"www.google.com", nil},
  855. {"foo.bar:12345", nil},
  856. {"127.0.0.1", nil},
  857. {"::", nil},
  858. {"127.0.0.1:12345", nil},
  859. {"[::1]:80", nil},
  860. {"[2001:db8:a0b:12f0::1]:21", nil},
  861. {":80", nil},
  862. {"127.0.0...1:12345", nil},
  863. {"[fe80::1%lo0]:80", nil},
  864. {"golang.org:http", nil},
  865. {"[2001:db8::1]:http", nil},
  866. {"[2001:db8::1]:", errEndsWithColon},
  867. {":", errEndsWithColon},
  868. {"", errMissingAddr},
  869. {"[2001:db8:a0b:12f0::1", fmt.Errorf("invalid target address [2001:db8:a0b:12f0::1, error info: address [2001:db8:a0b:12f0::1:443: missing ']' in address")},
  870. }
  871. b := NewBuilder()
  872. for _, v := range tests {
  873. cc := &testClientConn{target: v.addr}
  874. r, err := b.Build(resolver.Target{Endpoint: v.addr}, cc, resolver.BuildOption{})
  875. if err == nil {
  876. r.Close()
  877. }
  878. if !reflect.DeepEqual(err, v.want) {
  879. t.Errorf("Build(%q, cc, resolver.BuildOption{}) = %v, want %v", v.addr, err, v.want)
  880. }
  881. }
  882. }
  883. func TestDisableServiceConfig(t *testing.T) {
  884. defer leakcheck.Check(t)
  885. tests := []struct {
  886. target string
  887. scWant string
  888. disableServiceConfig bool
  889. }{
  890. {
  891. "foo.bar.com",
  892. generateSC("foo.bar.com"),
  893. false,
  894. },
  895. {
  896. "foo.bar.com",
  897. "",
  898. true,
  899. },
  900. }
  901. for _, a := range tests {
  902. b := NewBuilder()
  903. cc := &testClientConn{target: a.target}
  904. r, err := b.Build(resolver.Target{Endpoint: a.target}, cc, resolver.BuildOption{DisableServiceConfig: a.disableServiceConfig})
  905. if err != nil {
  906. t.Fatalf("%v\n", err)
  907. }
  908. var cnt int
  909. var sc string
  910. for {
  911. sc, cnt = cc.getSc()
  912. if cnt > 0 {
  913. break
  914. }
  915. time.Sleep(time.Millisecond)
  916. }
  917. if !reflect.DeepEqual(a.scWant, sc) {
  918. t.Errorf("Resolved service config of target: %q = %+v, want %+v\n", a.target, sc, a.scWant)
  919. }
  920. r.Close()
  921. }
  922. }
  923. func TestDNSResolverRetry(t *testing.T) {
  924. b := NewBuilder()
  925. target := "ipv4.single.fake"
  926. cc := &testClientConn{target: target}
  927. r, err := b.Build(resolver.Target{Endpoint: target}, cc, resolver.BuildOption{})
  928. if err != nil {
  929. t.Fatalf("%v\n", err)
  930. }
  931. var addrs []resolver.Address
  932. for {
  933. addrs, _ = cc.getAddress()
  934. if len(addrs) == 1 {
  935. break
  936. }
  937. time.Sleep(time.Millisecond)
  938. }
  939. want := []resolver.Address{{Addr: "1.2.3.4" + colonDefaultPort}}
  940. if !reflect.DeepEqual(want, addrs) {
  941. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", target, addrs, want)
  942. }
  943. // mutate the host lookup table so the target has 0 address returned.
  944. revertTbl := mutateTbl(target)
  945. // trigger a resolve that will get empty address list
  946. r.ResolveNow(resolver.ResolveNowOption{})
  947. for {
  948. addrs, _ = cc.getAddress()
  949. if len(addrs) == 0 {
  950. break
  951. }
  952. time.Sleep(time.Millisecond)
  953. }
  954. revertTbl()
  955. // wait for the retry to happen in two seconds.
  956. timer := time.NewTimer(2 * time.Second)
  957. for {
  958. b := false
  959. select {
  960. case <-timer.C:
  961. b = true
  962. default:
  963. addrs, _ = cc.getAddress()
  964. if len(addrs) == 1 {
  965. b = true
  966. break
  967. }
  968. time.Sleep(time.Millisecond)
  969. }
  970. if b {
  971. break
  972. }
  973. }
  974. if !reflect.DeepEqual(want, addrs) {
  975. t.Errorf("Resolved addresses of target: %q = %+v, want %+v\n", target, addrs, want)
  976. }
  977. r.Close()
  978. }
  979. func TestCustomAuthority(t *testing.T) {
  980. defer leakcheck.Check(t)
  981. tests := []struct {
  982. authority string
  983. authorityWant string
  984. expectError bool
  985. }{
  986. {
  987. "4.3.2.1:" + defaultDNSSvrPort,
  988. "4.3.2.1:" + defaultDNSSvrPort,
  989. false,
  990. },
  991. {
  992. "4.3.2.1:123",
  993. "4.3.2.1:123",
  994. false,
  995. },
  996. {
  997. "4.3.2.1",
  998. "4.3.2.1:" + defaultDNSSvrPort,
  999. false,
  1000. },
  1001. {
  1002. "::1",
  1003. "[::1]:" + defaultDNSSvrPort,
  1004. false,
  1005. },
  1006. {
  1007. "[::1]",
  1008. "[::1]:" + defaultDNSSvrPort,
  1009. false,
  1010. },
  1011. {
  1012. "[::1]:123",
  1013. "[::1]:123",
  1014. false,
  1015. },
  1016. {
  1017. "dnsserver.com",
  1018. "dnsserver.com:" + defaultDNSSvrPort,
  1019. false,
  1020. },
  1021. {
  1022. ":123",
  1023. "localhost:123",
  1024. false,
  1025. },
  1026. {
  1027. ":",
  1028. "",
  1029. true,
  1030. },
  1031. {
  1032. "[::1]:",
  1033. "",
  1034. true,
  1035. },
  1036. {
  1037. "dnsserver.com:",
  1038. "",
  1039. true,
  1040. },
  1041. }
  1042. oldCustomAuthorityDialler := customAuthorityDialler
  1043. defer func() {
  1044. customAuthorityDialler = oldCustomAuthorityDialler
  1045. }()
  1046. for _, a := range tests {
  1047. errChan := make(chan error, 1)
  1048. customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) {
  1049. if authority != a.authorityWant {
  1050. errChan <- fmt.Errorf("wrong custom authority passed to resolver. input: %s expected: %s actual: %s", a.authority, a.authorityWant, authority)
  1051. } else {
  1052. errChan <- nil
  1053. }
  1054. return func(ctx context.Context, network, address string) (net.Conn, error) {
  1055. return nil, errors.New("no need to dial")
  1056. }
  1057. }
  1058. b := NewBuilder()
  1059. cc := &testClientConn{target: "foo.bar.com"}
  1060. r, err := b.Build(resolver.Target{Endpoint: "foo.bar.com", Authority: a.authority}, cc, resolver.BuildOption{})
  1061. if err == nil {
  1062. r.Close()
  1063. err = <-errChan
  1064. if err != nil {
  1065. t.Errorf(err.Error())
  1066. }
  1067. if a.expectError {
  1068. t.Errorf("custom authority should have caused an error: %s", a.authority)
  1069. }
  1070. } else if !a.expectError {
  1071. t.Errorf("unexpected error using custom authority %s: %s", a.authority, err)
  1072. }
  1073. }
  1074. }