google.golang.org/grpc@v1.62.1/internal/balancer/gracefulswitch/gracefulswitch_test.go (about)

     1  /*
     2   *
     3   * Copyright 2022 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 gracefulswitch
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"strings"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/google/go-cmp/cmp"
    29  	"github.com/google/go-cmp/cmp/cmpopts"
    30  	"google.golang.org/grpc/balancer"
    31  	"google.golang.org/grpc/connectivity"
    32  	"google.golang.org/grpc/internal/grpcsync"
    33  	"google.golang.org/grpc/internal/grpctest"
    34  	"google.golang.org/grpc/internal/testutils"
    35  	"google.golang.org/grpc/resolver"
    36  	"google.golang.org/grpc/serviceconfig"
    37  )
    38  
    39  const (
    40  	defaultTestTimeout      = 5 * time.Second
    41  	defaultTestShortTimeout = 10 * time.Millisecond
    42  )
    43  
    44  type s struct {
    45  	grpctest.Tester
    46  }
    47  
    48  func Test(t *testing.T) {
    49  	grpctest.RunSubTests(t, s{})
    50  }
    51  
    52  func setup(t *testing.T) (*testutils.BalancerClientConn, *Balancer) {
    53  	tcc := testutils.NewBalancerClientConn(t)
    54  	return tcc, NewBalancer(tcc, balancer.BuildOptions{})
    55  }
    56  
    57  // TestSuccessfulFirstUpdate tests a basic scenario for the graceful switch load
    58  // balancer, where it is setup with a balancer which should populate the current
    59  // load balancer. Any ClientConn updates should then be forwarded to this
    60  // current load balancer.
    61  func (s) TestSuccessfulFirstUpdate(t *testing.T) {
    62  	_, gsb := setup(t)
    63  	if err := gsb.SwitchTo(mockBalancerBuilder1{}); err != nil {
    64  		t.Fatalf("Balancer.SwitchTo failed with error: %v", err)
    65  	}
    66  	if gsb.balancerCurrent == nil {
    67  		t.Fatal("current balancer not populated after a successful call to SwitchTo()")
    68  	}
    69  	// This will be used to update the graceful switch balancer. This update
    70  	// should simply be forwarded down to the current load balancing policy.
    71  	ccs := balancer.ClientConnState{
    72  		BalancerConfig: mockBalancerConfig{},
    73  	}
    74  
    75  	// Updating ClientConnState should forward the update exactly as is to the
    76  	// current balancer.
    77  	if err := gsb.UpdateClientConnState(ccs); err != nil {
    78  		t.Fatalf("Balancer.UpdateClientConnState(%v) failed: %v", ccs, err)
    79  	}
    80  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
    81  	defer cancel()
    82  	if err := gsb.balancerCurrent.Balancer.(*mockBalancer).waitForClientConnUpdate(ctx, ccs); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  }
    86  
    87  // TestTwoBalancersSameType tests the scenario where there is a graceful switch
    88  // load balancer setup with a current and pending load balancer of the same
    89  // type. Any ClientConn update should be forwarded to the current lb if there is
    90  // a current lb and no pending lb, and the only the pending lb if the graceful
    91  // switch balancer contains both a current lb and a pending lb. The pending load
    92  // balancer should also swap into current whenever it updates with a
    93  // connectivity state other than CONNECTING.
    94  func (s) TestTwoBalancersSameType(t *testing.T) {
    95  	tcc, gsb := setup(t)
    96  	// This will be used to update the graceful switch balancer. This update
    97  	// should simply be forwarded down to either the current or pending load
    98  	// balancing policy.
    99  	ccs := balancer.ClientConnState{
   100  		BalancerConfig: mockBalancerConfig{},
   101  	}
   102  
   103  	gsb.SwitchTo(mockBalancerBuilder1{})
   104  	gsb.UpdateClientConnState(ccs)
   105  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   106  	defer cancel()
   107  	if err := gsb.balancerCurrent.Balancer.(*mockBalancer).waitForClientConnUpdate(ctx, ccs); err != nil {
   108  		t.Fatal(err)
   109  	}
   110  
   111  	// The current balancer reporting READY should cause this state
   112  	// to be forwarded to the ClientConn.
   113  	gsb.balancerCurrent.Balancer.(*mockBalancer).updateState(balancer.State{
   114  		ConnectivityState: connectivity.Ready,
   115  		Picker:            &neverErrPicker{},
   116  	})
   117  
   118  	select {
   119  	case <-ctx.Done():
   120  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   121  	case state := <-tcc.NewStateCh:
   122  		if state != connectivity.Ready {
   123  			t.Fatalf("current balancer reports connectivity state %v, want %v", state, connectivity.Ready)
   124  		}
   125  	}
   126  
   127  	select {
   128  	case <-ctx.Done():
   129  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   130  	case picker := <-tcc.NewPickerCh:
   131  		// Should receive a never err picker.
   132  		if _, err := picker.Pick(balancer.PickInfo{}); err != nil {
   133  			t.Fatalf("ClientConn should have received a never err picker from an UpdateState call")
   134  		}
   135  	}
   136  
   137  	// An explicit call to switchTo, even if the same type, should cause the
   138  	// balancer to build a new balancer for pending.
   139  	gsb.SwitchTo(mockBalancerBuilder1{})
   140  	if gsb.balancerPending == nil {
   141  		t.Fatal("pending balancer not populated after another call to SwitchTo()")
   142  	}
   143  
   144  	// A ClientConn update received should be forwarded to the new pending LB
   145  	// policy, and not the current one.
   146  	gsb.UpdateClientConnState(ccs)
   147  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   148  	defer sCancel()
   149  	if err := gsb.balancerCurrent.Balancer.(*mockBalancer).waitForClientConnUpdate(sCtx, ccs); err == nil {
   150  		t.Fatal("current balancer received a ClientConn update when there is a pending balancer")
   151  	}
   152  	if err := gsb.balancerPending.Balancer.(*mockBalancer).waitForClientConnUpdate(ctx, ccs); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	// If the pending load balancer reports that is CONNECTING, no update should
   157  	// be sent to the ClientConn.
   158  	gsb.balancerPending.Balancer.(*mockBalancer).updateState(balancer.State{
   159  		ConnectivityState: connectivity.Connecting,
   160  	})
   161  	sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout)
   162  	defer sCancel()
   163  	select {
   164  	case <-tcc.NewStateCh:
   165  		t.Fatal("balancerPending reporting CONNECTING should not forward up to the ClientConn")
   166  	case <-sCtx.Done():
   167  	}
   168  
   169  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   170  	// If the pending load balancer reports a state other than CONNECTING, the
   171  	// pending load balancer is logically warmed up, and the ClientConn should
   172  	// be updated with the State and Picker to start using the new policy. The
   173  	// pending load balancing policy should also be switched into the current
   174  	// load balancer.
   175  	gsb.balancerPending.Balancer.(*mockBalancer).updateState(balancer.State{
   176  		ConnectivityState: connectivity.Ready,
   177  		Picker:            &neverErrPicker{},
   178  	})
   179  
   180  	select {
   181  	case <-ctx.Done():
   182  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   183  	case state := <-tcc.NewStateCh:
   184  		if state != connectivity.Ready {
   185  			t.Fatalf("pending balancer reports connectivity state %v, want %v", state, connectivity.Ready)
   186  		}
   187  	}
   188  
   189  	select {
   190  	case <-ctx.Done():
   191  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   192  	case picker := <-tcc.NewPickerCh:
   193  		// This picker should be the recent one sent from UpdateState(), a never
   194  		// err picker, not the nil picker from two updateState() calls previous.
   195  		if picker == nil {
   196  			t.Fatalf("ClientConn should have received a never err picker, which is the most recent picker, from an UpdateState call")
   197  		}
   198  		if _, err := picker.Pick(balancer.PickInfo{}); err != nil {
   199  			t.Fatalf("ClientConn should have received a never err picker, which is the most recent picker, from an UpdateState call")
   200  		}
   201  	}
   202  	// The current balancer should be closed as a result of the swap.
   203  	if err := currBal.waitForClose(ctx); err != nil {
   204  		t.Fatal(err)
   205  	}
   206  }
   207  
   208  // TestCurrentNotReadyPendingUpdate tests the scenario where there is a current
   209  // and pending load balancer setup in the graceful switch load balancer, and the
   210  // current LB is not in the connectivity state READY. Any update from the
   211  // pending load balancer should cause the graceful switch load balancer to swap
   212  // the pending into current, and update the ClientConn with the pending load
   213  // balancers state.
   214  func (s) TestCurrentNotReadyPendingUpdate(t *testing.T) {
   215  	tcc, gsb := setup(t)
   216  	gsb.SwitchTo(mockBalancerBuilder1{})
   217  	gsb.SwitchTo(mockBalancerBuilder1{})
   218  	if gsb.balancerPending == nil {
   219  		t.Fatal("pending balancer not populated after another call to SwitchTo()")
   220  	}
   221  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   222  	// Due to the current load balancer not being in state READY, any update
   223  	// from the pending load balancer should cause that update to be forwarded
   224  	// to the ClientConn and also cause the pending load balancer to swap into
   225  	// the current one.
   226  	gsb.balancerPending.Balancer.(*mockBalancer).updateState(balancer.State{
   227  		ConnectivityState: connectivity.Connecting,
   228  		Picker:            &neverErrPicker{},
   229  	})
   230  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   231  	defer cancel()
   232  	select {
   233  	case <-ctx.Done():
   234  		t.Fatalf("timeout waiting for an UpdateState call on the ClientConn")
   235  	case state := <-tcc.NewStateCh:
   236  		if state != connectivity.Connecting {
   237  			t.Fatalf("ClientConn received connectivity state %v, want %v (from pending)", state, connectivity.Connecting)
   238  		}
   239  	}
   240  	select {
   241  	case <-ctx.Done():
   242  		t.Fatalf("timeout waiting for an UpdateState call on the ClientConn")
   243  	case picker := <-tcc.NewPickerCh:
   244  		// Should receive a never err picker.
   245  		if _, err := picker.Pick(balancer.PickInfo{}); err != nil {
   246  			t.Fatalf("ClientConn should have received a never err picker from an UpdateState call")
   247  		}
   248  	}
   249  
   250  	// The current balancer should be closed as a result of the swap.
   251  	if err := currBal.waitForClose(ctx); err != nil {
   252  		t.Fatal(err)
   253  	}
   254  }
   255  
   256  // TestCurrentLeavingReady tests the scenario where there is a current and
   257  // pending load balancer setup in the graceful switch load balancer, with the
   258  // current load balancer being in the state READY, and the current load balancer
   259  // then transitions into a state other than READY. This should cause the pending
   260  // load balancer to swap into the current load balancer, and the ClientConn to
   261  // be updated with the cached pending load balancing state. Also, once the
   262  // current is cleared from the graceful switch load balancer, any updates sent
   263  // should be intercepted and not forwarded to the ClientConn, as the balancer
   264  // has already been cleared.
   265  func (s) TestCurrentLeavingReady(t *testing.T) {
   266  	tcc, gsb := setup(t)
   267  	gsb.SwitchTo(mockBalancerBuilder1{})
   268  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   269  	currBal.updateState(balancer.State{
   270  		ConnectivityState: connectivity.Ready,
   271  	})
   272  
   273  	gsb.SwitchTo(mockBalancerBuilder2{})
   274  	// Sends CONNECTING, shouldn't make it's way to ClientConn.
   275  	gsb.balancerPending.Balancer.(*mockBalancer).updateState(balancer.State{
   276  		ConnectivityState: connectivity.Connecting,
   277  		Picker:            &neverErrPicker{},
   278  	})
   279  
   280  	// The current balancer leaving READY should cause the pending balancer to
   281  	// swap to the current balancer. This swap from current to pending should
   282  	// also update the ClientConn with the pending balancers cached state and
   283  	// picker.
   284  	currBal.updateState(balancer.State{
   285  		ConnectivityState: connectivity.Idle,
   286  	})
   287  
   288  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   289  	defer cancel()
   290  	select {
   291  	case <-ctx.Done():
   292  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   293  	case state := <-tcc.NewStateCh:
   294  		if state != connectivity.Connecting {
   295  			t.Fatalf("current balancer reports connectivity state %v, want %v", state, connectivity.Connecting)
   296  		}
   297  	}
   298  
   299  	select {
   300  	case <-ctx.Done():
   301  		t.Fatalf("timeout while waiting for a UpdateState call on the ClientConn")
   302  	case picker := <-tcc.NewPickerCh:
   303  		// Should receive a never err picker cached from pending LB's updateState() call, which
   304  		// was cached.
   305  		if _, err := picker.Pick(balancer.PickInfo{}); err != nil {
   306  			t.Fatalf("ClientConn should have received a never err picker, the cached picker, from an UpdateState call")
   307  		}
   308  	}
   309  
   310  	// The current balancer should be closed as a result of the swap.
   311  	if err := currBal.waitForClose(ctx); err != nil {
   312  		t.Fatal(err)
   313  	}
   314  
   315  	// The current balancer is now cleared from the graceful switch load
   316  	// balancer. Thus, any update from the old current should be intercepted by
   317  	// the graceful switch load balancer and not forward up to the ClientConn.
   318  	currBal.updateState(balancer.State{
   319  		ConnectivityState: connectivity.Ready,
   320  		Picker:            &neverErrPicker{},
   321  	})
   322  
   323  	// This update should not be forwarded to the ClientConn.
   324  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   325  	defer sCancel()
   326  	select {
   327  	case <-sCtx.Done():
   328  	case <-tcc.NewStateCh:
   329  		t.Fatal("UpdateState() from a cleared balancer should not make it's way to ClientConn")
   330  	}
   331  
   332  	if _, err := currBal.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{}); err == nil {
   333  		t.Fatal("newSubConn() from a cleared balancer should have returned an error")
   334  	}
   335  
   336  	// This newSubConn call should also not reach the ClientConn.
   337  	sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout)
   338  	defer sCancel()
   339  	select {
   340  	case <-sCtx.Done():
   341  	case <-tcc.NewSubConnCh:
   342  		t.Fatal("newSubConn() from a cleared balancer should not make it's way to ClientConn")
   343  	}
   344  }
   345  
   346  // TestBalancerSubconns tests the SubConn functionality of the graceful switch
   347  // load balancer. This tests the SubConn update flow in both directions, and
   348  // make sure updates end up at the correct component.
   349  func (s) TestBalancerSubconns(t *testing.T) {
   350  	tcc, gsb := setup(t)
   351  	gsb.SwitchTo(mockBalancerBuilder1{})
   352  	gsb.SwitchTo(mockBalancerBuilder2{})
   353  
   354  	// A child balancer creating a new SubConn should eventually be forwarded to
   355  	// the ClientConn held by the graceful switch load balancer.
   356  	sc1, err := gsb.balancerCurrent.Balancer.(*mockBalancer).newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   357  	if err != nil {
   358  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   359  	}
   360  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   361  	defer cancel()
   362  	select {
   363  	case <-ctx.Done():
   364  		t.Fatalf("timeout while waiting for an NewSubConn call on the ClientConn")
   365  	case sc := <-tcc.NewSubConnCh:
   366  		if sc != sc1 {
   367  			t.Fatalf("NewSubConn, want %v, got %v", sc1, sc)
   368  		}
   369  	}
   370  
   371  	// The other child balancer creating a new SubConn should also be eventually
   372  	// be forwarded to the ClientConn held by the graceful switch load balancer.
   373  	sc2, err := gsb.balancerPending.Balancer.(*mockBalancer).newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   374  	if err != nil {
   375  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   376  	}
   377  	select {
   378  	case <-ctx.Done():
   379  		t.Fatalf("timeout while waiting for an NewSubConn call on the ClientConn")
   380  	case sc := <-tcc.NewSubConnCh:
   381  		if sc != sc2 {
   382  			t.Fatalf("NewSubConn, want %v, got %v", sc2, sc)
   383  		}
   384  	}
   385  	scState := balancer.SubConnState{ConnectivityState: connectivity.Ready}
   386  	// Updating the SubConnState for sc1 should cause the graceful switch
   387  	// balancer to forward the Update to balancerCurrent for sc1, as that is the
   388  	// balancer that created this SubConn.
   389  	sc1.(*testutils.TestSubConn).UpdateState(scState)
   390  
   391  	// Updating the SubConnState for sc2 should cause the graceful switch
   392  	// balancer to forward the Update to balancerPending for sc2, as that is the
   393  	// balancer that created this SubConn.
   394  	sc2.(*testutils.TestSubConn).UpdateState(scState)
   395  
   396  	// Updating the addresses for both SubConns and removing both SubConns
   397  	// should get forwarded to the ClientConn.
   398  
   399  	// Updating the addresses for sc1 should get forwarded to the ClientConn.
   400  	gsb.balancerCurrent.Balancer.(*mockBalancer).updateAddresses(sc1, []resolver.Address{})
   401  
   402  	select {
   403  	case <-ctx.Done():
   404  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   405  	case <-tcc.UpdateAddressesAddrsCh:
   406  	}
   407  
   408  	// Updating the addresses for sc2 should also get forwarded to the ClientConn.
   409  	gsb.balancerPending.Balancer.(*mockBalancer).updateAddresses(sc2, []resolver.Address{})
   410  	select {
   411  	case <-ctx.Done():
   412  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   413  	case <-tcc.UpdateAddressesAddrsCh:
   414  	}
   415  
   416  	// balancerCurrent removing sc1 should get forwarded to the ClientConn.
   417  	sc1.Shutdown()
   418  	select {
   419  	case <-ctx.Done():
   420  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   421  	case sc := <-tcc.ShutdownSubConnCh:
   422  		if sc != sc1 {
   423  			t.Fatalf("ShutdownSubConn, want %v, got %v", sc1, sc)
   424  		}
   425  	}
   426  	// balancerPending removing sc2 should get forwarded to the ClientConn.
   427  	sc2.Shutdown()
   428  	select {
   429  	case <-ctx.Done():
   430  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   431  	case sc := <-tcc.ShutdownSubConnCh:
   432  		if sc != sc2 {
   433  			t.Fatalf("ShutdownSubConn, want %v, got %v", sc2, sc)
   434  		}
   435  	}
   436  }
   437  
   438  // TestBalancerClose tests the graceful switch balancer's Close()
   439  // functionality.  From the Close() call, the graceful switch balancer should
   440  // shut down any created Subconns and Close() the current and pending load
   441  // balancers. This Close() call should also cause any other events (calls to
   442  // entrance functions) to be no-ops.
   443  func (s) TestBalancerClose(t *testing.T) {
   444  	// Setup gsb balancer with current, pending, and one created SubConn on both
   445  	// current and pending.
   446  	tcc, gsb := setup(t)
   447  	gsb.SwitchTo(mockBalancerBuilder1{})
   448  	gsb.SwitchTo(mockBalancerBuilder2{})
   449  
   450  	sc1, err := gsb.balancerCurrent.Balancer.(*mockBalancer).newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   451  	// Will eventually get back a SubConn with an identifying property id 1
   452  	if err != nil {
   453  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   454  	}
   455  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   456  	defer cancel()
   457  	select {
   458  	case <-ctx.Done():
   459  		t.Fatalf("timeout while waiting for an NewSubConn call on the ClientConn")
   460  	case <-tcc.NewSubConnCh:
   461  	}
   462  
   463  	sc2, err := gsb.balancerPending.Balancer.(*mockBalancer).newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   464  	// Will eventually get back a SubConn with an identifying property id 2
   465  	if err != nil {
   466  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   467  	}
   468  	select {
   469  	case <-ctx.Done():
   470  		t.Fatalf("timeout while waiting for an NewSubConn call on the ClientConn")
   471  	case <-tcc.NewSubConnCh:
   472  	}
   473  
   474  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   475  	pendBal := gsb.balancerPending.Balancer.(*mockBalancer)
   476  
   477  	// Closing the graceful switch load balancer should lead to removing any
   478  	// created SubConns, and closing both the current and pending load balancer.
   479  	gsb.Close()
   480  
   481  	// The order of SubConns the graceful switch load balancer tells the Client
   482  	// Conn to shut down is non deterministic, as it is stored in a
   483  	// map. However, the first SubConn shut down should be either sc1 or sc2.
   484  	select {
   485  	case <-ctx.Done():
   486  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   487  	case sc := <-tcc.ShutdownSubConnCh:
   488  		if sc != sc1 && sc != sc2 {
   489  			t.Fatalf("ShutdownSubConn, want either %v or %v, got %v", sc1, sc2, sc)
   490  		}
   491  	}
   492  
   493  	// The graceful switch load balancer should then tell the ClientConn to
   494  	// shut down the other SubConn.
   495  	select {
   496  	case <-ctx.Done():
   497  		t.Fatalf("timeout while waiting for an UpdateAddresses call on the ClientConn")
   498  	case sc := <-tcc.ShutdownSubConnCh:
   499  		if sc != sc1 && sc != sc2 {
   500  			t.Fatalf("ShutdownSubConn, want either %v or %v, got %v", sc1, sc2, sc)
   501  		}
   502  	}
   503  
   504  	// The current balancer should get closed as a result of the graceful switch balancer being closed.
   505  	if err := currBal.waitForClose(ctx); err != nil {
   506  		t.Fatal(err)
   507  	}
   508  	// The pending balancer should also get closed as a result of the graceful switch balancer being closed.
   509  	if err := pendBal.waitForClose(ctx); err != nil {
   510  		t.Fatal(err)
   511  	}
   512  
   513  	// Once the graceful switch load balancer has been closed, any entrance
   514  	// function should be a no-op and return errBalancerClosed if the function
   515  	// returns an error.
   516  
   517  	// SwitchTo() should return an error due to the graceful switch load
   518  	// balancer having been closed already.
   519  	if err := gsb.SwitchTo(mockBalancerBuilder1{}); err != errBalancerClosed {
   520  		t.Fatalf("gsb.SwitchTo(%v) returned error %v, want %v", mockBalancerBuilder1{}, err, errBalancerClosed)
   521  	}
   522  
   523  	// UpdateClientConnState() should return an error due to the graceful switch
   524  	// load balancer having been closed already.
   525  	ccs := balancer.ClientConnState{
   526  		BalancerConfig: mockBalancerConfig{},
   527  	}
   528  	if err := gsb.UpdateClientConnState(ccs); err != errBalancerClosed {
   529  		t.Fatalf("gsb.UpdateCLientConnState(%v) returned error %v, want %v", ccs, err, errBalancerClosed)
   530  	}
   531  
   532  	// After the graceful switch load balancer has been closed, any resolver error
   533  	// shouldn't forward to either balancer, as the resolver error is a no-op
   534  	// and also even if not, the balancers should have been cleared from the
   535  	// graceful switch load balancer.
   536  	gsb.ResolverError(balancer.ErrBadResolverState)
   537  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   538  	defer sCancel()
   539  	if err := currBal.waitForResolverError(sCtx, balancer.ErrBadResolverState); !strings.Contains(err.Error(), sCtx.Err().Error()) {
   540  		t.Fatal("the current balancer should not have received the resolver error after close")
   541  	}
   542  	sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout)
   543  	defer sCancel()
   544  	if err := pendBal.waitForResolverError(sCtx, balancer.ErrBadResolverState); !strings.Contains(err.Error(), sCtx.Err().Error()) {
   545  		t.Fatal("the pending balancer should not have received the resolver error after close")
   546  	}
   547  }
   548  
   549  // TestResolverError tests the functionality of a Resolver Error. If there is a
   550  // current balancer, but no pending, the error should be forwarded to the
   551  // current balancer. If there is both a current and pending balancer, the error
   552  // should be forwarded to only the pending balancer.
   553  func (s) TestResolverError(t *testing.T) {
   554  	_, gsb := setup(t)
   555  	gsb.SwitchTo(mockBalancerBuilder1{})
   556  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   557  	// If there is only a current balancer present, the resolver error should be
   558  	// forwarded to the current balancer.
   559  	gsb.ResolverError(balancer.ErrBadResolverState)
   560  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   561  	defer cancel()
   562  	if err := currBal.waitForResolverError(ctx, balancer.ErrBadResolverState); err != nil {
   563  		t.Fatal(err)
   564  	}
   565  
   566  	gsb.SwitchTo(mockBalancerBuilder1{})
   567  
   568  	// If there is a pending balancer present, then a resolver error should be
   569  	// forwarded to only the pending balancer, not the current.
   570  	pendBal := gsb.balancerPending.Balancer.(*mockBalancer)
   571  	gsb.ResolverError(balancer.ErrBadResolverState)
   572  
   573  	// The Resolver Error should not be forwarded to the current load balancer.
   574  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   575  	defer sCancel()
   576  	if err := currBal.waitForResolverError(sCtx, balancer.ErrBadResolverState); !strings.Contains(err.Error(), sCtx.Err().Error()) {
   577  		t.Fatal("the current balancer should not have received the resolver error after close")
   578  	}
   579  
   580  	// The Resolver Error should be forwarded to the pending load balancer.
   581  	if err := pendBal.waitForResolverError(ctx, balancer.ErrBadResolverState); err != nil {
   582  		t.Fatal(err)
   583  	}
   584  }
   585  
   586  // TestPendingReplacedByAnotherPending tests the scenario where a graceful
   587  // switch balancer has a current and pending load balancer, and receives a
   588  // SwitchTo() call, which then replaces the pending. This should cause the
   589  // graceful switch balancer to clear pending state, close old pending SubConns,
   590  // and Close() the pending balancer being replaced.
   591  func (s) TestPendingReplacedByAnotherPending(t *testing.T) {
   592  	tcc, gsb := setup(t)
   593  	gsb.SwitchTo(mockBalancerBuilder1{})
   594  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   595  	currBal.updateState(balancer.State{
   596  		ConnectivityState: connectivity.Ready,
   597  	})
   598  
   599  	// Populate pending with a SwitchTo() call.
   600  	gsb.SwitchTo(mockBalancerBuilder2{})
   601  
   602  	pendBal := gsb.balancerPending.Balancer.(*mockBalancer)
   603  	sc1, err := pendBal.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   604  	if err != nil {
   605  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   606  	}
   607  	// This picker never returns an error, which can help this this test verify
   608  	// whether this cached state will get cleared on a new pending balancer
   609  	// (will replace it with a picker that always errors).
   610  	pendBal.updateState(balancer.State{
   611  		ConnectivityState: connectivity.Connecting,
   612  		Picker:            &neverErrPicker{},
   613  	})
   614  
   615  	// Replace pending with a SwitchTo() call.
   616  	gsb.SwitchTo(mockBalancerBuilder2{})
   617  	// The pending balancer being replaced should cause the graceful switch
   618  	// balancer to Shutdown() any created SubConns for the old pending balancer
   619  	// and also Close() the old pending balancer.
   620  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   621  	defer cancel()
   622  	select {
   623  	case <-ctx.Done():
   624  		t.Fatalf("timeout while waiting for a SubConn.Shutdown")
   625  	case sc := <-tcc.ShutdownSubConnCh:
   626  		if sc != sc1 {
   627  			t.Fatalf("ShutdownSubConn, want %v, got %v", sc1, sc)
   628  		}
   629  	}
   630  
   631  	if err := pendBal.waitForClose(ctx); err != nil {
   632  		t.Fatal(err)
   633  	}
   634  
   635  	// Switching the current out of READY should cause the pending LB to swap
   636  	// into current, causing the graceful switch balancer to update the
   637  	// ClientConn with the cached pending state. Since the new pending hasn't
   638  	// sent an Update, the default state with connectivity state CONNECTING and
   639  	// an errPicker should be sent to the ClientConn.
   640  	currBal.updateState(balancer.State{
   641  		ConnectivityState: connectivity.Idle,
   642  	})
   643  
   644  	// The update should contain a default connectivity state CONNECTING for the
   645  	// state of the new pending LB policy.
   646  	select {
   647  	case <-ctx.Done():
   648  		t.Fatalf("timeout while waiting for an UpdateState() call on the ClientConn")
   649  	case state := <-tcc.NewStateCh:
   650  		if state != connectivity.Connecting {
   651  			t.Fatalf("UpdateState(), want connectivity state %v, got %v", connectivity.Connecting, state)
   652  		}
   653  	}
   654  	// The update should contain a default picker ErrPicker in the picker sent
   655  	// for the state of the new pending LB policy.
   656  	select {
   657  	case <-ctx.Done():
   658  		t.Fatalf("timeout while waiting for an UpdateState() call on the ClientConn")
   659  	case picker := <-tcc.NewPickerCh:
   660  		if _, err := picker.Pick(balancer.PickInfo{}); err != balancer.ErrNoSubConnAvailable {
   661  			t.Fatalf("ClientConn should have received a never err picker from an UpdateState call")
   662  		}
   663  	}
   664  }
   665  
   666  // Picker which never errors here for test purposes (can fill up tests further up with this)
   667  type neverErrPicker struct{}
   668  
   669  func (p *neverErrPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
   670  	return balancer.PickResult{}, nil
   671  }
   672  
   673  // TestUpdateSubConnStateRace tests the race condition when the graceful switch
   674  // load balancer receives a SubConnUpdate concurrently with an UpdateState()
   675  // call, which can cause the balancer to forward the update to to be closed and
   676  // cleared. The balancer API guarantees to never call any method the balancer
   677  // after a Close() call, and the test verifies that doesn't happen within the
   678  // graceful switch load balancer.
   679  func (s) TestUpdateSubConnStateRace(t *testing.T) {
   680  	tcc, gsb := setup(t)
   681  	gsb.SwitchTo(verifyBalancerBuilder{})
   682  	gsb.SwitchTo(mockBalancerBuilder1{})
   683  	currBal := gsb.balancerCurrent.Balancer.(*verifyBalancer)
   684  	currBal.t = t
   685  	pendBal := gsb.balancerPending.Balancer.(*mockBalancer)
   686  	sc, err := currBal.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   687  	if err != nil {
   688  		t.Fatalf("error constructing newSubConn in gsb: %v", err)
   689  	}
   690  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   691  	defer cancel()
   692  	select {
   693  	case <-ctx.Done():
   694  		t.Fatalf("timeout while waiting for an NewSubConn call on the ClientConn")
   695  	case <-tcc.NewSubConnCh:
   696  	}
   697  	// Spawn a goroutine that constantly calls UpdateSubConn for the current
   698  	// balancer, which will get deleted in this testing goroutine.
   699  	finished := make(chan struct{})
   700  	go func() {
   701  		for {
   702  			select {
   703  			case <-finished:
   704  				return
   705  			default:
   706  			}
   707  			sc.(*testutils.TestSubConn).UpdateState(balancer.SubConnState{
   708  				ConnectivityState: connectivity.Ready,
   709  			})
   710  		}
   711  	}()
   712  	time.Sleep(time.Millisecond)
   713  	// This UpdateState call causes current to be closed/cleared.
   714  	pendBal.updateState(balancer.State{
   715  		ConnectivityState: connectivity.Ready,
   716  	})
   717  	// From this, either one of two things happen. Either the graceful switch
   718  	// load balancer doesn't Close() the current balancer before it forwards the
   719  	// SubConn update to the child, and the call gets forwarded down to the
   720  	// current balancer, or it can Close() the current balancer in between
   721  	// reading the balancer pointer and writing to it, and in that case the old
   722  	// current balancer should not be updated, as the balancer has already been
   723  	// closed and the balancer API guarantees it.
   724  	close(finished)
   725  }
   726  
   727  // TestInlineCallbackInBuild tests the scenario where a balancer calls back into
   728  // the balancer.ClientConn API inline from it's build function.
   729  func (s) TestInlineCallbackInBuild(t *testing.T) {
   730  	tcc, gsb := setup(t)
   731  	// This build call should cause all of the inline updates to forward to the
   732  	// ClientConn.
   733  	gsb.SwitchTo(buildCallbackBalancerBuilder{})
   734  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   735  	defer cancel()
   736  	select {
   737  	case <-ctx.Done():
   738  		t.Fatalf("timeout while waiting for an UpdateState() call on the ClientConn")
   739  	case <-tcc.NewStateCh:
   740  	}
   741  	select {
   742  	case <-ctx.Done():
   743  		t.Fatalf("timeout while waiting for a NewSubConn() call on the ClientConn")
   744  	case <-tcc.NewSubConnCh:
   745  	}
   746  	select {
   747  	case <-ctx.Done():
   748  		t.Fatalf("timeout while waiting for an UpdateAddresses() call on the ClientConn")
   749  	case <-tcc.UpdateAddressesAddrsCh:
   750  	}
   751  	select {
   752  	case <-ctx.Done():
   753  		t.Fatalf("timeout while waiting for a Shutdown() call on the SubConn")
   754  	case <-tcc.ShutdownSubConnCh:
   755  	}
   756  	oldCurrent := gsb.balancerCurrent.Balancer.(*buildCallbackBal)
   757  
   758  	// Since the callback reports a state READY, this new inline balancer should
   759  	// be swapped to the current.
   760  	gsb.SwitchTo(buildCallbackBalancerBuilder{})
   761  	select {
   762  	case <-ctx.Done():
   763  		t.Fatalf("timeout while waiting for an UpdateState() call on the ClientConn")
   764  	case <-tcc.NewStateCh:
   765  	}
   766  	select {
   767  	case <-ctx.Done():
   768  		t.Fatalf("timeout while waiting for a NewSubConn() call on the ClientConn")
   769  	case <-tcc.NewSubConnCh:
   770  	}
   771  	select {
   772  	case <-ctx.Done():
   773  		t.Fatalf("timeout while waiting for an UpdateAddresses() call on the ClientConn")
   774  	case <-tcc.UpdateAddressesAddrsCh:
   775  	}
   776  	select {
   777  	case <-ctx.Done():
   778  		t.Fatalf("timeout while waiting for a Shutdown() call on the SubConn")
   779  	case <-tcc.ShutdownSubConnCh:
   780  	}
   781  
   782  	// The current balancer should be closed as a result of the swap.
   783  	if err := oldCurrent.waitForClose(ctx); err != nil {
   784  		t.Fatalf("error waiting for balancer close: %v", err)
   785  	}
   786  
   787  	// The old balancer should be deprecated and any calls from it should be a no-op.
   788  	oldCurrent.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   789  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   790  	defer sCancel()
   791  	select {
   792  	case <-tcc.NewSubConnCh:
   793  		t.Fatal("Deprecated LB calling NewSubConn() should not forward up to the ClientConn")
   794  	case <-sCtx.Done():
   795  	}
   796  }
   797  
   798  // TestExitIdle tests the ExitIdle operation on the Graceful Switch Balancer for
   799  // both possible codepaths, one where the child implements ExitIdler interface
   800  // and one where the child doesn't implement ExitIdler interface.
   801  func (s) TestExitIdle(t *testing.T) {
   802  	_, gsb := setup(t)
   803  	// switch to a balancer that implements ExitIdle{} (will populate current).
   804  	gsb.SwitchTo(mockBalancerBuilder1{})
   805  	currBal := gsb.balancerCurrent.Balancer.(*mockBalancer)
   806  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   807  	defer cancel()
   808  	// exitIdle on the Graceful Switch Balancer should get forwarded to the
   809  	// current child as it implements exitIdle.
   810  	gsb.ExitIdle()
   811  	if err := currBal.waitForExitIdle(ctx); err != nil {
   812  		t.Fatal(err)
   813  	}
   814  
   815  	// switch to a balancer that doesn't implement ExitIdle{} (will populate
   816  	// pending).
   817  	gsb.SwitchTo(verifyBalancerBuilder{})
   818  	// call exitIdle concurrently with newSubConn to make sure there is not a
   819  	// data race.
   820  	done := make(chan struct{})
   821  	go func() {
   822  		gsb.ExitIdle()
   823  		close(done)
   824  	}()
   825  	pendBal := gsb.balancerPending.Balancer.(*verifyBalancer)
   826  	for i := 0; i < 10; i++ {
   827  		pendBal.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
   828  	}
   829  	<-done
   830  }
   831  
   832  const balancerName1 = "mock_balancer_1"
   833  const balancerName2 = "mock_balancer_2"
   834  const verifyBalName = "verifyNoSubConnUpdateAfterCloseBalancer"
   835  const buildCallbackBalName = "callbackInBuildBalancer"
   836  
   837  type mockBalancerBuilder1 struct{}
   838  
   839  func (mockBalancerBuilder1) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
   840  	return &mockBalancer{
   841  		ccsCh:         testutils.NewChannel(),
   842  		scStateCh:     testutils.NewChannel(),
   843  		resolverErrCh: testutils.NewChannel(),
   844  		closeCh:       testutils.NewChannel(),
   845  		exitIdleCh:    testutils.NewChannel(),
   846  		cc:            cc,
   847  	}
   848  }
   849  
   850  func (mockBalancerBuilder1) Name() string {
   851  	return balancerName1
   852  }
   853  
   854  type mockBalancerConfig struct {
   855  	serviceconfig.LoadBalancingConfig
   856  }
   857  
   858  // mockBalancer is a fake balancer used to verify different actions from
   859  // the gracefulswitch. It contains a bunch of channels to signal different events
   860  // to the test.
   861  type mockBalancer struct {
   862  	// ccsCh is a channel used to signal the receipt of a ClientConn update.
   863  	ccsCh *testutils.Channel
   864  	// scStateCh is a channel used to signal the receipt of a SubConn update.
   865  	scStateCh *testutils.Channel
   866  	// resolverErrCh is a channel used to signal a resolver error.
   867  	resolverErrCh *testutils.Channel
   868  	// closeCh is a channel used to signal the closing of this balancer.
   869  	closeCh *testutils.Channel
   870  	// exitIdleCh is a channel used to signal the receipt of an ExitIdle call.
   871  	exitIdleCh *testutils.Channel
   872  	// Hold onto ClientConn wrapper to communicate with it
   873  	cc balancer.ClientConn
   874  }
   875  
   876  type subConnWithState struct {
   877  	sc    balancer.SubConn
   878  	state balancer.SubConnState
   879  }
   880  
   881  func (mb1 *mockBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
   882  	// Need to verify this call...use a channel?...all of these will need verification
   883  	mb1.ccsCh.Send(ccs)
   884  	return nil
   885  }
   886  
   887  func (mb1 *mockBalancer) ResolverError(err error) {
   888  	mb1.resolverErrCh.Send(err)
   889  }
   890  
   891  func (mb1 *mockBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
   892  	panic(fmt.Sprintf("UpdateSubConnState(%v, %+v) called unexpectedly", sc, state))
   893  }
   894  
   895  func (mb1 *mockBalancer) Close() {
   896  	mb1.closeCh.Send(struct{}{})
   897  }
   898  
   899  func (mb1 *mockBalancer) ExitIdle() {
   900  	mb1.exitIdleCh.Send(struct{}{})
   901  }
   902  
   903  // waitForClientConnUpdate verifies if the mockBalancer receives the
   904  // provided ClientConnState within a reasonable amount of time.
   905  func (mb1 *mockBalancer) waitForClientConnUpdate(ctx context.Context, wantCCS balancer.ClientConnState) error {
   906  	ccs, err := mb1.ccsCh.Receive(ctx)
   907  	if err != nil {
   908  		return fmt.Errorf("error waiting for ClientConnUpdate: %v", err)
   909  	}
   910  	gotCCS := ccs.(balancer.ClientConnState)
   911  	if diff := cmp.Diff(gotCCS, wantCCS, cmpopts.IgnoreFields(resolver.State{}, "Attributes")); diff != "" {
   912  		return fmt.Errorf("error in ClientConnUpdate: received unexpected ClientConnState, diff (-got +want): %v", diff)
   913  	}
   914  	return nil
   915  }
   916  
   917  // waitForResolverError verifies if the mockBalancer receives the provided
   918  // resolver error before the context expires.
   919  func (mb1 *mockBalancer) waitForResolverError(ctx context.Context, wantErr error) error {
   920  	gotErr, err := mb1.resolverErrCh.Receive(ctx)
   921  	if err != nil {
   922  		return fmt.Errorf("error waiting for resolver error: %v", err)
   923  	}
   924  	if gotErr != wantErr {
   925  		return fmt.Errorf("received resolver error: %v, want %v", gotErr, wantErr)
   926  	}
   927  	return nil
   928  }
   929  
   930  // waitForClose verifies that the mockBalancer is closed before the context
   931  // expires.
   932  func (mb1 *mockBalancer) waitForClose(ctx context.Context) error {
   933  	if _, err := mb1.closeCh.Receive(ctx); err != nil {
   934  		return fmt.Errorf("error waiting for Close(): %v", err)
   935  	}
   936  	return nil
   937  }
   938  
   939  // waitForExitIdle verifies that ExitIdle gets called on the mockBalancer before
   940  // the context expires.
   941  func (mb1 *mockBalancer) waitForExitIdle(ctx context.Context) error {
   942  	if _, err := mb1.exitIdleCh.Receive(ctx); err != nil {
   943  		return fmt.Errorf("error waiting for ExitIdle(): %v", err)
   944  	}
   945  	return nil
   946  }
   947  
   948  func (mb1 *mockBalancer) updateState(state balancer.State) {
   949  	mb1.cc.UpdateState(state)
   950  }
   951  
   952  func (mb1 *mockBalancer) newSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (sc balancer.SubConn, err error) {
   953  	if opts.StateListener == nil {
   954  		opts.StateListener = func(state balancer.SubConnState) {
   955  			mb1.scStateCh.Send(subConnWithState{sc: sc, state: state})
   956  		}
   957  	}
   958  	defer func() {
   959  		if sc != nil {
   960  			sc.Connect()
   961  		}
   962  	}()
   963  	return mb1.cc.NewSubConn(addrs, opts)
   964  }
   965  
   966  func (mb1 *mockBalancer) updateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
   967  	mb1.cc.UpdateAddresses(sc, addrs)
   968  }
   969  
   970  type mockBalancerBuilder2 struct{}
   971  
   972  func (mockBalancerBuilder2) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
   973  	return &mockBalancer{
   974  		ccsCh:         testutils.NewChannel(),
   975  		scStateCh:     testutils.NewChannel(),
   976  		resolverErrCh: testutils.NewChannel(),
   977  		closeCh:       testutils.NewChannel(),
   978  		cc:            cc,
   979  	}
   980  }
   981  
   982  func (mockBalancerBuilder2) Name() string {
   983  	return balancerName2
   984  }
   985  
   986  type verifyBalancerBuilder struct{}
   987  
   988  func (verifyBalancerBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
   989  	return &verifyBalancer{
   990  		closed: grpcsync.NewEvent(),
   991  		cc:     cc,
   992  	}
   993  }
   994  
   995  func (verifyBalancerBuilder) Name() string {
   996  	return verifyBalName
   997  }
   998  
   999  // verifyBalancer is a balancer that verifies that after a Close() call, a
  1000  // StateListener() call never happens.
  1001  type verifyBalancer struct {
  1002  	closed *grpcsync.Event
  1003  	// Hold onto the ClientConn wrapper to communicate with it.
  1004  	cc balancer.ClientConn
  1005  	// To fail the test if StateListener gets called after Close().
  1006  	t *testing.T
  1007  }
  1008  
  1009  func (vb *verifyBalancer) UpdateClientConnState(ccs balancer.ClientConnState) error {
  1010  	return nil
  1011  }
  1012  
  1013  func (vb *verifyBalancer) ResolverError(err error) {}
  1014  
  1015  func (vb *verifyBalancer) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
  1016  	panic(fmt.Sprintf("UpdateSubConnState(%v, %+v) called unexpectedly", sc, state))
  1017  }
  1018  
  1019  func (vb *verifyBalancer) Close() {
  1020  	vb.closed.Fire()
  1021  }
  1022  
  1023  func (vb *verifyBalancer) newSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (sc balancer.SubConn, err error) {
  1024  	if opts.StateListener == nil {
  1025  		opts.StateListener = func(state balancer.SubConnState) {
  1026  			if vb.closed.HasFired() {
  1027  				vb.t.Fatalf("StateListener(%+v) was called after Close(), which breaks the balancer API", state)
  1028  			}
  1029  		}
  1030  	}
  1031  	defer func() { sc.Connect() }()
  1032  	return vb.cc.NewSubConn(addrs, opts)
  1033  }
  1034  
  1035  type buildCallbackBalancerBuilder struct{}
  1036  
  1037  func (buildCallbackBalancerBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
  1038  	b := &buildCallbackBal{
  1039  		cc:      cc,
  1040  		closeCh: testutils.NewChannel(),
  1041  	}
  1042  	b.updateState(balancer.State{
  1043  		ConnectivityState: connectivity.Connecting,
  1044  	})
  1045  	sc, err := b.newSubConn([]resolver.Address{}, balancer.NewSubConnOptions{})
  1046  	if err != nil {
  1047  		return nil
  1048  	}
  1049  	b.updateAddresses(sc, []resolver.Address{})
  1050  	sc.Shutdown()
  1051  	return b
  1052  }
  1053  
  1054  func (buildCallbackBalancerBuilder) Name() string {
  1055  	return buildCallbackBalName
  1056  }
  1057  
  1058  type buildCallbackBal struct {
  1059  	// Hold onto the ClientConn wrapper to communicate with it.
  1060  	cc balancer.ClientConn
  1061  	// closeCh is a channel used to signal the closing of this balancer.
  1062  	closeCh *testutils.Channel
  1063  }
  1064  
  1065  func (bcb *buildCallbackBal) UpdateClientConnState(ccs balancer.ClientConnState) error {
  1066  	return nil
  1067  }
  1068  
  1069  func (bcb *buildCallbackBal) ResolverError(err error) {}
  1070  
  1071  func (bcb *buildCallbackBal) UpdateSubConnState(sc balancer.SubConn, state balancer.SubConnState) {
  1072  	panic(fmt.Sprintf("UpdateSubConnState(%v, %+v) called unexpectedly", sc, state))
  1073  }
  1074  
  1075  func (bcb *buildCallbackBal) Close() {
  1076  	bcb.closeCh.Send(struct{}{})
  1077  }
  1078  
  1079  func (bcb *buildCallbackBal) updateState(state balancer.State) {
  1080  	bcb.cc.UpdateState(state)
  1081  }
  1082  
  1083  func (bcb *buildCallbackBal) newSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (sc balancer.SubConn, err error) {
  1084  	defer func() {
  1085  		if sc != nil {
  1086  			sc.Connect()
  1087  		}
  1088  	}()
  1089  	return bcb.cc.NewSubConn(addrs, opts)
  1090  }
  1091  
  1092  func (bcb *buildCallbackBal) updateAddresses(sc balancer.SubConn, addrs []resolver.Address) {
  1093  	bcb.cc.UpdateAddresses(sc, addrs)
  1094  }
  1095  
  1096  // waitForClose verifies that the mockBalancer is closed before the context
  1097  // expires.
  1098  func (bcb *buildCallbackBal) waitForClose(ctx context.Context) error {
  1099  	if _, err := bcb.closeCh.Receive(ctx); err != nil {
  1100  		return err
  1101  	}
  1102  	return nil
  1103  }