google.golang.org/grpc@v1.72.2/balancer/pickfirst/pickfirstleaf/pickfirstleaf_ext_test.go (about)

     1  /*
     2   *
     3   * Copyright 2024 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package pickfirstleaf_test
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/google/go-cmp/cmp"
    28  
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/balancer"
    31  	pfinternal "google.golang.org/grpc/balancer/pickfirst/internal"
    32  	"google.golang.org/grpc/balancer/pickfirst/pickfirstleaf"
    33  	"google.golang.org/grpc/codes"
    34  	"google.golang.org/grpc/connectivity"
    35  	"google.golang.org/grpc/credentials/insecure"
    36  	"google.golang.org/grpc/internal"
    37  	"google.golang.org/grpc/internal/balancer/stub"
    38  	"google.golang.org/grpc/internal/grpcsync"
    39  	"google.golang.org/grpc/internal/grpctest"
    40  	"google.golang.org/grpc/internal/stubserver"
    41  	"google.golang.org/grpc/internal/testutils"
    42  	"google.golang.org/grpc/internal/testutils/pickfirst"
    43  	"google.golang.org/grpc/internal/testutils/stats"
    44  	"google.golang.org/grpc/metadata"
    45  	"google.golang.org/grpc/resolver"
    46  	"google.golang.org/grpc/resolver/manual"
    47  	"google.golang.org/grpc/status"
    48  
    49  	testgrpc "google.golang.org/grpc/interop/grpc_testing"
    50  	testpb "google.golang.org/grpc/interop/grpc_testing"
    51  )
    52  
    53  const (
    54  	// Default timeout for tests in this package.
    55  	defaultTestTimeout = 10 * time.Second
    56  	// Default short timeout, to be used when waiting for events which are not
    57  	// expected to happen.
    58  	defaultTestShortTimeout  = 100 * time.Millisecond
    59  	stateStoringBalancerName = "state_storing"
    60  )
    61  
    62  var (
    63  	stateStoringServiceConfig = fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, stateStoringBalancerName)
    64  	ignoreBalAttributesOpt    = cmp.Transformer("IgnoreBalancerAttributes", func(a resolver.Address) resolver.Address {
    65  		a.BalancerAttributes = nil
    66  		return a
    67  	})
    68  )
    69  
    70  type s struct {
    71  	grpctest.Tester
    72  }
    73  
    74  func Test(t *testing.T) {
    75  	grpctest.RunSubTests(t, s{})
    76  }
    77  
    78  // testServer is a server than can be stopped and resumed without closing
    79  // the listener. This guarantees the same port number (and address) is used
    80  // after restart. When a server is stopped, it accepts and closes all tcp
    81  // connections from clients.
    82  type testServer struct {
    83  	stubserver.StubServer
    84  	lis *testutils.RestartableListener
    85  }
    86  
    87  func (s *testServer) stop() {
    88  	s.lis.Stop()
    89  }
    90  
    91  func (s *testServer) resume() {
    92  	s.lis.Restart()
    93  }
    94  
    95  func newTestServer(t *testing.T) *testServer {
    96  	l, err := testutils.LocalTCPListener()
    97  	if err != nil {
    98  		t.Fatalf("Failed to create listener: %v", err)
    99  	}
   100  	rl := testutils.NewRestartableListener(l)
   101  	ss := stubserver.StubServer{
   102  		EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil },
   103  		Listener:   rl,
   104  	}
   105  	return &testServer{
   106  		StubServer: ss,
   107  		lis:        rl,
   108  	}
   109  }
   110  
   111  // setupPickFirstLeaf performs steps required for pick_first tests. It starts a
   112  // bunch of backends exporting the TestService, and creates a ClientConn to them.
   113  func setupPickFirstLeaf(t *testing.T, backendCount int, opts ...grpc.DialOption) (*grpc.ClientConn, *manual.Resolver, *backendManager) {
   114  	t.Helper()
   115  	r := manual.NewBuilderWithScheme("whatever")
   116  	backends := make([]*testServer, backendCount)
   117  	addrs := make([]resolver.Address, backendCount)
   118  
   119  	for i := 0; i < backendCount; i++ {
   120  		server := newTestServer(t)
   121  		backend := stubserver.StartTestService(t, &server.StubServer)
   122  		t.Cleanup(func() {
   123  			backend.Stop()
   124  		})
   125  		backends[i] = server
   126  		addrs[i] = resolver.Address{Addr: backend.Address}
   127  	}
   128  
   129  	dopts := []grpc.DialOption{
   130  		grpc.WithTransportCredentials(insecure.NewCredentials()),
   131  		grpc.WithResolvers(r),
   132  	}
   133  	dopts = append(dopts, opts...)
   134  	cc, err := grpc.NewClient(r.Scheme()+":///test.server", dopts...)
   135  	if err != nil {
   136  		t.Fatalf("grpc.NewClient() failed: %v", err)
   137  	}
   138  	t.Cleanup(func() { cc.Close() })
   139  
   140  	// At this point, the resolver has not returned any addresses to the channel.
   141  	// This RPC must block until the context expires.
   142  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   143  	defer sCancel()
   144  	client := testgrpc.NewTestServiceClient(cc)
   145  	if _, err := client.EmptyCall(sCtx, &testpb.Empty{}); status.Code(err) != codes.DeadlineExceeded {
   146  		t.Fatalf("EmptyCall() = %s, want %s", status.Code(err), codes.DeadlineExceeded)
   147  	}
   148  	return cc, r, &backendManager{backends}
   149  }
   150  
   151  // TestPickFirstLeaf_SimpleResolverUpdate tests the behaviour of the pick first
   152  // policy when given an list of addresses. The following steps are carried
   153  // out in order:
   154  //  1. A list of addresses are given through the resolver. Only one
   155  //     of the servers is running.
   156  //  2. RPCs are sent to verify they reach the running server.
   157  //
   158  // The state transitions of the ClientConn and all the SubConns created are
   159  // verified.
   160  func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerReady(t *testing.T) {
   161  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   162  	defer cancel()
   163  	balCh := make(chan *stateStoringBalancer, 1)
   164  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   165  
   166  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   167  	addrs := bm.resolverAddrs()
   168  	stateSubscriber := &ccStateSubscriber{}
   169  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   170  
   171  	r.UpdateState(resolver.State{Addresses: addrs})
   172  	var bal *stateStoringBalancer
   173  	select {
   174  	case bal = <-balCh:
   175  	case <-ctx.Done():
   176  		t.Fatal("Context expired while waiting for balancer to be built")
   177  	}
   178  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   179  
   180  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   181  		t.Fatal(err)
   182  	}
   183  
   184  	wantSCStates := []scState{
   185  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready},
   186  	}
   187  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   188  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   189  	}
   190  
   191  	wantConnStateTransitions := []connectivity.State{
   192  		connectivity.Connecting,
   193  		connectivity.Ready,
   194  	}
   195  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   196  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   197  	}
   198  }
   199  
   200  func (s) TestPickFirstLeaf_SimpleResolverUpdate_FirstServerUnReady(t *testing.T) {
   201  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   202  	defer cancel()
   203  	balCh := make(chan *stateStoringBalancer, 1)
   204  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   205  
   206  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   207  	addrs := bm.resolverAddrs()
   208  	stateSubscriber := &ccStateSubscriber{}
   209  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   210  	bm.stopAllExcept(1)
   211  
   212  	r.UpdateState(resolver.State{Addresses: addrs})
   213  	var bal *stateStoringBalancer
   214  	select {
   215  	case bal = <-balCh:
   216  	case <-ctx.Done():
   217  		t.Fatal("Context expired while waiting for balancer to be built")
   218  	}
   219  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   220  
   221  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   222  		t.Fatal(err)
   223  	}
   224  
   225  	wantSCStates := []scState{
   226  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   227  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   228  	}
   229  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   230  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   231  	}
   232  
   233  	wantConnStateTransitions := []connectivity.State{
   234  		connectivity.Connecting,
   235  		connectivity.Ready,
   236  	}
   237  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   238  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   239  	}
   240  }
   241  
   242  func (s) TestPickFirstLeaf_SimpleResolverUpdate_DuplicateAddrs(t *testing.T) {
   243  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   244  	defer cancel()
   245  	balCh := make(chan *stateStoringBalancer, 1)
   246  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   247  
   248  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   249  	addrs := bm.resolverAddrs()
   250  	stateSubscriber := &ccStateSubscriber{}
   251  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   252  	bm.stopAllExcept(1)
   253  
   254  	// Add a duplicate entry in the addresslist
   255  	r.UpdateState(resolver.State{
   256  		Addresses: append([]resolver.Address{addrs[0]}, addrs...),
   257  	})
   258  	var bal *stateStoringBalancer
   259  	select {
   260  	case bal = <-balCh:
   261  	case <-ctx.Done():
   262  		t.Fatal("Context expired while waiting for balancer to be built")
   263  	}
   264  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   265  
   266  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   267  		t.Fatal(err)
   268  	}
   269  
   270  	wantSCStates := []scState{
   271  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   272  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   273  	}
   274  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   275  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   276  	}
   277  
   278  	wantConnStateTransitions := []connectivity.State{
   279  		connectivity.Connecting,
   280  		connectivity.Ready,
   281  	}
   282  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   283  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   284  	}
   285  }
   286  
   287  // TestPickFirstLeaf_ResolverUpdates_DisjointLists tests the behaviour of the pick first
   288  // policy when the following steps are carried out in order:
   289  //  1. A list of addresses are given through the resolver. Only one
   290  //     of the servers is running.
   291  //  2. RPCs are sent to verify they reach the running server.
   292  //  3. A second resolver update is sent. Again, only one of the servers is
   293  //     running. This may not be the same server as before.
   294  //  4. RPCs are sent to verify they reach the running server.
   295  //
   296  // The state transitions of the ClientConn and all the SubConns created are
   297  // verified.
   298  func (s) TestPickFirstLeaf_ResolverUpdates_DisjointLists(t *testing.T) {
   299  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   300  	defer cancel()
   301  
   302  	balCh := make(chan *stateStoringBalancer, 1)
   303  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   304  	cc, r, bm := setupPickFirstLeaf(t, 4, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   305  	addrs := bm.resolverAddrs()
   306  	stateSubscriber := &ccStateSubscriber{}
   307  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   308  
   309  	bm.backends[0].stop()
   310  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[1]}})
   311  	var bal *stateStoringBalancer
   312  	select {
   313  	case bal = <-balCh:
   314  	case <-ctx.Done():
   315  		t.Fatal("Context expired while waiting for balancer to be built")
   316  	}
   317  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   318  
   319  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   320  		t.Fatal(err)
   321  	}
   322  	wantSCStates := []scState{
   323  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   324  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   325  	}
   326  
   327  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   328  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   329  	}
   330  
   331  	bm.backends[2].stop()
   332  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[2], addrs[3]}})
   333  
   334  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[3]); err != nil {
   335  		t.Fatal(err)
   336  	}
   337  	wantSCStates = []scState{
   338  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   339  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Shutdown},
   340  		{Addrs: []resolver.Address{addrs[2]}, State: connectivity.Shutdown},
   341  		{Addrs: []resolver.Address{addrs[3]}, State: connectivity.Ready},
   342  	}
   343  
   344  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   345  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   346  	}
   347  
   348  	wantConnStateTransitions := []connectivity.State{
   349  		connectivity.Connecting,
   350  		connectivity.Ready,
   351  		connectivity.Connecting,
   352  		connectivity.Ready,
   353  	}
   354  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   355  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   356  	}
   357  }
   358  
   359  func (s) TestPickFirstLeaf_ResolverUpdates_ActiveBackendInUpdatedList(t *testing.T) {
   360  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   361  	defer cancel()
   362  
   363  	balCh := make(chan *stateStoringBalancer, 1)
   364  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   365  	cc, r, bm := setupPickFirstLeaf(t, 3, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   366  	addrs := bm.resolverAddrs()
   367  	stateSubscriber := &ccStateSubscriber{}
   368  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   369  
   370  	bm.backends[0].stop()
   371  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[1]}})
   372  	var bal *stateStoringBalancer
   373  	select {
   374  	case bal = <-balCh:
   375  	case <-ctx.Done():
   376  		t.Fatal("Context expired while waiting for balancer to be built")
   377  	}
   378  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   379  
   380  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   381  		t.Fatal(err)
   382  	}
   383  	wantSCStates := []scState{
   384  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   385  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   386  	}
   387  
   388  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   389  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   390  	}
   391  
   392  	bm.backends[2].stop()
   393  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[2], addrs[1]}})
   394  
   395  	// Verify that the ClientConn stays in READY.
   396  	sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
   397  	defer sCancel()
   398  	testutils.AwaitNoStateChange(sCtx, t, cc, connectivity.Ready)
   399  
   400  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	wantSCStates = []scState{
   404  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   405  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   406  	}
   407  
   408  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   409  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   410  	}
   411  
   412  	wantConnStateTransitions := []connectivity.State{
   413  		connectivity.Connecting,
   414  		connectivity.Ready,
   415  	}
   416  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   417  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   418  	}
   419  }
   420  
   421  func (s) TestPickFirstLeaf_ResolverUpdates_InActiveBackendInUpdatedList(t *testing.T) {
   422  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   423  	defer cancel()
   424  
   425  	balCh := make(chan *stateStoringBalancer, 1)
   426  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   427  	cc, r, bm := setupPickFirstLeaf(t, 3, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   428  	addrs := bm.resolverAddrs()
   429  	stateSubscriber := &ccStateSubscriber{}
   430  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   431  
   432  	bm.backends[0].stop()
   433  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[1]}})
   434  	var bal *stateStoringBalancer
   435  	select {
   436  	case bal = <-balCh:
   437  	case <-ctx.Done():
   438  		t.Fatal("Context expired while waiting for balancer to be built")
   439  	}
   440  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   441  
   442  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   443  		t.Fatal(err)
   444  	}
   445  	wantSCStates := []scState{
   446  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   447  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   448  	}
   449  
   450  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   451  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   452  	}
   453  
   454  	bm.backends[2].stop()
   455  	bm.backends[0].resume()
   456  
   457  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[2]}})
   458  
   459  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   460  		t.Fatal(err)
   461  	}
   462  	wantSCStates = []scState{
   463  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   464  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Shutdown},
   465  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready},
   466  	}
   467  
   468  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   469  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   470  	}
   471  
   472  	wantConnStateTransitions := []connectivity.State{
   473  		connectivity.Connecting,
   474  		connectivity.Ready,
   475  		connectivity.Connecting,
   476  		connectivity.Ready,
   477  	}
   478  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   479  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   480  	}
   481  }
   482  
   483  func (s) TestPickFirstLeaf_ResolverUpdates_IdenticalLists(t *testing.T) {
   484  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   485  	defer cancel()
   486  
   487  	balCh := make(chan *stateStoringBalancer, 1)
   488  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   489  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   490  	addrs := bm.resolverAddrs()
   491  	stateSubscriber := &ccStateSubscriber{}
   492  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   493  
   494  	bm.backends[0].stop()
   495  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[1]}})
   496  	var bal *stateStoringBalancer
   497  	select {
   498  	case bal = <-balCh:
   499  	case <-ctx.Done():
   500  		t.Fatal("Context expired while waiting for balancer to be built")
   501  	}
   502  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   503  
   504  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   505  		t.Fatal(err)
   506  	}
   507  	wantSCStates := []scState{
   508  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   509  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   510  	}
   511  
   512  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   513  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   514  	}
   515  
   516  	r.UpdateState(resolver.State{Addresses: []resolver.Address{addrs[0], addrs[1]}})
   517  
   518  	// Verify that the ClientConn stays in READY.
   519  	sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
   520  	defer sCancel()
   521  	testutils.AwaitNoStateChange(sCtx, t, cc, connectivity.Ready)
   522  
   523  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   524  		t.Fatal(err)
   525  	}
   526  	wantSCStates = []scState{
   527  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   528  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   529  	}
   530  
   531  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   532  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   533  	}
   534  
   535  	wantConnStateTransitions := []connectivity.State{
   536  		connectivity.Connecting,
   537  		connectivity.Ready,
   538  	}
   539  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   540  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   541  	}
   542  }
   543  
   544  // TestPickFirstLeaf_StopConnectedServer tests the behaviour of the pick first
   545  // policy when the connected server is shut down. It carries out the following
   546  // steps in order:
   547  //  1. A list of addresses are given through the resolver. Only one
   548  //     of the servers is running.
   549  //  2. The running server is stopped, causing the ClientConn to enter IDLE.
   550  //  3. A (possibly different) server is started.
   551  //  4. RPCs are made to kick the ClientConn out of IDLE. The test verifies that
   552  //     the RPCs reach the running server.
   553  //
   554  // The test verifies the ClientConn state transitions.
   555  func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerRestart(t *testing.T) {
   556  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   557  	defer cancel()
   558  
   559  	balCh := make(chan *stateStoringBalancer, 1)
   560  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   561  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   562  	addrs := bm.resolverAddrs()
   563  	stateSubscriber := &ccStateSubscriber{}
   564  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   565  
   566  	// shutdown all active backends except the target.
   567  	bm.stopAllExcept(0)
   568  
   569  	r.UpdateState(resolver.State{Addresses: addrs})
   570  	var bal *stateStoringBalancer
   571  	select {
   572  	case bal = <-balCh:
   573  	case <-ctx.Done():
   574  		t.Fatal("Context expired while waiting for balancer to be built")
   575  	}
   576  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   577  
   578  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   579  		t.Fatal(err)
   580  	}
   581  
   582  	wantSCStates := []scState{
   583  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready},
   584  	}
   585  
   586  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   587  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   588  	}
   589  
   590  	// Shut down the connected server.
   591  	bm.backends[0].stop()
   592  	testutils.AwaitState(ctx, t, cc, connectivity.Idle)
   593  
   594  	// Start the new target server.
   595  	bm.backends[0].resume()
   596  
   597  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   598  		t.Fatal(err)
   599  	}
   600  
   601  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   602  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   603  	}
   604  
   605  	wantConnStateTransitions := []connectivity.State{
   606  		connectivity.Connecting,
   607  		connectivity.Ready,
   608  		connectivity.Idle,
   609  		connectivity.Connecting,
   610  		connectivity.Ready,
   611  	}
   612  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   613  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   614  	}
   615  }
   616  
   617  func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerRestart(t *testing.T) {
   618  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   619  	defer cancel()
   620  
   621  	balCh := make(chan *stateStoringBalancer, 1)
   622  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   623  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   624  	addrs := bm.resolverAddrs()
   625  	stateSubscriber := &ccStateSubscriber{}
   626  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   627  
   628  	// shutdown all active backends except the target.
   629  	bm.stopAllExcept(1)
   630  
   631  	r.UpdateState(resolver.State{Addresses: addrs})
   632  	var bal *stateStoringBalancer
   633  	select {
   634  	case bal = <-balCh:
   635  	case <-ctx.Done():
   636  		t.Fatal("Context expired while waiting for balancer to be built")
   637  	}
   638  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   639  
   640  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   641  		t.Fatal(err)
   642  	}
   643  
   644  	wantSCStates := []scState{
   645  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   646  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   647  	}
   648  
   649  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   650  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   651  	}
   652  
   653  	// Shut down the connected server.
   654  	bm.backends[1].stop()
   655  	testutils.AwaitState(ctx, t, cc, connectivity.Idle)
   656  
   657  	// Start the new target server.
   658  	bm.backends[1].resume()
   659  
   660  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   661  		t.Fatal(err)
   662  	}
   663  
   664  	wantSCStates = []scState{
   665  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   666  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   667  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   668  	}
   669  
   670  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   671  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   672  	}
   673  
   674  	wantConnStateTransitions := []connectivity.State{
   675  		connectivity.Connecting,
   676  		connectivity.Ready,
   677  		connectivity.Idle,
   678  		connectivity.Connecting,
   679  		connectivity.Ready,
   680  	}
   681  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   682  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   683  	}
   684  }
   685  
   686  func (s) TestPickFirstLeaf_StopConnectedServer_SecondServerToFirst(t *testing.T) {
   687  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   688  	defer cancel()
   689  
   690  	balCh := make(chan *stateStoringBalancer, 1)
   691  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   692  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   693  	addrs := bm.resolverAddrs()
   694  	stateSubscriber := &ccStateSubscriber{}
   695  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   696  
   697  	// shutdown all active backends except the target.
   698  	bm.stopAllExcept(1)
   699  
   700  	r.UpdateState(resolver.State{Addresses: addrs})
   701  	var bal *stateStoringBalancer
   702  	select {
   703  	case bal = <-balCh:
   704  	case <-ctx.Done():
   705  		t.Fatal("Context expired while waiting for balancer to be built")
   706  	}
   707  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   708  
   709  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   710  		t.Fatal(err)
   711  	}
   712  
   713  	wantSCStates := []scState{
   714  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   715  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   716  	}
   717  
   718  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   719  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   720  	}
   721  
   722  	// Shut down the connected server.
   723  	bm.backends[1].stop()
   724  	testutils.AwaitState(ctx, t, cc, connectivity.Idle)
   725  
   726  	// Start the new target server.
   727  	bm.backends[0].resume()
   728  
   729  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   730  		t.Fatal(err)
   731  	}
   732  
   733  	wantSCStates = []scState{
   734  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   735  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Shutdown},
   736  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready},
   737  	}
   738  
   739  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   740  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   741  	}
   742  
   743  	wantConnStateTransitions := []connectivity.State{
   744  		connectivity.Connecting,
   745  		connectivity.Ready,
   746  		connectivity.Idle,
   747  		connectivity.Connecting,
   748  		connectivity.Ready,
   749  	}
   750  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   751  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   752  	}
   753  }
   754  
   755  func (s) TestPickFirstLeaf_StopConnectedServer_FirstServerToSecond(t *testing.T) {
   756  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   757  	defer cancel()
   758  
   759  	balCh := make(chan *stateStoringBalancer, 1)
   760  	balancer.Register(&stateStoringBalancerBuilder{balancer: balCh})
   761  	cc, r, bm := setupPickFirstLeaf(t, 2, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   762  	addrs := bm.resolverAddrs()
   763  	stateSubscriber := &ccStateSubscriber{}
   764  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   765  
   766  	// shutdown all active backends except the target.
   767  	bm.stopAllExcept(0)
   768  
   769  	r.UpdateState(resolver.State{Addresses: addrs})
   770  	var bal *stateStoringBalancer
   771  	select {
   772  	case bal = <-balCh:
   773  	case <-ctx.Done():
   774  		t.Fatal("Context expired while waiting for balancer to be built")
   775  	}
   776  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   777  
   778  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   779  		t.Fatal(err)
   780  	}
   781  
   782  	wantSCStates := []scState{
   783  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Ready},
   784  	}
   785  
   786  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   787  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   788  	}
   789  
   790  	// Shut down the connected server.
   791  	bm.backends[0].stop()
   792  	testutils.AwaitState(ctx, t, cc, connectivity.Idle)
   793  
   794  	// Start the new target server.
   795  	bm.backends[1].resume()
   796  
   797  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
   798  		t.Fatal(err)
   799  	}
   800  
   801  	wantSCStates = []scState{
   802  		{Addrs: []resolver.Address{addrs[0]}, State: connectivity.Shutdown},
   803  		{Addrs: []resolver.Address{addrs[1]}, State: connectivity.Ready},
   804  	}
   805  
   806  	if diff := cmp.Diff(wantSCStates, bal.subConnStates(), ignoreBalAttributesOpt); diff != "" {
   807  		t.Errorf("SubConn states mismatch (-want +got):\n%s", diff)
   808  	}
   809  
   810  	wantConnStateTransitions := []connectivity.State{
   811  		connectivity.Connecting,
   812  		connectivity.Ready,
   813  		connectivity.Idle,
   814  		connectivity.Connecting,
   815  		connectivity.Ready,
   816  	}
   817  	if diff := cmp.Diff(wantConnStateTransitions, stateSubscriber.transitions()); diff != "" {
   818  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   819  	}
   820  }
   821  
   822  // TestPickFirstLeaf_EmptyAddressList carries out the following steps in order:
   823  // 1. Send a resolver update with one running backend.
   824  // 2. Send an empty address list causing the balancer to enter TRANSIENT_FAILURE.
   825  // 3. Send a resolver update with one running backend.
   826  // The test verifies the ClientConn state transitions.
   827  func (s) TestPickFirstLeaf_EmptyAddressList(t *testing.T) {
   828  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   829  	defer cancel()
   830  	balChan := make(chan *stateStoringBalancer, 1)
   831  	balancer.Register(&stateStoringBalancerBuilder{balancer: balChan})
   832  	cc, r, bm := setupPickFirstLeaf(t, 1, grpc.WithDefaultServiceConfig(stateStoringServiceConfig))
   833  	addrs := bm.resolverAddrs()
   834  
   835  	stateSubscriber := &ccStateSubscriber{}
   836  	internal.SubscribeToConnectivityStateChanges.(func(cc *grpc.ClientConn, s grpcsync.Subscriber) func())(cc, stateSubscriber)
   837  
   838  	r.UpdateState(resolver.State{Addresses: addrs})
   839  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   840  
   841  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   842  		t.Fatal(err)
   843  	}
   844  
   845  	r.UpdateState(resolver.State{})
   846  	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
   847  
   848  	// The balancer should have entered transient failure.
   849  	// It should transition to CONNECTING from TRANSIENT_FAILURE as sticky TF
   850  	// only applies when the initial TF is reported due to connection failures
   851  	// and not bad resolver states.
   852  	r.UpdateState(resolver.State{Addresses: addrs})
   853  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
   854  
   855  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
   856  		t.Fatal(err)
   857  	}
   858  
   859  	wantTransitions := []connectivity.State{
   860  		// From first resolver update.
   861  		connectivity.Connecting,
   862  		connectivity.Ready,
   863  		// From second update.
   864  		connectivity.TransientFailure,
   865  		// From third update.
   866  		connectivity.Connecting,
   867  		connectivity.Ready,
   868  	}
   869  
   870  	if diff := cmp.Diff(wantTransitions, stateSubscriber.transitions()); diff != "" {
   871  		t.Errorf("ClientConn states mismatch (-want +got):\n%s", diff)
   872  	}
   873  }
   874  
   875  // Test verifies that pickfirst correctly detects the end of the first happy
   876  // eyeballs pass when the timer causes pickfirst to reach the end of the address
   877  // list and failures are reported out of order.
   878  func (s) TestPickFirstLeaf_HappyEyeballs_TF_AfterEndOfList(t *testing.T) {
   879  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   880  	defer cancel()
   881  
   882  	originalTimer := pfinternal.TimeAfterFunc
   883  	defer func() {
   884  		pfinternal.TimeAfterFunc = originalTimer
   885  	}()
   886  	triggerTimer, timeAfter := mockTimer()
   887  	pfinternal.TimeAfterFunc = timeAfter
   888  
   889  	tmr := stats.NewTestMetricsRecorder()
   890  	dialer := testutils.NewBlockingDialer()
   891  	opts := []grpc.DialOption{
   892  		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, pickfirstleaf.Name)),
   893  		grpc.WithContextDialer(dialer.DialContext),
   894  		grpc.WithStatsHandler(tmr),
   895  	}
   896  	cc, rb, bm := setupPickFirstLeaf(t, 3, opts...)
   897  	addrs := bm.resolverAddrs()
   898  	holds := bm.holds(dialer)
   899  	rb.UpdateState(resolver.State{Addresses: addrs})
   900  	cc.Connect()
   901  
   902  	testutils.AwaitState(ctx, t, cc, connectivity.Connecting)
   903  
   904  	// Verify that only the first server is contacted.
   905  	if holds[0].Wait(ctx) != true {
   906  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 0, addrs[0])
   907  	}
   908  	if holds[1].IsStarted() != false {
   909  		t.Fatalf("Server %d with address %q contacted unexpectedly", 1, addrs[1])
   910  	}
   911  	if holds[2].IsStarted() != false {
   912  		t.Fatalf("Server %d with address %q contacted unexpectedly", 2, addrs[2])
   913  	}
   914  
   915  	// Make the happy eyeballs timer fire once and verify that the
   916  	// second server is contacted, but the third isn't.
   917  	triggerTimer()
   918  	if holds[1].Wait(ctx) != true {
   919  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 1, addrs[1])
   920  	}
   921  	if holds[2].IsStarted() != false {
   922  		t.Fatalf("Server %d with address %q contacted unexpectedly", 2, addrs[2])
   923  	}
   924  
   925  	// Make the happy eyeballs timer fire once more and verify that the
   926  	// third server is contacted.
   927  	triggerTimer()
   928  	if holds[2].Wait(ctx) != true {
   929  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 2, addrs[2])
   930  	}
   931  
   932  	// First SubConn Fails.
   933  	holds[0].Fail(fmt.Errorf("test error"))
   934  	tmr.WaitForInt64CountIncr(ctx, 1)
   935  
   936  	// No TF should be reported until the first pass is complete.
   937  	shortCtx, shortCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
   938  	defer shortCancel()
   939  	testutils.AwaitNotState(shortCtx, t, cc, connectivity.TransientFailure)
   940  
   941  	// Third SubConn fails.
   942  	shortCtx, shortCancel = context.WithTimeout(ctx, defaultTestShortTimeout)
   943  	defer shortCancel()
   944  	holds[2].Fail(fmt.Errorf("test error"))
   945  	tmr.WaitForInt64CountIncr(ctx, 1)
   946  	testutils.AwaitNotState(shortCtx, t, cc, connectivity.TransientFailure)
   947  
   948  	// Last SubConn fails, this should result in a TF update.
   949  	holds[1].Fail(fmt.Errorf("test error"))
   950  	tmr.WaitForInt64CountIncr(ctx, 1)
   951  	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
   952  
   953  	// Only connection attempt fails in this test.
   954  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_succeeded"); got != 0 {
   955  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_succeeded", got, 0)
   956  	}
   957  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_failed"); got != 1 {
   958  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_failed", got, 1)
   959  	}
   960  	if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
   961  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
   962  	}
   963  }
   964  
   965  // Test verifies that pickfirst attempts to connect to the second backend once
   966  // the happy eyeballs timer expires.
   967  func (s) TestPickFirstLeaf_HappyEyeballs_TriggerConnectionDelay(t *testing.T) {
   968  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   969  	defer cancel()
   970  
   971  	originalTimer := pfinternal.TimeAfterFunc
   972  	defer func() {
   973  		pfinternal.TimeAfterFunc = originalTimer
   974  	}()
   975  	triggerTimer, timeAfter := mockTimer()
   976  	pfinternal.TimeAfterFunc = timeAfter
   977  
   978  	tmr := stats.NewTestMetricsRecorder()
   979  	dialer := testutils.NewBlockingDialer()
   980  	opts := []grpc.DialOption{
   981  		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, pickfirstleaf.Name)),
   982  		grpc.WithContextDialer(dialer.DialContext),
   983  		grpc.WithStatsHandler(tmr),
   984  	}
   985  	cc, rb, bm := setupPickFirstLeaf(t, 2, opts...)
   986  	addrs := bm.resolverAddrs()
   987  	holds := bm.holds(dialer)
   988  	rb.UpdateState(resolver.State{Addresses: addrs})
   989  	cc.Connect()
   990  
   991  	testutils.AwaitState(ctx, t, cc, connectivity.Connecting)
   992  
   993  	// Verify that only the first server is contacted.
   994  	if holds[0].Wait(ctx) != true {
   995  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 0, addrs[0])
   996  	}
   997  	if holds[1].IsStarted() != false {
   998  		t.Fatalf("Server %d with address %q contacted unexpectedly", 1, addrs[1])
   999  	}
  1000  
  1001  	// Make the happy eyeballs timer fire once and verify that the
  1002  	// second server is contacted.
  1003  	triggerTimer()
  1004  	if holds[1].Wait(ctx) != true {
  1005  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 1, addrs[1])
  1006  	}
  1007  
  1008  	// Get the connection attempt to the second server to succeed and verify
  1009  	// that the channel becomes READY.
  1010  	holds[1].Resume()
  1011  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
  1012  
  1013  	// Only connection attempt successes in this test.
  1014  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_succeeded"); got != 1 {
  1015  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_succeeded", got, 1)
  1016  	}
  1017  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_failed"); got != 0 {
  1018  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_failed", got, 0)
  1019  	}
  1020  	if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
  1021  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
  1022  	}
  1023  }
  1024  
  1025  // Test tests the pickfirst balancer by causing a SubConn to fail and then
  1026  // jumping to the 3rd SubConn after the happy eyeballs timer expires.
  1027  func (s) TestPickFirstLeaf_HappyEyeballs_TF_ThenTimerFires(t *testing.T) {
  1028  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1029  	defer cancel()
  1030  
  1031  	originalTimer := pfinternal.TimeAfterFunc
  1032  	defer func() {
  1033  		pfinternal.TimeAfterFunc = originalTimer
  1034  	}()
  1035  	triggerTimer, timeAfter := mockTimer()
  1036  	pfinternal.TimeAfterFunc = timeAfter
  1037  
  1038  	tmr := stats.NewTestMetricsRecorder()
  1039  	dialer := testutils.NewBlockingDialer()
  1040  	opts := []grpc.DialOption{
  1041  		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, pickfirstleaf.Name)),
  1042  		grpc.WithContextDialer(dialer.DialContext),
  1043  		grpc.WithStatsHandler(tmr),
  1044  	}
  1045  	cc, rb, bm := setupPickFirstLeaf(t, 3, opts...)
  1046  	addrs := bm.resolverAddrs()
  1047  	holds := bm.holds(dialer)
  1048  	rb.UpdateState(resolver.State{Addresses: addrs})
  1049  	cc.Connect()
  1050  
  1051  	testutils.AwaitState(ctx, t, cc, connectivity.Connecting)
  1052  
  1053  	// Verify that only the first server is contacted.
  1054  	if holds[0].Wait(ctx) != true {
  1055  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 0, addrs[0])
  1056  	}
  1057  	if holds[1].IsStarted() != false {
  1058  		t.Fatalf("Server %d with address %q contacted unexpectedly", 1, addrs[1])
  1059  	}
  1060  	if holds[2].IsStarted() != false {
  1061  		t.Fatalf("Server %d with address %q contacted unexpectedly", 2, addrs[2])
  1062  	}
  1063  
  1064  	// First SubConn Fails.
  1065  	holds[0].Fail(fmt.Errorf("test error"))
  1066  
  1067  	// Verify that only the second server is contacted.
  1068  	if holds[1].Wait(ctx) != true {
  1069  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 1, addrs[1])
  1070  	}
  1071  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_failed"); got != 1 {
  1072  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_failed", got, 1)
  1073  	}
  1074  	if holds[2].IsStarted() != false {
  1075  		t.Fatalf("Server %d with address %q contacted unexpectedly", 2, addrs[2])
  1076  	}
  1077  
  1078  	// The happy eyeballs timer expires, pickfirst should stop waiting for
  1079  	// server[1] to report a failure/success and request the creation of a third
  1080  	// SubConn.
  1081  	triggerTimer()
  1082  	if holds[2].Wait(ctx) != true {
  1083  		t.Fatalf("Timeout waiting for server %d with address %q to be contacted", 2, addrs[2])
  1084  	}
  1085  
  1086  	// Get the connection attempt to the second server to succeed and verify
  1087  	// that the channel becomes READY.
  1088  	holds[1].Resume()
  1089  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
  1090  
  1091  	if got, _ := tmr.Metric("grpc.lb.pick_first.connection_attempts_succeeded"); got != 1 {
  1092  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.connection_attempts_succeeded", got, 1)
  1093  	}
  1094  	if got, _ := tmr.Metric("grpc.lb.pick_first.disconnections"); got != 0 {
  1095  		t.Errorf("Unexpected data for metric %v, got: %v, want: %v", "grpc.lb.pick_first.disconnections", got, 0)
  1096  	}
  1097  }
  1098  
  1099  func (s) TestPickFirstLeaf_InterleavingIPV4Preffered(t *testing.T) {
  1100  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1101  	defer cancel()
  1102  	cc := testutils.NewBalancerClientConn(t)
  1103  	bal := balancer.Get(pickfirstleaf.Name).Build(cc, balancer.BuildOptions{})
  1104  	defer bal.Close()
  1105  	ccState := balancer.ClientConnState{
  1106  		ResolverState: resolver.State{
  1107  			Endpoints: []resolver.Endpoint{
  1108  				{Addresses: []resolver.Address{{Addr: "1.1.1.1:1111"}}},
  1109  				{Addresses: []resolver.Address{{Addr: "2.2.2.2:2"}}},
  1110  				{Addresses: []resolver.Address{{Addr: "3.3.3.3:3"}}},
  1111  				// IPv4-mapped IPv6 address, considered as an IPv4 for
  1112  				// interleaving.
  1113  				{Addresses: []resolver.Address{{Addr: "[::FFFF:192.168.0.1]:2222"}}},
  1114  				{Addresses: []resolver.Address{{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"}}},
  1115  				{Addresses: []resolver.Address{{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:8080"}}},
  1116  				{Addresses: []resolver.Address{{Addr: "[fe80::1%eth0]:3333"}}},
  1117  				{Addresses: []resolver.Address{{Addr: "grpc.io:80"}}}, // not an IP.
  1118  			},
  1119  		},
  1120  	}
  1121  	if err := bal.UpdateClientConnState(ccState); err != nil {
  1122  		t.Fatalf("UpdateClientConnState(%v) returned error: %v", ccState, err)
  1123  	}
  1124  
  1125  	wantAddrs := []resolver.Address{
  1126  		{Addr: "1.1.1.1:1111"},
  1127  		{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"},
  1128  		{Addr: "grpc.io:80"},
  1129  		{Addr: "2.2.2.2:2"},
  1130  		{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:8080"},
  1131  		{Addr: "3.3.3.3:3"},
  1132  		{Addr: "[fe80::1%eth0]:3333"},
  1133  		{Addr: "[::FFFF:192.168.0.1]:2222"},
  1134  	}
  1135  
  1136  	gotAddrs, err := subConnAddresses(ctx, cc, 8)
  1137  	if err != nil {
  1138  		t.Fatalf("%v", err)
  1139  	}
  1140  	if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" {
  1141  		t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff)
  1142  	}
  1143  }
  1144  
  1145  func (s) TestPickFirstLeaf_InterleavingIPv6Preffered(t *testing.T) {
  1146  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1147  	defer cancel()
  1148  	cc := testutils.NewBalancerClientConn(t)
  1149  	bal := balancer.Get(pickfirstleaf.Name).Build(cc, balancer.BuildOptions{})
  1150  	defer bal.Close()
  1151  	ccState := balancer.ClientConnState{
  1152  		ResolverState: resolver.State{
  1153  			Endpoints: []resolver.Endpoint{
  1154  				{Addresses: []resolver.Address{{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"}}},
  1155  				{Addresses: []resolver.Address{{Addr: "1.1.1.1:1111"}}},
  1156  				{Addresses: []resolver.Address{{Addr: "2.2.2.2:2"}}},
  1157  				{Addresses: []resolver.Address{{Addr: "3.3.3.3:3"}}},
  1158  				{Addresses: []resolver.Address{{Addr: "[::FFFF:192.168.0.1]:2222"}}},
  1159  				{Addresses: []resolver.Address{{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:2222"}}},
  1160  				{Addresses: []resolver.Address{{Addr: "[fe80::1%eth0]:3333"}}},
  1161  				{Addresses: []resolver.Address{{Addr: "grpc.io:80"}}}, // not an IP.
  1162  			},
  1163  		},
  1164  	}
  1165  	if err := bal.UpdateClientConnState(ccState); err != nil {
  1166  		t.Fatalf("UpdateClientConnState(%v) returned error: %v", ccState, err)
  1167  	}
  1168  
  1169  	wantAddrs := []resolver.Address{
  1170  		{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"},
  1171  		{Addr: "1.1.1.1:1111"},
  1172  		{Addr: "grpc.io:80"},
  1173  		{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:2222"},
  1174  		{Addr: "2.2.2.2:2"},
  1175  		{Addr: "[fe80::1%eth0]:3333"},
  1176  		{Addr: "3.3.3.3:3"},
  1177  		{Addr: "[::FFFF:192.168.0.1]:2222"},
  1178  	}
  1179  
  1180  	gotAddrs, err := subConnAddresses(ctx, cc, 8)
  1181  	if err != nil {
  1182  		t.Fatalf("%v", err)
  1183  	}
  1184  	if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" {
  1185  		t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff)
  1186  	}
  1187  }
  1188  
  1189  func (s) TestPickFirstLeaf_InterleavingUnknownPreffered(t *testing.T) {
  1190  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1191  	defer cancel()
  1192  	cc := testutils.NewBalancerClientConn(t)
  1193  	bal := balancer.Get(pickfirstleaf.Name).Build(cc, balancer.BuildOptions{})
  1194  	defer bal.Close()
  1195  	ccState := balancer.ClientConnState{
  1196  		ResolverState: resolver.State{
  1197  			Endpoints: []resolver.Endpoint{
  1198  				{Addresses: []resolver.Address{{Addr: "grpc.io:80"}}}, // not an IP.
  1199  				{Addresses: []resolver.Address{{Addr: "1.1.1.1:1111"}}},
  1200  				{Addresses: []resolver.Address{{Addr: "2.2.2.2:2"}}},
  1201  				{Addresses: []resolver.Address{{Addr: "3.3.3.3:3"}}},
  1202  				{Addresses: []resolver.Address{{Addr: "[::FFFF:192.168.0.1]:2222"}}},
  1203  				{Addresses: []resolver.Address{{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"}}},
  1204  				{Addresses: []resolver.Address{{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:8080"}}},
  1205  				{Addresses: []resolver.Address{{Addr: "[fe80::1%eth0]:3333"}}},
  1206  				{Addresses: []resolver.Address{{Addr: "example.com:80"}}}, // not an IP.
  1207  			},
  1208  		},
  1209  	}
  1210  	if err := bal.UpdateClientConnState(ccState); err != nil {
  1211  		t.Fatalf("UpdateClientConnState(%v) returned error: %v", ccState, err)
  1212  	}
  1213  
  1214  	wantAddrs := []resolver.Address{
  1215  		{Addr: "grpc.io:80"},
  1216  		{Addr: "1.1.1.1:1111"},
  1217  		{Addr: "[0001:0001:0001:0001:0001:0001:0001:0001]:8080"},
  1218  		{Addr: "example.com:80"},
  1219  		{Addr: "2.2.2.2:2"},
  1220  		{Addr: "[0002:0002:0002:0002:0002:0002:0002:0002]:8080"},
  1221  		{Addr: "3.3.3.3:3"},
  1222  		{Addr: "[fe80::1%eth0]:3333"},
  1223  		{Addr: "[::FFFF:192.168.0.1]:2222"},
  1224  	}
  1225  
  1226  	gotAddrs, err := subConnAddresses(ctx, cc, 9)
  1227  	if err != nil {
  1228  		t.Fatalf("%v", err)
  1229  	}
  1230  	if diff := cmp.Diff(wantAddrs, gotAddrs, ignoreBalAttributesOpt); diff != "" {
  1231  		t.Errorf("SubConn creation order mismatch (-want +got):\n%s", diff)
  1232  	}
  1233  }
  1234  
  1235  // Test verifies that pickfirst balancer transitions to READY when the health
  1236  // listener is enabled. Since client side health checking is not enabled in
  1237  // the service config, the health listener will send a health update for READY
  1238  // after registering the listener.
  1239  func (s) TestPickFirstLeaf_HealthListenerEnabled(t *testing.T) {
  1240  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1241  	defer cancel()
  1242  	bf := stub.BalancerFuncs{
  1243  		Init: func(bd *stub.BalancerData) {
  1244  			bd.Data = balancer.Get(pickfirstleaf.Name).Build(bd.ClientConn, bd.BuildOptions)
  1245  		},
  1246  		Close: func(bd *stub.BalancerData) {
  1247  			bd.Data.(balancer.Balancer).Close()
  1248  		},
  1249  		UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
  1250  			ccs.ResolverState = pickfirstleaf.EnableHealthListener(ccs.ResolverState)
  1251  			return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs)
  1252  		},
  1253  	}
  1254  
  1255  	stub.Register(t.Name(), bf)
  1256  	svcCfg := fmt.Sprintf(`{ "loadBalancingConfig": [{%q: {}}] }`, t.Name())
  1257  	backend := stubserver.StartTestService(t, nil)
  1258  	defer backend.Stop()
  1259  	opts := []grpc.DialOption{
  1260  		grpc.WithTransportCredentials(insecure.NewCredentials()),
  1261  		grpc.WithDefaultServiceConfig(svcCfg),
  1262  	}
  1263  	cc, err := grpc.NewClient(backend.Address, opts...)
  1264  	if err != nil {
  1265  		t.Fatalf("grpc.NewClient(%q) failed: %v", backend.Address, err)
  1266  
  1267  	}
  1268  	defer cc.Close()
  1269  
  1270  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, resolver.Address{Addr: backend.Address}); err != nil {
  1271  		t.Fatal(err)
  1272  	}
  1273  }
  1274  
  1275  // Test verifies that a health listener is not registered when pickfirst is not
  1276  // under a petiole policy.
  1277  func (s) TestPickFirstLeaf_HealthListenerNotEnabled(t *testing.T) {
  1278  	// Wrap the clientconn to intercept NewSubConn.
  1279  	// Capture the health list by wrapping the SC.
  1280  	// Wrap the picker to unwrap the SC.
  1281  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1282  	defer cancel()
  1283  	healthListenerCh := make(chan func(balancer.SubConnState))
  1284  
  1285  	bf := stub.BalancerFuncs{
  1286  		Init: func(bd *stub.BalancerData) {
  1287  			ccw := &healthListenerCapturingCCWrapper{
  1288  				ClientConn:       bd.ClientConn,
  1289  				healthListenerCh: healthListenerCh,
  1290  				subConnStateCh:   make(chan balancer.SubConnState, 5),
  1291  			}
  1292  			bd.Data = balancer.Get(pickfirstleaf.Name).Build(ccw, bd.BuildOptions)
  1293  		},
  1294  		Close: func(bd *stub.BalancerData) {
  1295  			bd.Data.(balancer.Balancer).Close()
  1296  		},
  1297  		UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
  1298  			// Functions like a non-petiole policy by not configuring the use
  1299  			// of health listeners.
  1300  			return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs)
  1301  		},
  1302  	}
  1303  
  1304  	stub.Register(t.Name(), bf)
  1305  	svcCfg := fmt.Sprintf(`{ "loadBalancingConfig": [{%q: {}}] }`, t.Name())
  1306  	backend := stubserver.StartTestService(t, nil)
  1307  	defer backend.Stop()
  1308  	opts := []grpc.DialOption{
  1309  		grpc.WithTransportCredentials(insecure.NewCredentials()),
  1310  		grpc.WithDefaultServiceConfig(svcCfg),
  1311  	}
  1312  	cc, err := grpc.NewClient(backend.Address, opts...)
  1313  	if err != nil {
  1314  		t.Fatalf("grpc.NewClient(%q) failed: %v", backend.Address, err)
  1315  
  1316  	}
  1317  	defer cc.Close()
  1318  	cc.Connect()
  1319  
  1320  	select {
  1321  	case <-healthListenerCh:
  1322  		t.Fatal("Health listener registered when not enabled.")
  1323  	case <-time.After(defaultTestShortTimeout):
  1324  	}
  1325  
  1326  	testutils.AwaitState(ctx, t, cc, connectivity.Ready)
  1327  }
  1328  
  1329  // Test mocks the updates sent to the health listener and verifies that the
  1330  // balancer correctly reports the health state once the SubConn's connectivity
  1331  // state becomes READY.
  1332  func (s) TestPickFirstLeaf_HealthUpdates(t *testing.T) {
  1333  	// Wrap the clientconn to intercept NewSubConn.
  1334  	// Capture the health list by wrapping the SC.
  1335  	// Wrap the picker to unwrap the SC.
  1336  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1337  	defer cancel()
  1338  	healthListenerCh := make(chan func(balancer.SubConnState))
  1339  	scConnectivityStateCh := make(chan balancer.SubConnState, 5)
  1340  
  1341  	bf := stub.BalancerFuncs{
  1342  		Init: func(bd *stub.BalancerData) {
  1343  			ccw := &healthListenerCapturingCCWrapper{
  1344  				ClientConn:       bd.ClientConn,
  1345  				healthListenerCh: healthListenerCh,
  1346  				subConnStateCh:   scConnectivityStateCh,
  1347  			}
  1348  			bd.Data = balancer.Get(pickfirstleaf.Name).Build(ccw, bd.BuildOptions)
  1349  		},
  1350  		Close: func(bd *stub.BalancerData) {
  1351  			bd.Data.(balancer.Balancer).Close()
  1352  		},
  1353  		UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error {
  1354  			ccs.ResolverState = pickfirstleaf.EnableHealthListener(ccs.ResolverState)
  1355  			return bd.Data.(balancer.Balancer).UpdateClientConnState(ccs)
  1356  		},
  1357  	}
  1358  
  1359  	stub.Register(t.Name(), bf)
  1360  	svcCfg := fmt.Sprintf(`{ "loadBalancingConfig": [{%q: {}}] }`, t.Name())
  1361  	backend := stubserver.StartTestService(t, nil)
  1362  	defer backend.Stop()
  1363  	opts := []grpc.DialOption{
  1364  		grpc.WithTransportCredentials(insecure.NewCredentials()),
  1365  		grpc.WithDefaultServiceConfig(svcCfg),
  1366  	}
  1367  	cc, err := grpc.NewClient(backend.Address, opts...)
  1368  	if err != nil {
  1369  		t.Fatalf("grpc.NewClient(%q) failed: %v", backend.Address, err)
  1370  
  1371  	}
  1372  	defer cc.Close()
  1373  	cc.Connect()
  1374  
  1375  	var healthListener func(balancer.SubConnState)
  1376  	select {
  1377  	case healthListener = <-healthListenerCh:
  1378  	case <-ctx.Done():
  1379  		t.Fatal("Context timed out waiting for health listener to be registered.")
  1380  	}
  1381  
  1382  	// Wait for the raw connectivity state to become READY. The LB policy should
  1383  	// wait for the health updates before transitioning the channel to READY.
  1384  	for {
  1385  		var scs balancer.SubConnState
  1386  		select {
  1387  		case scs = <-scConnectivityStateCh:
  1388  		case <-ctx.Done():
  1389  			t.Fatal("Context timed out waiting for the SubConn connectivity state to become READY.")
  1390  		}
  1391  		if scs.ConnectivityState == connectivity.Ready {
  1392  			break
  1393  		}
  1394  	}
  1395  
  1396  	shortCtx, cancel := context.WithTimeout(ctx, defaultTestShortTimeout)
  1397  	defer cancel()
  1398  	testutils.AwaitNoStateChange(shortCtx, t, cc, connectivity.Connecting)
  1399  
  1400  	// The LB policy should update the channel state based on the health state.
  1401  	healthListener(balancer.SubConnState{
  1402  		ConnectivityState: connectivity.TransientFailure,
  1403  		ConnectionError:   fmt.Errorf("test health check failure"),
  1404  	})
  1405  	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
  1406  
  1407  	healthListener(balancer.SubConnState{
  1408  		ConnectivityState: connectivity.Connecting,
  1409  		ConnectionError:   balancer.ErrNoSubConnAvailable,
  1410  	})
  1411  	testutils.AwaitState(ctx, t, cc, connectivity.Connecting)
  1412  
  1413  	healthListener(balancer.SubConnState{
  1414  		ConnectivityState: connectivity.Ready,
  1415  	})
  1416  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, resolver.Address{Addr: backend.Address}); err != nil {
  1417  		t.Fatal(err)
  1418  	}
  1419  
  1420  	// When the health check fails, the channel should transition to TF.
  1421  	healthListener(balancer.SubConnState{
  1422  		ConnectivityState: connectivity.TransientFailure,
  1423  		ConnectionError:   fmt.Errorf("test health check failure"),
  1424  	})
  1425  	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
  1426  }
  1427  
  1428  // Tests the case where an address update received by the pick_first LB policy
  1429  // differs in metadata which should be ignored by the LB policy. In this case,
  1430  // the test verifies that new connections are not created when the address
  1431  // update only changes the metadata.
  1432  func (s) TestPickFirstLeaf_AddressUpdateWithMetadata(t *testing.T) {
  1433  	dialer := testutils.NewBlockingDialer()
  1434  	dopts := []grpc.DialOption{
  1435  		grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%s":{}}]}`, pickfirstleaf.Name)),
  1436  		grpc.WithContextDialer(dialer.DialContext),
  1437  	}
  1438  	cc, r, backends := setupPickFirstLeaf(t, 2, dopts...)
  1439  
  1440  	// Add a metadata to the addresses before pushing them to the pick_first LB
  1441  	// policy through the manual resolver.
  1442  	addrs := backends.resolverAddrs()
  1443  	for i := range addrs {
  1444  		addrs[i].Metadata = &metadata.MD{
  1445  			"test-metadata-1": []string{fmt.Sprintf("%d", i)},
  1446  		}
  1447  	}
  1448  	r.UpdateState(resolver.State{Addresses: addrs})
  1449  
  1450  	// Ensure that RPCs succeed to the expected backend.
  1451  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
  1452  	defer cancel()
  1453  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
  1454  		t.Fatal(err)
  1455  	}
  1456  
  1457  	// Create holds for each backend. This will be used to verify the connection
  1458  	// is not re-established.
  1459  	holds := backends.holds(dialer)
  1460  
  1461  	// Add metadata to the addresses before pushing them to the pick_first LB
  1462  	// policy through the manual resolver. Leave the order of the addresses
  1463  	// unchanged.
  1464  	for i := range addrs {
  1465  		addrs[i].Metadata = &metadata.MD{
  1466  			"test-metadata-2": []string{fmt.Sprintf("%d", i)},
  1467  		}
  1468  	}
  1469  	r.UpdateState(resolver.State{Addresses: addrs})
  1470  
  1471  	// Ensure that no new connection is established.
  1472  	for i := range holds {
  1473  		sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
  1474  		defer sCancel()
  1475  		if holds[i].Wait(sCtx) {
  1476  			t.Fatalf("Unexpected connection attempt to backend: %s", addrs[i])
  1477  		}
  1478  	}
  1479  
  1480  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil {
  1481  		t.Fatal(err)
  1482  	}
  1483  
  1484  	// Add metadata to the addresses before pushing them to the pick_first LB
  1485  	// policy through the manual resolver. Reverse of the order of addresses.
  1486  	for i := range addrs {
  1487  		addrs[i].Metadata = &metadata.MD{
  1488  			"test-metadata-3": []string{fmt.Sprintf("%d", i)},
  1489  		}
  1490  	}
  1491  	addrs[0], addrs[1] = addrs[1], addrs[0]
  1492  	r.UpdateState(resolver.State{Addresses: addrs})
  1493  
  1494  	// Ensure that no new connection is established.
  1495  	for i := range holds {
  1496  		sCtx, sCancel := context.WithTimeout(ctx, defaultTestShortTimeout)
  1497  		defer sCancel()
  1498  		if holds[i].Wait(sCtx) {
  1499  			t.Fatalf("Unexpected connection attempt to backend: %s", addrs[i])
  1500  		}
  1501  	}
  1502  	if err := pickfirst.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil {
  1503  		t.Fatal(err)
  1504  	}
  1505  }
  1506  
  1507  // healthListenerCapturingCCWrapper is used to capture the health listener so
  1508  // that health updates can be mocked for testing.
  1509  type healthListenerCapturingCCWrapper struct {
  1510  	balancer.ClientConn
  1511  	healthListenerCh chan func(balancer.SubConnState)
  1512  	subConnStateCh   chan balancer.SubConnState
  1513  }
  1514  
  1515  func (ccw *healthListenerCapturingCCWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
  1516  	oldListener := opts.StateListener
  1517  	opts.StateListener = func(scs balancer.SubConnState) {
  1518  		ccw.subConnStateCh <- scs
  1519  		if oldListener != nil {
  1520  			oldListener(scs)
  1521  		}
  1522  	}
  1523  	sc, err := ccw.ClientConn.NewSubConn(addrs, opts)
  1524  	if err != nil {
  1525  		return nil, err
  1526  	}
  1527  	return &healthListenerCapturingSCWrapper{
  1528  		SubConn:    sc,
  1529  		listenerCh: ccw.healthListenerCh,
  1530  	}, nil
  1531  }
  1532  
  1533  func (ccw *healthListenerCapturingCCWrapper) UpdateState(state balancer.State) {
  1534  	state.Picker = &unwrappingPicker{state.Picker}
  1535  	ccw.ClientConn.UpdateState(state)
  1536  }
  1537  
  1538  type healthListenerCapturingSCWrapper struct {
  1539  	balancer.SubConn
  1540  	listenerCh chan func(balancer.SubConnState)
  1541  }
  1542  
  1543  func (scw *healthListenerCapturingSCWrapper) RegisterHealthListener(listener func(balancer.SubConnState)) {
  1544  	scw.listenerCh <- listener
  1545  }
  1546  
  1547  // unwrappingPicker unwraps SubConns because the channel expects SubConns to be
  1548  // addrConns.
  1549  type unwrappingPicker struct {
  1550  	balancer.Picker
  1551  }
  1552  
  1553  func (pw *unwrappingPicker) Pick(info balancer.PickInfo) (balancer.PickResult, error) {
  1554  	pr, err := pw.Picker.Pick(info)
  1555  	if pr.SubConn != nil {
  1556  		pr.SubConn = pr.SubConn.(*healthListenerCapturingSCWrapper).SubConn
  1557  	}
  1558  	return pr, err
  1559  }
  1560  
  1561  // subConnAddresses makes the pickfirst balancer create the requested number of
  1562  // SubConns by triggering transient failures. The function returns the
  1563  // addresses of the created SubConns.
  1564  func subConnAddresses(ctx context.Context, cc *testutils.BalancerClientConn, subConnCount int) ([]resolver.Address, error) {
  1565  	addresses := []resolver.Address{}
  1566  	for i := 0; i < subConnCount; i++ {
  1567  		select {
  1568  		case <-ctx.Done():
  1569  			return nil, fmt.Errorf("test timed out after creating %d subchannels, want %d", i, subConnCount)
  1570  		case sc := <-cc.NewSubConnCh:
  1571  			if len(sc.Addresses) != 1 {
  1572  				return nil, fmt.Errorf("new subchannel created with %d addresses, want 1", len(sc.Addresses))
  1573  			}
  1574  			addresses = append(addresses, sc.Addresses[0])
  1575  			sc.UpdateState(balancer.SubConnState{ConnectivityState: connectivity.Connecting})
  1576  			sc.UpdateState(balancer.SubConnState{
  1577  				ConnectivityState: connectivity.TransientFailure,
  1578  			})
  1579  		}
  1580  	}
  1581  	return addresses, nil
  1582  }
  1583  
  1584  // stateStoringBalancer stores the state of the SubConns being created.
  1585  type stateStoringBalancer struct {
  1586  	balancer.Balancer
  1587  	mu       sync.Mutex
  1588  	scStates []*scState
  1589  }
  1590  
  1591  func (b *stateStoringBalancer) Close() {
  1592  	b.Balancer.Close()
  1593  }
  1594  
  1595  func (b *stateStoringBalancer) ExitIdle() {
  1596  	if ib, ok := b.Balancer.(balancer.ExitIdler); ok {
  1597  		ib.ExitIdle()
  1598  	}
  1599  }
  1600  
  1601  type stateStoringBalancerBuilder struct {
  1602  	balancer chan *stateStoringBalancer
  1603  }
  1604  
  1605  func (b *stateStoringBalancerBuilder) Name() string {
  1606  	return stateStoringBalancerName
  1607  }
  1608  
  1609  func (b *stateStoringBalancerBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
  1610  	bal := &stateStoringBalancer{}
  1611  	bal.Balancer = balancer.Get(pickfirstleaf.Name).Build(&stateStoringCCWrapper{cc, bal}, opts)
  1612  	b.balancer <- bal
  1613  	return bal
  1614  }
  1615  
  1616  func (b *stateStoringBalancer) subConnStates() []scState {
  1617  	b.mu.Lock()
  1618  	defer b.mu.Unlock()
  1619  	ret := []scState{}
  1620  	for _, s := range b.scStates {
  1621  		ret = append(ret, *s)
  1622  	}
  1623  	return ret
  1624  }
  1625  
  1626  func (b *stateStoringBalancer) addSCState(state *scState) {
  1627  	b.mu.Lock()
  1628  	b.scStates = append(b.scStates, state)
  1629  	b.mu.Unlock()
  1630  }
  1631  
  1632  type stateStoringCCWrapper struct {
  1633  	balancer.ClientConn
  1634  	b *stateStoringBalancer
  1635  }
  1636  
  1637  func (ccw *stateStoringCCWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
  1638  	oldListener := opts.StateListener
  1639  	scs := &scState{
  1640  		State: connectivity.Idle,
  1641  		Addrs: addrs,
  1642  	}
  1643  	ccw.b.addSCState(scs)
  1644  	opts.StateListener = func(s balancer.SubConnState) {
  1645  		ccw.b.mu.Lock()
  1646  		scs.State = s.ConnectivityState
  1647  		ccw.b.mu.Unlock()
  1648  		oldListener(s)
  1649  	}
  1650  	return ccw.ClientConn.NewSubConn(addrs, opts)
  1651  }
  1652  
  1653  type scState struct {
  1654  	State connectivity.State
  1655  	Addrs []resolver.Address
  1656  }
  1657  
  1658  type backendManager struct {
  1659  	backends []*testServer
  1660  }
  1661  
  1662  func (b *backendManager) stopAllExcept(index int) {
  1663  	for idx, b := range b.backends {
  1664  		if idx != index {
  1665  			b.stop()
  1666  		}
  1667  	}
  1668  }
  1669  
  1670  // resolverAddrs  returns a list of resolver addresses for the stub server
  1671  // backends. Useful when pushing addresses to the manual resolver.
  1672  func (b *backendManager) resolverAddrs() []resolver.Address {
  1673  	addrs := make([]resolver.Address, len(b.backends))
  1674  	for i, backend := range b.backends {
  1675  		addrs[i] = resolver.Address{Addr: backend.Address}
  1676  	}
  1677  	return addrs
  1678  }
  1679  
  1680  func (b *backendManager) holds(dialer *testutils.BlockingDialer) []*testutils.Hold {
  1681  	holds := []*testutils.Hold{}
  1682  	for _, addr := range b.resolverAddrs() {
  1683  		holds = append(holds, dialer.Hold(addr.Addr))
  1684  	}
  1685  	return holds
  1686  }
  1687  
  1688  type ccStateSubscriber struct {
  1689  	mu     sync.Mutex
  1690  	states []connectivity.State
  1691  }
  1692  
  1693  // transitions returns all the states that ccStateSubscriber recorded.
  1694  // Without this a race condition occurs when the test compares the states
  1695  // and the subscriber at the same time receives a connectivity.Shutdown.
  1696  func (c *ccStateSubscriber) transitions() []connectivity.State {
  1697  	c.mu.Lock()
  1698  	defer c.mu.Unlock()
  1699  	return c.states
  1700  }
  1701  
  1702  func (c *ccStateSubscriber) OnMessage(msg any) {
  1703  	c.mu.Lock()
  1704  	defer c.mu.Unlock()
  1705  	c.states = append(c.states, msg.(connectivity.State))
  1706  }
  1707  
  1708  // mockTimer returns a fake timeAfterFunc that will not trigger automatically.
  1709  // It returns a function that can be called to manually trigger the execution
  1710  // of the scheduled callback.
  1711  func mockTimer() (triggerFunc func(), timerFunc func(_ time.Duration, f func()) func()) {
  1712  	timerCh := make(chan struct{})
  1713  	triggerFunc = func() {
  1714  		timerCh <- struct{}{}
  1715  	}
  1716  	return triggerFunc, func(_ time.Duration, f func()) func() {
  1717  		stopCh := make(chan struct{})
  1718  		go func() {
  1719  			select {
  1720  			case <-timerCh:
  1721  				f()
  1722  			case <-stopCh:
  1723  			}
  1724  		}()
  1725  		return sync.OnceFunc(func() {
  1726  			close(stopCh)
  1727  		})
  1728  	}
  1729  }