dns_resolver_test.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. *
  3. * Copyright 2017 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 naming
  19. import (
  20. "context"
  21. "fmt"
  22. "net"
  23. "reflect"
  24. "sync"
  25. "testing"
  26. "time"
  27. )
  28. func newUpdateWithMD(op Operation, addr, lb string) *Update {
  29. return &Update{
  30. Op: op,
  31. Addr: addr,
  32. Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: lb},
  33. }
  34. }
  35. func toMap(u []*Update) map[string]*Update {
  36. m := make(map[string]*Update)
  37. for _, v := range u {
  38. m[v.Addr] = v
  39. }
  40. return m
  41. }
  42. func TestCompileUpdate(t *testing.T) {
  43. tests := []struct {
  44. oldAddrs []string
  45. newAddrs []string
  46. want []*Update
  47. }{
  48. {
  49. []string{},
  50. []string{"1.0.0.1"},
  51. []*Update{{Op: Add, Addr: "1.0.0.1"}},
  52. },
  53. {
  54. []string{"1.0.0.1"},
  55. []string{"1.0.0.1"},
  56. []*Update{},
  57. },
  58. {
  59. []string{"1.0.0.0"},
  60. []string{"1.0.0.1"},
  61. []*Update{{Op: Delete, Addr: "1.0.0.0"}, {Op: Add, Addr: "1.0.0.1"}},
  62. },
  63. {
  64. []string{"1.0.0.1"},
  65. []string{"1.0.0.0"},
  66. []*Update{{Op: Add, Addr: "1.0.0.0"}, {Op: Delete, Addr: "1.0.0.1"}},
  67. },
  68. {
  69. []string{"1.0.0.1"},
  70. []string{"1.0.0.1", "1.0.0.2", "1.0.0.3"},
  71. []*Update{{Op: Add, Addr: "1.0.0.2"}, {Op: Add, Addr: "1.0.0.3"}},
  72. },
  73. {
  74. []string{"1.0.0.1", "1.0.0.2", "1.0.0.3"},
  75. []string{"1.0.0.0"},
  76. []*Update{{Op: Add, Addr: "1.0.0.0"}, {Op: Delete, Addr: "1.0.0.1"}, {Op: Delete, Addr: "1.0.0.2"}, {Op: Delete, Addr: "1.0.0.3"}},
  77. },
  78. {
  79. []string{"1.0.0.1", "1.0.0.3", "1.0.0.5"},
  80. []string{"1.0.0.2", "1.0.0.3", "1.0.0.6"},
  81. []*Update{{Op: Delete, Addr: "1.0.0.1"}, {Op: Add, Addr: "1.0.0.2"}, {Op: Delete, Addr: "1.0.0.5"}, {Op: Add, Addr: "1.0.0.6"}},
  82. },
  83. {
  84. []string{"1.0.0.1", "1.0.0.1", "1.0.0.2"},
  85. []string{"1.0.0.1"},
  86. []*Update{{Op: Delete, Addr: "1.0.0.2"}},
  87. },
  88. }
  89. var w dnsWatcher
  90. for _, c := range tests {
  91. w.curAddrs = make(map[string]*Update)
  92. newUpdates := make(map[string]*Update)
  93. for _, a := range c.oldAddrs {
  94. w.curAddrs[a] = &Update{Addr: a}
  95. }
  96. for _, a := range c.newAddrs {
  97. newUpdates[a] = &Update{Addr: a}
  98. }
  99. r := w.compileUpdate(newUpdates)
  100. if !reflect.DeepEqual(toMap(c.want), toMap(r)) {
  101. t.Errorf("w(%+v).compileUpdate(%+v) = %+v, want %+v", c.oldAddrs, c.newAddrs, updatesToSlice(r), updatesToSlice(c.want))
  102. }
  103. }
  104. }
  105. func TestResolveFunc(t *testing.T) {
  106. tests := []struct {
  107. addr string
  108. want error
  109. }{
  110. // TODO(yuxuanli): More false cases?
  111. {"www.google.com", nil},
  112. {"foo.bar:12345", nil},
  113. {"127.0.0.1", nil},
  114. {"127.0.0.1:12345", nil},
  115. {"[::1]:80", nil},
  116. {"[2001:db8:a0b:12f0::1]:21", nil},
  117. {":80", nil},
  118. {"127.0.0...1:12345", nil},
  119. {"[fe80::1%lo0]:80", nil},
  120. {"golang.org:http", nil},
  121. {"[2001:db8::1]:http", nil},
  122. {":", nil},
  123. {"", errMissingAddr},
  124. {"[2001:db8:a0b:12f0::1", fmt.Errorf("invalid target address %v", "[2001:db8:a0b:12f0::1")},
  125. }
  126. r, err := NewDNSResolver()
  127. if err != nil {
  128. t.Errorf("%v", err)
  129. }
  130. for _, v := range tests {
  131. _, err := r.Resolve(v.addr)
  132. if !reflect.DeepEqual(err, v.want) {
  133. t.Errorf("Resolve(%q) = %v, want %v", v.addr, err, v.want)
  134. }
  135. }
  136. }
  137. var hostLookupTbl = map[string][]string{
  138. "foo.bar.com": {"1.2.3.4", "5.6.7.8"},
  139. "ipv4.single.fake": {"1.2.3.4"},
  140. "ipv4.multi.fake": {"1.2.3.4", "5.6.7.8", "9.10.11.12"},
  141. "ipv6.single.fake": {"2607:f8b0:400a:801::1001"},
  142. "ipv6.multi.fake": {"2607:f8b0:400a:801::1001", "2607:f8b0:400a:801::1002", "2607:f8b0:400a:801::1003"},
  143. }
  144. func hostLookup(host string) ([]string, error) {
  145. if addrs, ok := hostLookupTbl[host]; ok {
  146. return addrs, nil
  147. }
  148. return nil, fmt.Errorf("failed to lookup host:%s resolution in hostLookupTbl", host)
  149. }
  150. var srvLookupTbl = map[string][]*net.SRV{
  151. "_grpclb._tcp.srv.ipv4.single.fake": {&net.SRV{Target: "ipv4.single.fake", Port: 1234}},
  152. "_grpclb._tcp.srv.ipv4.multi.fake": {&net.SRV{Target: "ipv4.multi.fake", Port: 1234}},
  153. "_grpclb._tcp.srv.ipv6.single.fake": {&net.SRV{Target: "ipv6.single.fake", Port: 1234}},
  154. "_grpclb._tcp.srv.ipv6.multi.fake": {&net.SRV{Target: "ipv6.multi.fake", Port: 1234}},
  155. }
  156. func srvLookup(service, proto, name string) (string, []*net.SRV, error) {
  157. cname := "_" + service + "._" + proto + "." + name
  158. if srvs, ok := srvLookupTbl[cname]; ok {
  159. return cname, srvs, nil
  160. }
  161. return "", nil, fmt.Errorf("failed to lookup srv record for %s in srvLookupTbl", cname)
  162. }
  163. func updatesToSlice(updates []*Update) []Update {
  164. res := make([]Update, len(updates))
  165. for i, u := range updates {
  166. res[i] = *u
  167. }
  168. return res
  169. }
  170. func testResolver(t *testing.T, freq time.Duration, slp time.Duration) {
  171. tests := []struct {
  172. target string
  173. want []*Update
  174. }{
  175. {
  176. "foo.bar.com",
  177. []*Update{{Op: Add, Addr: "1.2.3.4" + colonDefaultPort}, {Op: Add, Addr: "5.6.7.8" + colonDefaultPort}},
  178. },
  179. {
  180. "foo.bar.com:1234",
  181. []*Update{{Op: Add, Addr: "1.2.3.4:1234"}, {Op: Add, Addr: "5.6.7.8:1234"}},
  182. },
  183. {
  184. "srv.ipv4.single.fake",
  185. []*Update{newUpdateWithMD(Add, "1.2.3.4:1234", "ipv4.single.fake")},
  186. },
  187. {
  188. "srv.ipv4.multi.fake",
  189. []*Update{
  190. newUpdateWithMD(Add, "1.2.3.4:1234", "ipv4.multi.fake"),
  191. newUpdateWithMD(Add, "5.6.7.8:1234", "ipv4.multi.fake"),
  192. newUpdateWithMD(Add, "9.10.11.12:1234", "ipv4.multi.fake")},
  193. },
  194. {
  195. "srv.ipv6.single.fake",
  196. []*Update{newUpdateWithMD(Add, "[2607:f8b0:400a:801::1001]:1234", "ipv6.single.fake")},
  197. },
  198. {
  199. "srv.ipv6.multi.fake",
  200. []*Update{
  201. newUpdateWithMD(Add, "[2607:f8b0:400a:801::1001]:1234", "ipv6.multi.fake"),
  202. newUpdateWithMD(Add, "[2607:f8b0:400a:801::1002]:1234", "ipv6.multi.fake"),
  203. newUpdateWithMD(Add, "[2607:f8b0:400a:801::1003]:1234", "ipv6.multi.fake"),
  204. },
  205. },
  206. }
  207. for _, a := range tests {
  208. r, err := NewDNSResolverWithFreq(freq)
  209. if err != nil {
  210. t.Fatalf("%v\n", err)
  211. }
  212. w, err := r.Resolve(a.target)
  213. if err != nil {
  214. t.Fatalf("%v\n", err)
  215. }
  216. updates, err := w.Next()
  217. if err != nil {
  218. t.Fatalf("%v\n", err)
  219. }
  220. if !reflect.DeepEqual(toMap(a.want), toMap(updates)) {
  221. t.Errorf("Resolve(%q) = %+v, want %+v\n", a.target, updatesToSlice(updates), updatesToSlice(a.want))
  222. }
  223. var wg sync.WaitGroup
  224. wg.Add(1)
  225. go func() {
  226. defer wg.Done()
  227. for {
  228. _, err := w.Next()
  229. if err != nil {
  230. return
  231. }
  232. t.Error("Execution shouldn't reach here, since w.Next() should be blocked until close happen.")
  233. }
  234. }()
  235. // Sleep for sometime to let watcher do more than one lookup
  236. time.Sleep(slp)
  237. w.Close()
  238. wg.Wait()
  239. }
  240. }
  241. func replaceNetFunc() func() {
  242. oldLookupHost := lookupHost
  243. oldLookupSRV := lookupSRV
  244. lookupHost = func(ctx context.Context, host string) ([]string, error) {
  245. return hostLookup(host)
  246. }
  247. lookupSRV = func(ctx context.Context, service, proto, name string) (string, []*net.SRV, error) {
  248. return srvLookup(service, proto, name)
  249. }
  250. return func() {
  251. lookupHost = oldLookupHost
  252. lookupSRV = oldLookupSRV
  253. }
  254. }
  255. func TestResolve(t *testing.T) {
  256. defer replaceNetFunc()()
  257. testResolver(t, time.Millisecond*5, time.Millisecond*10)
  258. }
  259. const colonDefaultPort = ":" + defaultPort
  260. func TestIPWatcher(t *testing.T) {
  261. tests := []struct {
  262. target string
  263. want []*Update
  264. }{
  265. {"127.0.0.1", []*Update{{Op: Add, Addr: "127.0.0.1" + colonDefaultPort}}},
  266. {"127.0.0.1:12345", []*Update{{Op: Add, Addr: "127.0.0.1:12345"}}},
  267. {"::1", []*Update{{Op: Add, Addr: "[::1]" + colonDefaultPort}}},
  268. {"[::1]:12345", []*Update{{Op: Add, Addr: "[::1]:12345"}}},
  269. {"[::1]:", []*Update{{Op: Add, Addr: "[::1]:443"}}},
  270. {"2001:db8:85a3::8a2e:370:7334", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
  271. {"[2001:db8:85a3::8a2e:370:7334]", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]" + colonDefaultPort}}},
  272. {"[2001:db8:85a3::8a2e:370:7334]:12345", []*Update{{Op: Add, Addr: "[2001:db8:85a3::8a2e:370:7334]:12345"}}},
  273. {"[2001:db8::1]:http", []*Update{{Op: Add, Addr: "[2001:db8::1]:http"}}},
  274. // TODO(yuxuanli): zone support?
  275. }
  276. for _, v := range tests {
  277. r, err := NewDNSResolverWithFreq(time.Millisecond * 5)
  278. if err != nil {
  279. t.Fatalf("%v\n", err)
  280. }
  281. w, err := r.Resolve(v.target)
  282. if err != nil {
  283. t.Fatalf("%v\n", err)
  284. }
  285. var updates []*Update
  286. var wg sync.WaitGroup
  287. wg.Add(1)
  288. count := 0
  289. go func() {
  290. defer wg.Done()
  291. for {
  292. u, err := w.Next()
  293. if err != nil {
  294. return
  295. }
  296. updates = u
  297. count++
  298. }
  299. }()
  300. // Sleep for sometime to let watcher do more than one lookup
  301. time.Sleep(time.Millisecond * 10)
  302. w.Close()
  303. wg.Wait()
  304. if !reflect.DeepEqual(v.want, updates) {
  305. t.Errorf("Resolve(%q) = %v, want %+v\n", v.target, updatesToSlice(updates), updatesToSlice(v.want))
  306. }
  307. if count != 1 {
  308. t.Errorf("IPWatcher Next() should return only once, not %d times\n", count)
  309. }
  310. }
  311. }