Tests the scenario where a connection is established and then breaks, leading to a reconnection attempt. While the reconnection is in progress, a resolver update with a new address is received. The test verifies that the balancer creates a new SubConn for the new address and that the ClientConn even
(t *testing.T)
| 2680 | // creates a new SubConn for the new address and that the ClientConn eventually |
| 2681 | // becomes READY. |
| 2682 | func (s) TestPickFirstLeaf_Reconnection(t *testing.T) { |
| 2683 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 2684 | defer cancel() |
| 2685 | cc := testutils.NewBalancerClientConn(t) |
| 2686 | bal := balancer.Get(pfbalancer.Name).Build(cc, balancer.BuildOptions{}) |
| 2687 | defer bal.Close() |
| 2688 | ccState := balancer.ClientConnState{ |
| 2689 | ResolverState: resolver.State{ |
| 2690 | Endpoints: []resolver.Endpoint{ |
| 2691 | {Addresses: []resolver.Address{{Addr: "1.1.1.1:1"}}}, |
| 2692 | }, |
| 2693 | }, |
| 2694 | } |
| 2695 | if err := bal.UpdateClientConnState(ccState); err != nil { |
| 2696 | t.Fatalf("UpdateClientConnState(%v) returned error: %v", ccState, err) |
| 2697 | } |
| 2698 | |
| 2699 | select { |
| 2700 | case state := <-cc.NewStateCh: |
| 2701 | if got, want := state, connectivity.Connecting; got != want { |
| 2702 | t.Fatalf("Received unexpected ClientConn sate: got %v, want %v", got, want) |
| 2703 | } |
| 2704 | case <-ctx.Done(): |
| 2705 | t.Fatal("Context timed out waiting for ClientConn state update.") |
| 2706 | } |
| 2707 | |
| 2708 | sc1 := <-cc.NewSubConnCh |
| 2709 | select { |
| 2710 | case <-sc1.ConnectCh: |
| 2711 | case <-ctx.Done(): |
| 2712 | t.Fatal("Context timed out waiting for Connect() to be called on sc1.") |
| 2713 | } |
| 2714 | sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting}) |
| 2715 | sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Ready}) |
| 2716 | |
| 2717 | if err := cc.WaitForConnectivityState(ctx, connectivity.Ready); err != nil { |
| 2718 | t.Fatalf("Context timed out waiting for ClientConn to become READY.") |
| 2719 | } |
| 2720 | |
| 2721 | // Simulate a connection breakage, this should result the channel |
| 2722 | // transitioning to IDLE. |
| 2723 | sc1.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Idle}) |
| 2724 | if err := cc.WaitForConnectivityState(ctx, connectivity.Idle); err != nil { |
| 2725 | t.Fatalf("Context timed out waiting for ClientConn to enter IDLE.") |
| 2726 | } |
| 2727 | |
| 2728 | // Calling the idle picker should result in the SubConn being re-connected. |
| 2729 | picker := <-cc.NewPickerCh |
| 2730 | if _, err := picker.Pick(balancer.PickInfo{}); err != balancer.ErrNoSubConnAvailable { |
| 2731 | t.Fatalf("picker.Pick() returned error: %v, want %v", err, balancer.ErrNoSubConnAvailable) |
| 2732 | } |
| 2733 | |
| 2734 | select { |
| 2735 | case <-sc1.ConnectCh: |
| 2736 | case <-ctx.Done(): |
| 2737 | t.Fatal("Context timed out waiting for Connect() to be called on sc1.") |
| 2738 | } |
| 2739 |
nothing calls this directly
no test coverage detected