1
18
19 package priority
20
21 import (
22 "context"
23 "fmt"
24 "testing"
25 "time"
26
27 "google.golang.org/grpc/balancer"
28 "google.golang.org/grpc/balancer/roundrobin"
29 "google.golang.org/grpc/connectivity"
30 "google.golang.org/grpc/internal/balancer/stub"
31 "google.golang.org/grpc/internal/grpctest"
32 "google.golang.org/grpc/internal/hierarchy"
33 internalserviceconfig "google.golang.org/grpc/internal/serviceconfig"
34 "google.golang.org/grpc/internal/testutils"
35 "google.golang.org/grpc/resolver"
36 )
37
38 const (
39 defaultTestTimeout = 5 * time.Second
40 defaultTestShortTimeout = 100 * time.Millisecond
41 )
42
43 type s struct {
44 grpctest.Tester
45 }
46
47 func Test(t *testing.T) {
48 grpctest.RunSubTests(t, s{})
49 }
50
51 var testBackendAddrStrs []string
52
53 const (
54 testBackendAddrsCount = 12
55 testRRBalancerName = "another-round-robin"
56 )
57
58 type anotherRR struct {
59 balancer.Builder
60 }
61
62 func (*anotherRR) Name() string {
63 return testRRBalancerName
64 }
65
66 func init() {
67 for i := 0; i < testBackendAddrsCount; i++ {
68 testBackendAddrStrs = append(testBackendAddrStrs, fmt.Sprintf("%d.%d.%d.%d:%d", i, i, i, i, i))
69 }
70
71
72 DefaultSubBalancerCloseTimeout = time.Duration(0)
73 balancer.Register(&anotherRR{Builder: balancer.Get(roundrobin.Name)})
74 }
75
76
77
78
79
80 func (s) TestPriority_HighPriorityReady(t *testing.T) {
81 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
82 defer cancel()
83
84 cc := testutils.NewBalancerClientConn(t)
85 bb := balancer.Get(Name)
86 pb := bb.Build(cc, balancer.BuildOptions{})
87 defer pb.Close()
88
89
90 if err := pb.UpdateClientConnState(balancer.ClientConnState{
91 ResolverState: resolver.State{
92 Addresses: []resolver.Address{
93 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
94 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
95 },
96 },
97 BalancerConfig: &LBConfig{
98 Children: map[string]*Child{
99 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
100 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
101 },
102 Priorities: []string{"child-0", "child-1"},
103 },
104 }); err != nil {
105 t.Fatalf("failed to update ClientConn state: %v", err)
106 }
107
108 addrs1 := <-cc.NewSubConnAddrsCh
109 if got, want := addrs1[0].Addr, testBackendAddrStrs[0]; got != want {
110 t.Fatalf("sc is created with addr %v, want %v", got, want)
111 }
112 sc1 := <-cc.NewSubConnCh
113
114
115 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
116 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
117
118
119 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
120 t.Fatal(err.Error())
121 }
122
123
124 if err := pb.UpdateClientConnState(balancer.ClientConnState{
125 ResolverState: resolver.State{
126 Addresses: []resolver.Address{
127 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
128 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
129 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-2"}),
130 },
131 },
132 BalancerConfig: &LBConfig{
133 Children: map[string]*Child{
134 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
135 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
136 "child-2": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
137 },
138 Priorities: []string{"child-0", "child-1", "child-2"},
139 },
140 }); err != nil {
141 t.Fatalf("failed to update ClientConn state: %v", err)
142 }
143
144 select {
145 case sc := <-cc.NewSubConnCh:
146 t.Fatalf("got unexpected new SubConn: %s", sc)
147 case sc := <-cc.ShutdownSubConnCh:
148 t.Fatalf("got unexpected shutdown SubConn: %v", sc)
149 case <-time.After(time.Millisecond * 100):
150 }
151
152
153 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
154 t.Fatal(err.Error())
155 }
156
157
158 if err := pb.UpdateClientConnState(balancer.ClientConnState{
159 ResolverState: resolver.State{
160 Addresses: []resolver.Address{
161 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
162 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
163 },
164 },
165 BalancerConfig: &LBConfig{
166 Children: map[string]*Child{
167 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
168 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
169 },
170 Priorities: []string{"child-0", "child-1"},
171 },
172 }); err != nil {
173 t.Fatalf("failed to update ClientConn state: %v", err)
174 }
175
176 select {
177 case <-cc.NewSubConnCh:
178 t.Fatalf("got unexpected new SubConn")
179 case <-cc.ShutdownSubConnCh:
180 t.Fatalf("got unexpected shutdown SubConn")
181 case <-time.After(time.Millisecond * 100):
182 }
183
184
185 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
186 t.Fatal(err.Error())
187 }
188 }
189
190
191
192
193
194 func (s) TestPriority_SwitchPriority(t *testing.T) {
195 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
196 defer cancel()
197
198 cc := testutils.NewBalancerClientConn(t)
199 bb := balancer.Get(Name)
200 pb := bb.Build(cc, balancer.BuildOptions{})
201 defer pb.Close()
202
203 t.Log("Two localities, with priorities [0, 1], each with one backend.")
204 if err := pb.UpdateClientConnState(balancer.ClientConnState{
205 ResolverState: resolver.State{
206 Addresses: []resolver.Address{
207 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
208 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
209 },
210 },
211 BalancerConfig: &LBConfig{
212 Children: map[string]*Child{
213 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
214 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
215 },
216 Priorities: []string{"child-0", "child-1"},
217 },
218 }); err != nil {
219 t.Fatalf("failed to update ClientConn state: %v", err)
220 }
221
222 addrs0 := <-cc.NewSubConnAddrsCh
223 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
224 t.Fatalf("sc is created with addr %v, want %v", got, want)
225 }
226 sc0 := <-cc.NewSubConnCh
227
228 t.Log("Make p0 ready.")
229 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
230 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
231
232
233 if err := cc.WaitForRoundRobinPicker(ctx, sc0); err != nil {
234 t.Fatal(err.Error())
235 }
236
237 t.Log("Turn down 0, will start and use 1.")
238 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
239
240
241 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
242 t.Fatal(err.Error())
243 }
244
245 t.Log("Handle SubConn creation from 1.")
246 addrs1 := <-cc.NewSubConnAddrsCh
247 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
248 t.Fatalf("sc is created with addr %v, want %v", got, want)
249 }
250 sc1 := <-cc.NewSubConnCh
251 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
252 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
253
254
255 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
256 t.Fatal(err.Error())
257 }
258
259 t.Log("Add p2, it shouldn't cause any updates.")
260 if err := pb.UpdateClientConnState(balancer.ClientConnState{
261 ResolverState: resolver.State{
262 Addresses: []resolver.Address{
263 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
264 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
265 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-2"}),
266 },
267 },
268 BalancerConfig: &LBConfig{
269 Children: map[string]*Child{
270 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
271 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
272 "child-2": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
273 },
274 Priorities: []string{"child-0", "child-1", "child-2"},
275 },
276 }); err != nil {
277 t.Fatalf("failed to update ClientConn state: %v", err)
278 }
279
280 select {
281 case sc := <-cc.NewSubConnCh:
282 t.Fatalf("got unexpected new SubConn, %s", sc)
283 case <-cc.ShutdownSubConnCh:
284 t.Fatalf("got unexpected shutdown SubConn")
285 case <-time.After(time.Millisecond * 100):
286 }
287
288 t.Log("Turn down 1, use 2.")
289 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
290
291
292
293 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
294 t.Fatal(err.Error())
295 }
296
297 addrs2 := <-cc.NewSubConnAddrsCh
298 if got, want := addrs2[0].Addr, testBackendAddrStrs[2]; got != want {
299 t.Fatalf("sc is created with addr %v, want %v", got, want)
300 }
301 sc2 := <-cc.NewSubConnCh
302 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
303 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
304
305
306 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
307 t.Fatal(err.Error())
308 }
309
310 t.Log("Remove 2, use 1.")
311 if err := pb.UpdateClientConnState(balancer.ClientConnState{
312 ResolverState: resolver.State{
313 Addresses: []resolver.Address{
314 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
315 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
316 },
317 },
318 BalancerConfig: &LBConfig{
319 Children: map[string]*Child{
320 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
321 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
322 },
323 Priorities: []string{"child-0", "child-1"},
324 },
325 }); err != nil {
326 t.Fatalf("failed to update ClientConn state: %v", err)
327 }
328
329
330 scToShutdown := <-cc.ShutdownSubConnCh
331 if scToShutdown != sc2 {
332 t.Fatalf("ShutdownSubConn, want %v, got %v", sc2, scToShutdown)
333 }
334
335
336
337 if err := cc.WaitForErrPicker(ctx); err != nil {
338 t.Fatal(err.Error())
339 }
340 <-cc.NewStateCh
341
342 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
343
344
345 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
346
347 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
348 t.Fatal(err.Error())
349 }
350 }
351
352
353
354
355
356
357 func (s) TestPriority_HighPriorityToConnectingFromReady(t *testing.T) {
358 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
359 defer cancel()
360
361 cc := testutils.NewBalancerClientConn(t)
362 bb := balancer.Get(Name)
363 pb := bb.Build(cc, balancer.BuildOptions{})
364 defer pb.Close()
365
366
367 if err := pb.UpdateClientConnState(balancer.ClientConnState{
368 ResolverState: resolver.State{
369 Addresses: []resolver.Address{
370 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
371 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
372 },
373 },
374 BalancerConfig: &LBConfig{
375 Children: map[string]*Child{
376 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
377 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
378 },
379 Priorities: []string{"child-0", "child-1"},
380 },
381 }); err != nil {
382 t.Fatalf("failed to update ClientConn state: %v", err)
383 }
384
385 addrs0 := <-cc.NewSubConnAddrsCh
386 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
387 t.Fatalf("sc is created with addr %v, want %v", got, want)
388 }
389 sc0 := <-cc.NewSubConnCh
390
391
392 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
393 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
394
395
396 if err := cc.WaitForRoundRobinPicker(ctx, sc0); err != nil {
397 t.Fatal(err.Error())
398 }
399
400
401 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
402
403
404
405 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
406 t.Fatal(err.Error())
407 }
408
409
410 addrs1 := <-cc.NewSubConnAddrsCh
411 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
412 t.Fatalf("sc is created with addr %v, want %v", got, want)
413 }
414 sc1 := <-cc.NewSubConnCh
415 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
416 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
417
418
419 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
420 t.Fatal(err.Error())
421 }
422
423
424 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
425 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
426
427
428 scToShutdown := <-cc.ShutdownSubConnCh
429 if scToShutdown != sc1 {
430 t.Fatalf("ShutdownSubConn, want %v, got %v", sc0, scToShutdown)
431 }
432
433 if err := cc.WaitForRoundRobinPicker(ctx, sc0); err != nil {
434 t.Fatal(err.Error())
435 }
436 }
437
438
439
440
441 func (s) TestPriority_HigherDownWhileAddingLower(t *testing.T) {
442 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
443 defer cancel()
444
445 cc := testutils.NewBalancerClientConn(t)
446 bb := balancer.Get(Name)
447 pb := bb.Build(cc, balancer.BuildOptions{})
448 defer pb.Close()
449
450
451 if err := pb.UpdateClientConnState(balancer.ClientConnState{
452 ResolverState: resolver.State{
453 Addresses: []resolver.Address{
454 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
455 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
456 },
457 },
458 BalancerConfig: &LBConfig{
459 Children: map[string]*Child{
460 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
461 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
462 },
463 Priorities: []string{"child-0", "child-1"},
464 },
465 }); err != nil {
466 t.Fatalf("failed to update ClientConn state: %v", err)
467 }
468
469 addrs0 := <-cc.NewSubConnAddrsCh
470 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
471 t.Fatalf("sc is created with addr %v, want %v", got, want)
472 }
473 sc0 := <-cc.NewSubConnCh
474
475 t.Log("Turn down 0, 1 is used.")
476 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
477
478
479
480 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
481 t.Fatal(err.Error())
482 }
483
484 addrs1 := <-cc.NewSubConnAddrsCh
485 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
486 t.Fatalf("sc is created with addr %v, want %v", got, want)
487 }
488 sc1 := <-cc.NewSubConnCh
489
490 t.Log("Turn down 1, pick should error.")
491 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
492
493
494 if err := cc.WaitForErrPicker(ctx); err != nil {
495 t.Fatal(err.Error())
496 }
497 <-cc.NewStateCh
498
499 t.Log("Add p2, it should create a new SubConn.")
500 if err := pb.UpdateClientConnState(balancer.ClientConnState{
501 ResolverState: resolver.State{
502 Addresses: []resolver.Address{
503 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
504 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
505 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-2"}),
506 },
507 },
508 BalancerConfig: &LBConfig{
509 Children: map[string]*Child{
510 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
511 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
512 "child-2": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
513 },
514 Priorities: []string{"child-0", "child-1", "child-2"},
515 },
516 }); err != nil {
517 t.Fatalf("failed to update ClientConn state: %v", err)
518 }
519
520
521 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
522 t.Fatal(err.Error())
523 }
524
525 addrs2 := <-cc.NewSubConnAddrsCh
526 if got, want := addrs2[0].Addr, testBackendAddrStrs[2]; got != want {
527 t.Fatalf("sc is created with addr %v, want %v", got, want)
528 }
529 sc2 := <-cc.NewSubConnCh
530 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
531 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
532
533
534 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
535 t.Fatal(err.Error())
536 }
537 }
538
539
540
541
542 func (s) TestPriority_HigherReadyCloseAllLower(t *testing.T) {
543 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
544 defer cancel()
545
546 cc := testutils.NewBalancerClientConn(t)
547 bb := balancer.Get(Name)
548 pb := bb.Build(cc, balancer.BuildOptions{})
549 defer pb.Close()
550
551
552 if err := pb.UpdateClientConnState(balancer.ClientConnState{
553 ResolverState: resolver.State{
554 Addresses: []resolver.Address{
555 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
556 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
557 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-2"}),
558 },
559 },
560 BalancerConfig: &LBConfig{
561 Children: map[string]*Child{
562 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
563 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
564 "child-2": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
565 },
566 Priorities: []string{"child-0", "child-1", "child-2"},
567 },
568 }); err != nil {
569 t.Fatalf("failed to update ClientConn state: %v", err)
570 }
571
572 addrs0 := <-cc.NewSubConnAddrsCh
573 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
574 t.Fatalf("sc is created with addr %v, want %v", got, want)
575 }
576 sc0 := <-cc.NewSubConnCh
577
578
579 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
580
581
582 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
583 t.Fatal(err.Error())
584 }
585
586 addrs1 := <-cc.NewSubConnAddrsCh
587 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
588 t.Fatalf("sc is created with addr %v, want %v", got, want)
589 }
590 sc1 := <-cc.NewSubConnCh
591
592
593 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
594
595
596 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
597 t.Fatal(err.Error())
598 }
599
600 addrs2 := <-cc.NewSubConnAddrsCh
601 if got, want := addrs2[0].Addr, testBackendAddrStrs[2]; got != want {
602 t.Fatalf("sc is created with addr %v, want %v", got, want)
603 }
604 sc2 := <-cc.NewSubConnCh
605 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
606 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
607
608
609 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
610 t.Fatal(err.Error())
611 }
612
613
614 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
615
616
617
618
619
620 scToShutdown := []balancer.SubConn{<-cc.ShutdownSubConnCh, <-cc.ShutdownSubConnCh}
621 if !(scToShutdown[0] == sc1 && scToShutdown[1] == sc2) && !(scToShutdown[0] == sc2 && scToShutdown[1] == sc1) {
622 t.Errorf("ShutdownSubConn, want [%v, %v], got %v", sc1, sc2, scToShutdown)
623 }
624
625
626 if err := cc.WaitForRoundRobinPicker(ctx, sc0); err != nil {
627 t.Fatal(err.Error())
628 }
629 }
630
631
632
633
634
635 func (s) TestPriority_InitTimeout(t *testing.T) {
636 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
637 defer cancel()
638
639 const testPriorityInitTimeout = 200 * time.Millisecond
640 defer func() func() {
641 old := DefaultPriorityInitTimeout
642 DefaultPriorityInitTimeout = testPriorityInitTimeout
643 return func() {
644 DefaultPriorityInitTimeout = old
645 }
646 }()()
647
648 cc := testutils.NewBalancerClientConn(t)
649 bb := balancer.Get(Name)
650 pb := bb.Build(cc, balancer.BuildOptions{})
651 defer pb.Close()
652
653
654 if err := pb.UpdateClientConnState(balancer.ClientConnState{
655 ResolverState: resolver.State{
656 Addresses: []resolver.Address{
657 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
658 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
659 },
660 },
661 BalancerConfig: &LBConfig{
662 Children: map[string]*Child{
663 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
664 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
665 },
666 Priorities: []string{"child-0", "child-1"},
667 },
668 }); err != nil {
669 t.Fatalf("failed to update ClientConn state: %v", err)
670 }
671
672 addrs0 := <-cc.NewSubConnAddrsCh
673 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
674 t.Fatalf("sc is created with addr %v, want %v", got, want)
675 }
676 sc0 := <-cc.NewSubConnCh
677
678
679 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
680
681
682 select {
683 case <-time.After(testPriorityInitTimeout * 3 / 4):
684 case <-cc.NewSubConnAddrsCh:
685 t.Fatalf("Got a new SubConn too early (Within timeout). Expect a new SubConn only after timeout")
686 }
687
688 addrs1 := <-cc.NewSubConnAddrsCh
689 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
690 t.Fatalf("sc is created with addr %v, want %v", got, want)
691 }
692 sc1 := <-cc.NewSubConnCh
693
694
695
696 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
697 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
698
699
700 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
701 t.Fatal(err.Error())
702 }
703 }
704
705
706 func (s) TestPriority_RemovesAllPriorities(t *testing.T) {
707 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
708 defer cancel()
709
710 const testPriorityInitTimeout = 200 * time.Millisecond
711 defer func() func() {
712 old := DefaultPriorityInitTimeout
713 DefaultPriorityInitTimeout = testPriorityInitTimeout
714 return func() {
715 DefaultPriorityInitTimeout = old
716 }
717 }()()
718
719 cc := testutils.NewBalancerClientConn(t)
720 bb := balancer.Get(Name)
721 pb := bb.Build(cc, balancer.BuildOptions{})
722 defer pb.Close()
723
724
725 if err := pb.UpdateClientConnState(balancer.ClientConnState{
726 ResolverState: resolver.State{
727 Addresses: []resolver.Address{
728 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
729 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
730 },
731 },
732 BalancerConfig: &LBConfig{
733 Children: map[string]*Child{
734 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
735 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
736 },
737 Priorities: []string{"child-0", "child-1"},
738 },
739 }); err != nil {
740 t.Fatalf("failed to update ClientConn state: %v", err)
741 }
742
743 addrs0 := <-cc.NewSubConnAddrsCh
744 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
745 t.Fatalf("sc is created with addr %v, want %v", got, want)
746 }
747 sc0 := <-cc.NewSubConnCh
748 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
749 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
750
751
752 if err := cc.WaitForRoundRobinPicker(ctx, sc0); err != nil {
753 t.Fatal(err.Error())
754 }
755
756
757 if err := pb.UpdateClientConnState(balancer.ClientConnState{
758 ResolverState: resolver.State{
759 Addresses: nil,
760 },
761 BalancerConfig: &LBConfig{
762 Children: nil,
763 Priorities: nil,
764 },
765 }); err != nil {
766 t.Fatalf("failed to update ClientConn state: %v", err)
767 }
768
769
770 scToShutdown := <-cc.ShutdownSubConnCh
771 if scToShutdown != sc0 {
772 t.Fatalf("ShutdownSubConn, want %v, got %v", sc0, scToShutdown)
773 }
774
775
776 if err := cc.WaitForPickerWithErr(ctx, ErrAllPrioritiesRemoved); err != nil {
777 t.Fatal(err.Error())
778 }
779
780
781 if err := pb.UpdateClientConnState(balancer.ClientConnState{
782 ResolverState: resolver.State{
783 Addresses: []resolver.Address{
784 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-0"}),
785 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[3]}, []string{"child-1"}),
786 },
787 },
788 BalancerConfig: &LBConfig{
789 Children: map[string]*Child{
790 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
791 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
792 },
793 Priorities: []string{"child-0", "child-1"},
794 },
795 }); err != nil {
796 t.Fatalf("failed to update ClientConn state: %v", err)
797 }
798
799 addrs01 := <-cc.NewSubConnAddrsCh
800 if got, want := addrs01[0].Addr, testBackendAddrStrs[2]; got != want {
801 t.Fatalf("sc is created with addr %v, want %v", got, want)
802 }
803 sc01 := <-cc.NewSubConnCh
804
805
806
807
808
809
810 addrs11 := <-cc.NewSubConnAddrsCh
811 if got, want := addrs11[0].Addr, testBackendAddrStrs[3]; got != want {
812 t.Fatalf("sc is created with addr %v, want %v", got, want)
813 }
814 sc11 := <-cc.NewSubConnCh
815 sc11.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
816 sc11.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
817
818
819 if err := cc.WaitForRoundRobinPicker(ctx, sc11); err != nil {
820 t.Fatal(err.Error())
821 }
822
823
824 if err := pb.UpdateClientConnState(balancer.ClientConnState{
825 ResolverState: resolver.State{
826 Addresses: []resolver.Address{
827 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-0"}),
828 },
829 },
830 BalancerConfig: &LBConfig{
831 Children: map[string]*Child{
832 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
833 },
834 Priorities: []string{"child-0"},
835 },
836 }); err != nil {
837 t.Fatalf("failed to update ClientConn state: %v", err)
838 }
839
840
841 scToShutdown1 := <-cc.ShutdownSubConnCh
842 if scToShutdown1 != sc11 {
843 t.Fatalf("ShutdownSubConn, want %v, got %v", sc11, scToShutdown1)
844 }
845
846
847 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
848 t.Fatal(err.Error())
849 }
850
851
852
853 sc01.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
854 sc01.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
855
856
857 if err := cc.WaitForRoundRobinPicker(ctx, sc01); err != nil {
858 t.Fatal(err.Error())
859 }
860
861 select {
862 case <-cc.NewPickerCh:
863 t.Fatalf("got unexpected new picker")
864 case <-cc.NewSubConnCh:
865 t.Fatalf("got unexpected new SubConn")
866 case <-cc.ShutdownSubConnCh:
867 t.Fatalf("got unexpected shutdown SubConn")
868 case <-time.After(time.Millisecond * 100):
869 }
870 }
871
872
873
874 func (s) TestPriority_HighPriorityNoEndpoints(t *testing.T) {
875 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
876 defer cancel()
877
878 cc := testutils.NewBalancerClientConn(t)
879 bb := balancer.Get(Name)
880 pb := bb.Build(cc, balancer.BuildOptions{})
881 defer pb.Close()
882
883
884 if err := pb.UpdateClientConnState(balancer.ClientConnState{
885 ResolverState: resolver.State{
886 Addresses: []resolver.Address{
887 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
888 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
889 },
890 },
891 BalancerConfig: &LBConfig{
892 Children: map[string]*Child{
893 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
894 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
895 },
896 Priorities: []string{"child-0", "child-1"},
897 },
898 }); err != nil {
899 t.Fatalf("failed to update ClientConn state: %v", err)
900 }
901
902 addrs1 := <-cc.NewSubConnAddrsCh
903 if got, want := addrs1[0].Addr, testBackendAddrStrs[0]; got != want {
904 t.Fatalf("sc is created with addr %v, want %v", got, want)
905 }
906 sc1 := <-cc.NewSubConnCh
907
908
909 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
910 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
911
912
913 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
914 t.Fatal(err.Error())
915 }
916
917
918 if err := pb.UpdateClientConnState(balancer.ClientConnState{
919 ResolverState: resolver.State{
920 Addresses: []resolver.Address{
921 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
922 },
923 },
924 BalancerConfig: &LBConfig{
925 Children: map[string]*Child{
926 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
927 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
928 },
929 Priorities: []string{"child-0", "child-1"},
930 },
931 }); err != nil {
932 t.Fatalf("failed to update ClientConn state: %v", err)
933 }
934
935
936
937 scToShutdown := <-cc.ShutdownSubConnCh
938 scToShutdown.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Shutdown})
939
940 addrs2 := <-cc.NewSubConnAddrsCh
941 if got, want := addrs2[0].Addr, testBackendAddrStrs[1]; got != want {
942 t.Fatalf("sc is created with addr %v, want %v", got, want)
943 }
944 sc2 := <-cc.NewSubConnCh
945
946
947
948 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
949 t.Fatal(err.Error())
950 }
951
952
953 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
954 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
955
956
957 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
958 t.Fatal(err.Error())
959 }
960 }
961
962
963 func (s) TestPriority_FirstPriorityUnavailable(t *testing.T) {
964 const testPriorityInitTimeout = 200 * time.Millisecond
965 defer func(t time.Duration) {
966 DefaultPriorityInitTimeout = t
967 }(DefaultPriorityInitTimeout)
968 DefaultPriorityInitTimeout = testPriorityInitTimeout
969
970 cc := testutils.NewBalancerClientConn(t)
971 bb := balancer.Get(Name)
972 pb := bb.Build(cc, balancer.BuildOptions{})
973 defer pb.Close()
974
975
976 if err := pb.UpdateClientConnState(balancer.ClientConnState{
977 ResolverState: resolver.State{
978 Addresses: []resolver.Address{
979 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
980 },
981 },
982 BalancerConfig: &LBConfig{
983 Children: map[string]*Child{
984 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
985 },
986 Priorities: []string{"child-0"},
987 },
988 }); err != nil {
989 t.Fatalf("failed to update ClientConn state: %v", err)
990 }
991
992
993 if err := pb.UpdateClientConnState(balancer.ClientConnState{
994 ResolverState: resolver.State{
995 Addresses: nil,
996 },
997 BalancerConfig: &LBConfig{
998 Children: nil,
999 Priorities: nil,
1000 },
1001 }); err != nil {
1002 t.Fatalf("failed to update ClientConn state: %v", err)
1003 }
1004
1005
1006 time.Sleep(testPriorityInitTimeout * 2)
1007 }
1008
1009
1010
1011
1012 func (s) TestPriority_MoveChildToHigherPriority(t *testing.T) {
1013 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1014 defer cancel()
1015
1016 cc := testutils.NewBalancerClientConn(t)
1017 bb := balancer.Get(Name)
1018 pb := bb.Build(cc, balancer.BuildOptions{})
1019 defer pb.Close()
1020
1021
1022 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1023 ResolverState: resolver.State{
1024 Addresses: []resolver.Address{
1025 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1026 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1027 },
1028 },
1029 BalancerConfig: &LBConfig{
1030 Children: map[string]*Child{
1031 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1032 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1033 },
1034 Priorities: []string{"child-0", "child-1"},
1035 },
1036 }); err != nil {
1037 t.Fatalf("failed to update ClientConn state: %v", err)
1038 }
1039
1040 addrs1 := <-cc.NewSubConnAddrsCh
1041 if got, want := addrs1[0].Addr, testBackendAddrStrs[0]; got != want {
1042 t.Fatalf("sc is created with addr %v, want %v", got, want)
1043 }
1044 sc1 := <-cc.NewSubConnCh
1045
1046
1047 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1048 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1049
1050
1051 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1052 t.Fatal(err.Error())
1053 }
1054
1055
1056
1057 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1058 ResolverState: resolver.State{
1059 Addresses: []resolver.Address{
1060 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1061 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1062 },
1063 },
1064 BalancerConfig: &LBConfig{
1065 Children: map[string]*Child{
1066 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1067 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1068 },
1069 Priorities: []string{"child-1", "child-0"},
1070 },
1071 }); err != nil {
1072 t.Fatalf("failed to update ClientConn state: %v", err)
1073 }
1074
1075
1076
1077
1078
1079 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
1080 t.Fatal(err.Error())
1081 }
1082
1083
1084 scToShutdown := <-cc.ShutdownSubConnCh
1085 if scToShutdown != sc1 {
1086 t.Fatalf("ShutdownSubConn, want %v, got %v", sc1, scToShutdown)
1087 }
1088
1089 addrs2 := <-cc.NewSubConnAddrsCh
1090 if got, want := addrs2[0].Addr, testBackendAddrStrs[1]; got != want {
1091 t.Fatalf("sc is created with addr %v, want %v", got, want)
1092 }
1093 sc2 := <-cc.NewSubConnCh
1094
1095
1096 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1097 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1098
1099
1100 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
1101 t.Fatal(err.Error())
1102 }
1103 }
1104
1105
1106
1107
1108
1109 func (s) TestPriority_MoveReadyChildToHigherPriority(t *testing.T) {
1110 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1111 defer cancel()
1112
1113 cc := testutils.NewBalancerClientConn(t)
1114 bb := balancer.Get(Name)
1115 pb := bb.Build(cc, balancer.BuildOptions{})
1116 defer pb.Close()
1117
1118
1119 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1120 ResolverState: resolver.State{
1121 Addresses: []resolver.Address{
1122 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1123 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1124 },
1125 },
1126 BalancerConfig: &LBConfig{
1127 Children: map[string]*Child{
1128 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1129 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1130 },
1131 Priorities: []string{"child-0", "child-1"},
1132 },
1133 }); err != nil {
1134 t.Fatalf("failed to update ClientConn state: %v", err)
1135 }
1136
1137 addrs0 := <-cc.NewSubConnAddrsCh
1138 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1139 t.Fatalf("sc is created with addr %v, want %v", got, want)
1140 }
1141 sc0 := <-cc.NewSubConnCh
1142
1143
1144 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
1145
1146
1147 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
1148 t.Fatal(err.Error())
1149 }
1150
1151 addrs1 := <-cc.NewSubConnAddrsCh
1152 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
1153 t.Fatalf("sc is created with addr %v, want %v", got, want)
1154 }
1155 sc1 := <-cc.NewSubConnCh
1156 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1157 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1158
1159
1160 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1161 t.Fatal(err.Error())
1162 }
1163
1164
1165
1166 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1167 ResolverState: resolver.State{
1168 Addresses: []resolver.Address{
1169 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1170 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1171 },
1172 },
1173 BalancerConfig: &LBConfig{
1174 Children: map[string]*Child{
1175 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1176 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1177 },
1178 Priorities: []string{"child-1", "child-0"},
1179 },
1180 }); err != nil {
1181 t.Fatalf("failed to update ClientConn state: %v", err)
1182 }
1183
1184
1185 scToShutdown := <-cc.ShutdownSubConnCh
1186 if scToShutdown != sc0 {
1187 t.Fatalf("ShutdownSubConn, want %v, got %v", sc0, scToShutdown)
1188 }
1189
1190
1191
1192 select {
1193 case <-cc.NewSubConnCh:
1194 t.Fatalf("got unexpected new SubConn")
1195 case <-cc.ShutdownSubConnCh:
1196 t.Fatalf("got unexpected shutdown SubConn")
1197 case <-time.After(time.Millisecond * 100):
1198 }
1199 }
1200
1201
1202
1203
1204
1205 func (s) TestPriority_RemoveReadyLowestChild(t *testing.T) {
1206 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1207 defer cancel()
1208
1209 cc := testutils.NewBalancerClientConn(t)
1210 bb := balancer.Get(Name)
1211 pb := bb.Build(cc, balancer.BuildOptions{})
1212 defer pb.Close()
1213
1214
1215 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1216 ResolverState: resolver.State{
1217 Addresses: []resolver.Address{
1218 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1219 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1220 },
1221 },
1222 BalancerConfig: &LBConfig{
1223 Children: map[string]*Child{
1224 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1225 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1226 },
1227 Priorities: []string{"child-0", "child-1"},
1228 },
1229 }); err != nil {
1230 t.Fatalf("failed to update ClientConn state: %v", err)
1231 }
1232
1233 addrs0 := <-cc.NewSubConnAddrsCh
1234 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1235 t.Fatalf("sc is created with addr %v, want %v", got, want)
1236 }
1237 sc0 := <-cc.NewSubConnCh
1238
1239
1240 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
1241
1242
1243 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
1244 t.Fatal(err.Error())
1245 }
1246
1247 addrs1 := <-cc.NewSubConnAddrsCh
1248 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
1249 t.Fatalf("sc is created with addr %v, want %v", got, want)
1250 }
1251 sc1 := <-cc.NewSubConnCh
1252 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1253 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1254
1255
1256 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1257 t.Fatal(err.Error())
1258 }
1259
1260
1261 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1262 ResolverState: resolver.State{
1263 Addresses: []resolver.Address{
1264 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1265 },
1266 },
1267 BalancerConfig: &LBConfig{
1268 Children: map[string]*Child{
1269 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1270 },
1271 Priorities: []string{"child-0"},
1272 },
1273 }); err != nil {
1274 t.Fatalf("failed to update ClientConn state: %v", err)
1275 }
1276
1277
1278 scToShutdown := <-cc.ShutdownSubConnCh
1279 if scToShutdown != sc1 {
1280 t.Fatalf("ShutdownSubConn, want %v, got %v", sc1, scToShutdown)
1281 }
1282
1283 if err := cc.WaitForErrPicker(ctx); err != nil {
1284 t.Fatal(err.Error())
1285 }
1286 <-cc.NewStateCh
1287
1288
1289 select {
1290 case <-cc.NewSubConnCh:
1291 t.Fatalf("got unexpected new SubConn")
1292 case <-time.After(time.Millisecond * 100):
1293 }
1294 }
1295
1296
1297
1298
1299
1300 func (s) TestPriority_ReadyChildRemovedButInCache(t *testing.T) {
1301 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1302 defer cancel()
1303
1304 const testChildCacheTimeout = time.Second
1305 defer func() func() {
1306 old := DefaultSubBalancerCloseTimeout
1307 DefaultSubBalancerCloseTimeout = testChildCacheTimeout
1308 return func() {
1309 DefaultSubBalancerCloseTimeout = old
1310 }
1311 }()()
1312
1313 cc := testutils.NewBalancerClientConn(t)
1314 bb := balancer.Get(Name)
1315 pb := bb.Build(cc, balancer.BuildOptions{})
1316 defer pb.Close()
1317
1318
1319 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1320 ResolverState: resolver.State{
1321 Addresses: []resolver.Address{
1322 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1323 },
1324 },
1325 BalancerConfig: &LBConfig{
1326 Children: map[string]*Child{
1327 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1328 },
1329 Priorities: []string{"child-0"},
1330 },
1331 }); err != nil {
1332 t.Fatalf("failed to update ClientConn state: %v", err)
1333 }
1334
1335 addrs1 := <-cc.NewSubConnAddrsCh
1336 if got, want := addrs1[0].Addr, testBackendAddrStrs[0]; got != want {
1337 t.Fatalf("sc is created with addr %v, want %v", got, want)
1338 }
1339 sc1 := <-cc.NewSubConnCh
1340
1341
1342 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1343 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1344
1345
1346 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1347 t.Fatal(err.Error())
1348 }
1349
1350
1351
1352 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1353 ResolverState: resolver.State{},
1354 BalancerConfig: &LBConfig{},
1355 }); err != nil {
1356 t.Fatalf("failed to update ClientConn state: %v", err)
1357 }
1358
1359 if err := cc.WaitForPickerWithErr(ctx, ErrAllPrioritiesRemoved); err != nil {
1360 t.Fatal(err.Error())
1361 }
1362
1363
1364 select {
1365 case sc := <-cc.NewSubConnCh:
1366 t.Fatalf("got unexpected new SubConn: %s", sc)
1367 case sc := <-cc.ShutdownSubConnCh:
1368 t.Fatalf("got unexpected shutdown SubConn: %v", sc)
1369 case <-time.After(time.Millisecond * 100):
1370 }
1371
1372
1373 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1374 ResolverState: resolver.State{
1375 Addresses: []resolver.Address{
1376 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1377 },
1378 },
1379 BalancerConfig: &LBConfig{
1380 Children: map[string]*Child{
1381 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1382 },
1383 Priorities: []string{"child-0"},
1384 },
1385 }); err != nil {
1386 t.Fatalf("failed to update ClientConn state: %v", err)
1387 }
1388
1389
1390 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1391 t.Fatal(err.Error())
1392 }
1393
1394
1395
1396 select {
1397 case sc := <-cc.NewSubConnCh:
1398 t.Fatalf("got unexpected new SubConn: %s", sc)
1399 case sc := <-cc.ShutdownSubConnCh:
1400 t.Fatalf("got unexpected shutdown SubConn: %v", sc)
1401 case <-time.After(time.Millisecond * 100):
1402 }
1403 }
1404
1405
1406
1407
1408 func (s) TestPriority_ChildPolicyChange(t *testing.T) {
1409 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1410 defer cancel()
1411
1412 cc := testutils.NewBalancerClientConn(t)
1413 bb := balancer.Get(Name)
1414 pb := bb.Build(cc, balancer.BuildOptions{})
1415 defer pb.Close()
1416
1417
1418 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1419 ResolverState: resolver.State{
1420 Addresses: []resolver.Address{
1421 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1422 },
1423 },
1424 BalancerConfig: &LBConfig{
1425 Children: map[string]*Child{
1426 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1427 },
1428 Priorities: []string{"child-0"},
1429 },
1430 }); err != nil {
1431 t.Fatalf("failed to update ClientConn state: %v", err)
1432 }
1433
1434 addrs1 := <-cc.NewSubConnAddrsCh
1435 if got, want := addrs1[0].Addr, testBackendAddrStrs[0]; got != want {
1436 t.Fatalf("sc is created with addr %v, want %v", got, want)
1437 }
1438 sc1 := <-cc.NewSubConnCh
1439
1440
1441 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1442 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1443
1444
1445 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1446 t.Fatal(err.Error())
1447 }
1448
1449
1450
1451 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1452 ResolverState: resolver.State{
1453 Addresses: []resolver.Address{
1454 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1455 },
1456 },
1457 BalancerConfig: &LBConfig{
1458 Children: map[string]*Child{
1459 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: testRRBalancerName}},
1460 },
1461 Priorities: []string{"child-0"},
1462 },
1463 }); err != nil {
1464 t.Fatalf("failed to update ClientConn state: %v", err)
1465 }
1466
1467
1468 scToShutdown := <-cc.ShutdownSubConnCh
1469 if scToShutdown != sc1 {
1470 t.Fatalf("ShutdownSubConn, want %v, got %v", sc1, scToShutdown)
1471 }
1472
1473
1474 addrs2 := <-cc.NewSubConnAddrsCh
1475 if got, want := addrs2[0].Addr, testBackendAddrStrs[0]; got != want {
1476 t.Fatalf("sc is created with addr %v, want %v", got, want)
1477 }
1478 sc2 := <-cc.NewSubConnCh
1479 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1480 sc2.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1481
1482
1483 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
1484 t.Fatal(err.Error())
1485 }
1486 }
1487
1488 const inlineUpdateBalancerName = "test-inline-update-balancer"
1489
1490 var errTestInlineStateUpdate = fmt.Errorf("don't like addresses, empty or not")
1491
1492 func init() {
1493 stub.Register(inlineUpdateBalancerName, stub.BalancerFuncs{
1494 UpdateClientConnState: func(bd *stub.BalancerData, opts balancer.ClientConnState) error {
1495 bd.ClientConn.UpdateState(balancer.State{
1496 ConnectivityState: connectivity.Ready,
1497 Picker: &testutils.TestConstPicker{Err: errTestInlineStateUpdate},
1498 })
1499 return nil
1500 },
1501 })
1502 }
1503
1504
1505
1506
1507 func (s) TestPriority_ChildPolicyUpdatePickerInline(t *testing.T) {
1508 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1509 defer cancel()
1510
1511 cc := testutils.NewBalancerClientConn(t)
1512 bb := balancer.Get(Name)
1513 pb := bb.Build(cc, balancer.BuildOptions{})
1514 defer pb.Close()
1515
1516
1517 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1518 ResolverState: resolver.State{
1519 Addresses: []resolver.Address{
1520 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1521 },
1522 },
1523 BalancerConfig: &LBConfig{
1524 Children: map[string]*Child{
1525 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: inlineUpdateBalancerName}},
1526 },
1527 Priorities: []string{"child-0"},
1528 },
1529 }); err != nil {
1530 t.Fatalf("failed to update ClientConn state: %v", err)
1531 }
1532
1533 if err := cc.WaitForPickerWithErr(ctx, errTestInlineStateUpdate); err != nil {
1534 t.Fatal(err.Error())
1535 }
1536 }
1537
1538
1539
1540
1541
1542 func (s) TestPriority_IgnoreReresolutionRequest(t *testing.T) {
1543
1544
1545
1546 ccCh := testutils.NewChannel()
1547 childPolicyName := t.Name()
1548 stub.Register(childPolicyName, stub.BalancerFuncs{
1549 Init: func(data *stub.BalancerData) {
1550 ccCh.Send(data.ClientConn)
1551 },
1552 })
1553
1554 cc := testutils.NewBalancerClientConn(t)
1555 bb := balancer.Get(Name)
1556 pb := bb.Build(cc, balancer.BuildOptions{})
1557 defer pb.Close()
1558
1559
1560
1561 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1562 ResolverState: resolver.State{
1563 Addresses: []resolver.Address{
1564 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1565 },
1566 },
1567 BalancerConfig: &LBConfig{
1568 Children: map[string]*Child{
1569 "child-0": {
1570 Config: &internalserviceconfig.BalancerConfig{Name: childPolicyName},
1571 IgnoreReresolutionRequests: true,
1572 },
1573 },
1574 Priorities: []string{"child-0"},
1575 },
1576 }); err != nil {
1577 t.Fatalf("failed to update ClientConn state: %v", err)
1578 }
1579
1580
1581 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1582 defer cancel()
1583 val, err := ccCh.Receive(ctx)
1584 if err != nil {
1585 t.Fatalf("timeout waiting for ClientConn from the child policy")
1586 }
1587 balancerCC := val.(balancer.ClientConn)
1588
1589
1590
1591 for i := 0; i < 5; i++ {
1592 balancerCC.ResolveNow(resolver.ResolveNowOptions{})
1593 }
1594 select {
1595 case <-cc.ResolveNowCh:
1596 t.Fatalf("got unexpected ResolveNow() call")
1597 case <-time.After(defaultTestShortTimeout):
1598 }
1599
1600
1601 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1602 ResolverState: resolver.State{
1603 Addresses: []resolver.Address{
1604 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1605 },
1606 },
1607 BalancerConfig: &LBConfig{
1608 Children: map[string]*Child{
1609 "child-0": {
1610 Config: &internalserviceconfig.BalancerConfig{Name: childPolicyName},
1611 IgnoreReresolutionRequests: false,
1612 },
1613 },
1614 Priorities: []string{"child-0"},
1615 },
1616 }); err != nil {
1617 t.Fatalf("failed to update ClientConn state: %v", err)
1618 }
1619
1620
1621 balancerCC.ResolveNow(resolver.ResolveNowOptions{})
1622 select {
1623 case <-cc.ResolveNowCh:
1624 case <-time.After(time.Second):
1625 t.Fatalf("timeout waiting for ResolveNow()")
1626 }
1627
1628 }
1629
1630
1631
1632
1633
1634
1635
1636 func (s) TestPriority_IgnoreReresolutionRequestTwoChildren(t *testing.T) {
1637
1638
1639
1640 ccCh := testutils.NewChannel()
1641 childPolicyName := t.Name()
1642 stub.Register(childPolicyName, stub.BalancerFuncs{
1643 Init: func(bd *stub.BalancerData) {
1644 ccCh.Send(bd.ClientConn)
1645 bd.Data = balancer.Get(roundrobin.Name).Build(bd.ClientConn, bd.BuildOptions)
1646 },
1647 UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
1648 bal := bd.Data.(balancer.Balancer)
1649 return bal.UpdateClientConnState(ccs)
1650 },
1651 })
1652
1653 cc := testutils.NewBalancerClientConn(t)
1654 bb := balancer.Get(Name)
1655 pb := bb.Build(cc, balancer.BuildOptions{})
1656 defer pb.Close()
1657
1658
1659
1660 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1661 ResolverState: resolver.State{
1662 Addresses: []resolver.Address{
1663 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1664 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1665 },
1666 },
1667 BalancerConfig: &LBConfig{
1668 Children: map[string]*Child{
1669 "child-0": {
1670 Config: &internalserviceconfig.BalancerConfig{Name: childPolicyName},
1671 IgnoreReresolutionRequests: true,
1672 },
1673 "child-1": {
1674 Config: &internalserviceconfig.BalancerConfig{Name: childPolicyName},
1675 },
1676 },
1677 Priorities: []string{"child-0", "child-1"},
1678 },
1679 }); err != nil {
1680 t.Fatalf("failed to update ClientConn state: %v", err)
1681 }
1682
1683
1684 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1685 defer cancel()
1686 val, err := ccCh.Receive(ctx)
1687 if err != nil {
1688 t.Fatalf("timeout waiting for ClientConn from the child policy")
1689 }
1690 balancerCC0 := val.(balancer.ClientConn)
1691
1692
1693 addrs0 := <-cc.NewSubConnAddrsCh
1694 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1695 t.Fatalf("sc is created with addr %v, want %v", got, want)
1696 }
1697 sc0 := <-cc.NewSubConnCh
1698 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
1699
1700
1701 val, err = ccCh.Receive(ctx)
1702 if err != nil {
1703 t.Fatalf("timeout waiting for ClientConn from the child policy")
1704 }
1705 balancerCC1 := val.(balancer.ClientConn)
1706
1707
1708
1709 for i := 0; i < 5; i++ {
1710 balancerCC0.ResolveNow(resolver.ResolveNowOptions{})
1711 }
1712 select {
1713 case <-cc.ResolveNowCh:
1714 t.Fatalf("got unexpected ResolveNow() call")
1715 case <-time.After(defaultTestShortTimeout):
1716 }
1717
1718
1719
1720 balancerCC1.ResolveNow(resolver.ResolveNowOptions{})
1721 select {
1722 case <-cc.ResolveNowCh:
1723 case <-time.After(defaultTestShortTimeout):
1724 t.Fatalf("timeout waiting for ResolveNow()")
1725 }
1726 }
1727
1728 const initIdleBalancerName = "test-init-Idle-balancer"
1729
1730 var errsTestInitIdle = []error{
1731 fmt.Errorf("init Idle balancer error 0"),
1732 fmt.Errorf("init Idle balancer error 1"),
1733 }
1734
1735 func init() {
1736 for i := 0; i < 2; i++ {
1737 ii := i
1738 stub.Register(fmt.Sprintf("%s-%d", initIdleBalancerName, ii), stub.BalancerFuncs{
1739 UpdateClientConnState: func(bd *stub.BalancerData, opts balancer.ClientConnState) error {
1740 lis := func(state balancer.SubConnState) {
1741 err := fmt.Errorf("wrong picker error")
1742 if state.ConnectivityState == connectivity.Idle {
1743 err = errsTestInitIdle[ii]
1744 }
1745 bd.ClientConn.UpdateState(balancer.State{
1746 ConnectivityState: state.ConnectivityState,
1747 Picker: &testutils.TestConstPicker{Err: err},
1748 })
1749 }
1750
1751 sc, err := bd.ClientConn.NewSubConn(opts.ResolverState.Addresses, balancer.NewSubConnOptions{StateListener: lis})
1752 if err != nil {
1753 return err
1754 }
1755 sc.Connect()
1756 bd.ClientConn.UpdateState(balancer.State{
1757 ConnectivityState: connectivity.Connecting,
1758 Picker: &testutils.TestConstPicker{Err: balancer.ErrNoSubConnAvailable},
1759 })
1760 return nil
1761 },
1762 })
1763 }
1764 }
1765
1766
1767
1768
1769
1770
1771 func (s) TestPriority_HighPriorityInitIdle(t *testing.T) {
1772 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1773 defer cancel()
1774
1775 cc := testutils.NewBalancerClientConn(t)
1776 bb := balancer.Get(Name)
1777 pb := bb.Build(cc, balancer.BuildOptions{})
1778 defer pb.Close()
1779
1780
1781 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1782 ResolverState: resolver.State{
1783 Addresses: []resolver.Address{
1784 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1785 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1786 },
1787 },
1788 BalancerConfig: &LBConfig{
1789 Children: map[string]*Child{
1790 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: fmt.Sprintf("%s-%d", initIdleBalancerName, 0)}},
1791 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: fmt.Sprintf("%s-%d", initIdleBalancerName, 1)}},
1792 },
1793 Priorities: []string{"child-0", "child-1"},
1794 },
1795 }); err != nil {
1796 t.Fatalf("failed to update ClientConn state: %v", err)
1797 }
1798
1799 addrs0 := <-cc.NewSubConnAddrsCh
1800 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1801 t.Fatalf("sc is created with addr %v, want %v", got, want)
1802 }
1803 sc0 := <-cc.NewSubConnCh
1804
1805
1806 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Idle})
1807 if err := cc.WaitForPickerWithErr(ctx, errsTestInitIdle[0]); err != nil {
1808 t.Fatal(err.Error())
1809 }
1810
1811
1812 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
1813
1814
1815 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
1816 t.Fatal(err.Error())
1817 }
1818
1819 addrs1 := <-cc.NewSubConnAddrsCh
1820 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
1821 t.Fatalf("sc is created with addr %v, want %v", got, want)
1822 }
1823 sc1 := <-cc.NewSubConnCh
1824
1825 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Idle})
1826 if err := cc.WaitForPickerWithErr(ctx, errsTestInitIdle[1]); err != nil {
1827 t.Fatal(err.Error())
1828 }
1829 }
1830
1831
1832
1833
1834
1835
1836
1837 func (s) TestPriority_AddLowPriorityWhenHighIsInIdle(t *testing.T) {
1838 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1839 defer cancel()
1840
1841 cc := testutils.NewBalancerClientConn(t)
1842 bb := balancer.Get(Name)
1843 pb := bb.Build(cc, balancer.BuildOptions{})
1844 defer pb.Close()
1845
1846
1847 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1848 ResolverState: resolver.State{
1849 Addresses: []resolver.Address{
1850 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1851 },
1852 },
1853 BalancerConfig: &LBConfig{
1854 Children: map[string]*Child{
1855 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: fmt.Sprintf("%s-%d", initIdleBalancerName, 0)}},
1856 },
1857 Priorities: []string{"child-0"},
1858 },
1859 }); err != nil {
1860 t.Fatalf("failed to update ClientConn state: %v", err)
1861 }
1862
1863 addrs0 := <-cc.NewSubConnAddrsCh
1864 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1865 t.Fatalf("sc is created with addr %v, want %v", got, want)
1866 }
1867 sc0 := <-cc.NewSubConnCh
1868
1869
1870 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Idle})
1871 if err := cc.WaitForPickerWithErr(ctx, errsTestInitIdle[0]); err != nil {
1872 t.Fatal(err.Error())
1873 }
1874
1875
1876 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1877 ResolverState: resolver.State{
1878 Addresses: []resolver.Address{
1879 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1880 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1881 },
1882 },
1883 BalancerConfig: &LBConfig{
1884 Children: map[string]*Child{
1885 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: fmt.Sprintf("%s-%d", initIdleBalancerName, 0)}},
1886 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: fmt.Sprintf("%s-%d", initIdleBalancerName, 1)}},
1887 },
1888 Priorities: []string{"child-0", "child-1"},
1889 },
1890 }); err != nil {
1891 t.Fatalf("failed to update ClientConn state: %v", err)
1892 }
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907 addrsNew := <-cc.NewSubConnAddrsCh
1908 if got, want := addrsNew[0].Addr, testBackendAddrStrs[0]; got != want {
1909
1910 t.Fatalf("got unexpected call to NewSubConn with addr: %v, want %v", addrsNew, want)
1911 }
1912 }
1913
1914
1915
1916
1917
1918 func (s) TestPriority_HighPriorityUpdatesWhenLowInUse(t *testing.T) {
1919 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
1920 defer cancel()
1921
1922 cc := testutils.NewBalancerClientConn(t)
1923 bb := balancer.Get(Name)
1924 pb := bb.Build(cc, balancer.BuildOptions{})
1925 defer pb.Close()
1926
1927 t.Log("Two localities, with priorities [0, 1], each with one backend.")
1928 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1929 ResolverState: resolver.State{
1930 Addresses: []resolver.Address{
1931 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[0]}, []string{"child-0"}),
1932 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[1]}, []string{"child-1"}),
1933 },
1934 },
1935 BalancerConfig: &LBConfig{
1936 Children: map[string]*Child{
1937 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1938 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1939 },
1940 Priorities: []string{"child-0", "child-1"},
1941 },
1942 }); err != nil {
1943 t.Fatalf("failed to update ClientConn state: %v", err)
1944 }
1945
1946 addrs0 := <-cc.NewSubConnAddrsCh
1947 if got, want := addrs0[0].Addr, testBackendAddrStrs[0]; got != want {
1948 t.Fatalf("sc is created with addr %v, want %v", got, want)
1949 }
1950 sc0 := <-cc.NewSubConnCh
1951
1952 t.Log("Make p0 fail.")
1953 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1954 sc0.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.TransientFailure})
1955
1956
1957
1958 if err := cc.WaitForPickerWithErr(ctx, balancer.ErrNoSubConnAvailable); err != nil {
1959 t.Fatal(err.Error())
1960 }
1961
1962 t.Log("Make p1 ready.")
1963 addrs1 := <-cc.NewSubConnAddrsCh
1964 if got, want := addrs1[0].Addr, testBackendAddrStrs[1]; got != want {
1965 t.Fatalf("sc is created with addr %v, want %v", got, want)
1966 }
1967 sc1 := <-cc.NewSubConnCh
1968 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1969 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1970
1971
1972 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1973 t.Fatal(err.Error())
1974 }
1975
1976 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
1977
1978
1979 sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
1980
1981 if err := cc.WaitForRoundRobinPicker(ctx, sc1); err != nil {
1982 t.Fatal(err.Error())
1983 }
1984
1985 t.Log("Change p0 to use new address.")
1986 if err := pb.UpdateClientConnState(balancer.ClientConnState{
1987 ResolverState: resolver.State{
1988 Addresses: []resolver.Address{
1989 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[2]}, []string{"child-0"}),
1990 hierarchy.Set(resolver.Address{Addr: testBackendAddrStrs[3]}, []string{"child-1"}),
1991 },
1992 },
1993 BalancerConfig: &LBConfig{
1994 Children: map[string]*Child{
1995 "child-0": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1996 "child-1": {Config: &internalserviceconfig.BalancerConfig{Name: roundrobin.Name}},
1997 },
1998 Priorities: []string{"child-0", "child-1"},
1999 },
2000 }); err != nil {
2001 t.Fatalf("failed to update ClientConn state: %v", err)
2002 }
2003
2004
2005
2006
2007 t.Log("Make p0 and p1 both ready; p0 should be used.")
2008 var sc2, sc3 balancer.SubConn
2009 for i := 0; i < 2; i++ {
2010 addr := <-cc.NewSubConnAddrsCh
2011 sc := <-cc.NewSubConnCh
2012 switch addr[0].Addr {
2013 case testBackendAddrStrs[2]:
2014 sc2 = sc
2015 case testBackendAddrStrs[3]:
2016 sc3 = sc
2017 default:
2018 t.Fatalf("sc is created with addr %v, want %v or %v", addr[0].Addr, testBackendAddrStrs[2], testBackendAddrStrs[3])
2019 }
2020 sc.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
2021 sc.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready})
2022 }
2023 if sc2 == nil {
2024 t.Fatalf("sc not created with addr %v", testBackendAddrStrs[2])
2025 }
2026 if sc3 == nil {
2027 t.Fatalf("sc not created with addr %v", testBackendAddrStrs[3])
2028 }
2029
2030
2031 if err := cc.WaitForRoundRobinPicker(ctx, sc2); err != nil {
2032 t.Fatal(err.Error())
2033 }
2034 }
2035
View as plain text