OSDN Git Service

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