google.golang.org/grpc@v1.72.2/balancer/leastrequest/leastrequest_test.go (about)

     1  /*
     2   *
     3   * Copyright 2023 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 leastrequest
    19  
    20  import (
    21  	"context"
    22  	"encoding/json"
    23  	"fmt"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/google/go-cmp/cmp"
    30  	"google.golang.org/grpc"
    31  	"google.golang.org/grpc/connectivity"
    32  	"google.golang.org/grpc/credentials/insecure"
    33  	"google.golang.org/grpc/internal"
    34  	"google.golang.org/grpc/internal/grpctest"
    35  	"google.golang.org/grpc/internal/stubserver"
    36  	"google.golang.org/grpc/internal/testutils"
    37  	testgrpc "google.golang.org/grpc/interop/grpc_testing"
    38  	testpb "google.golang.org/grpc/interop/grpc_testing"
    39  	"google.golang.org/grpc/peer"
    40  	"google.golang.org/grpc/resolver"
    41  	"google.golang.org/grpc/resolver/manual"
    42  	"google.golang.org/grpc/serviceconfig"
    43  )
    44  
    45  const (
    46  	defaultTestTimeout      = 5 * time.Second
    47  	defaultTestShortTimeout = 10 * time.Millisecond
    48  )
    49  
    50  type s struct {
    51  	grpctest.Tester
    52  }
    53  
    54  func Test(t *testing.T) {
    55  	grpctest.RunSubTests(t, s{})
    56  }
    57  
    58  func (s) TestParseConfig(t *testing.T) {
    59  	parser := bb{}
    60  	tests := []struct {
    61  		name    string
    62  		input   string
    63  		wantCfg serviceconfig.LoadBalancingConfig
    64  		wantErr string
    65  	}{
    66  		{
    67  			name:  "happy-case-default",
    68  			input: `{}`,
    69  			wantCfg: &LBConfig{
    70  				ChoiceCount: 2,
    71  			},
    72  		},
    73  		{
    74  			name:  "happy-case-choice-count-set",
    75  			input: `{"choiceCount": 3}`,
    76  			wantCfg: &LBConfig{
    77  				ChoiceCount: 3,
    78  			},
    79  		},
    80  		{
    81  			name:  "happy-case-choice-count-greater-than-ten",
    82  			input: `{"choiceCount": 11}`,
    83  			wantCfg: &LBConfig{
    84  				ChoiceCount: 10,
    85  			},
    86  		},
    87  		{
    88  			name:    "choice-count-less-than-2",
    89  			input:   `{"choiceCount": 1}`,
    90  			wantErr: "must be >= 2",
    91  		},
    92  		{
    93  			name:    "invalid-json",
    94  			input:   "{{invalidjson{{",
    95  			wantErr: "invalid character",
    96  		},
    97  	}
    98  	for _, test := range tests {
    99  		t.Run(test.name, func(t *testing.T) {
   100  			gotCfg, gotErr := parser.ParseConfig(json.RawMessage(test.input))
   101  			// Substring match makes this very tightly coupled to the
   102  			// internalserviceconfig.BalancerConfig error strings. However, it
   103  			// is important to distinguish the different types of error messages
   104  			// possible as the parser has a few defined buckets of ways it can
   105  			// error out.
   106  			if (gotErr != nil) != (test.wantErr != "") {
   107  				t.Fatalf("ParseConfig(%v) = %v, wantErr %v", test.input, gotErr, test.wantErr)
   108  			}
   109  			if gotErr != nil && !strings.Contains(gotErr.Error(), test.wantErr) {
   110  				t.Fatalf("ParseConfig(%v) = %v, wantErr %v", test.input, gotErr, test.wantErr)
   111  			}
   112  			if test.wantErr != "" {
   113  				return
   114  			}
   115  			if diff := cmp.Diff(gotCfg, test.wantCfg); diff != "" {
   116  				t.Fatalf("ParseConfig(%v) got unexpected output, diff (-got +want): %v", test.input, diff)
   117  			}
   118  		})
   119  	}
   120  }
   121  
   122  func startBackends(t *testing.T, numBackends int) []*stubserver.StubServer {
   123  	backends := make([]*stubserver.StubServer, 0, numBackends)
   124  	// Construct and start working backends.
   125  	for i := 0; i < numBackends; i++ {
   126  		backend := &stubserver.StubServer{
   127  			EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) {
   128  				return &testpb.Empty{}, nil
   129  			},
   130  			FullDuplexCallF: func(stream testgrpc.TestService_FullDuplexCallServer) error {
   131  				<-stream.Context().Done()
   132  				return nil
   133  			},
   134  		}
   135  		if err := backend.StartServer(); err != nil {
   136  			t.Fatalf("Failed to start backend: %v", err)
   137  		}
   138  		t.Logf("Started good TestService backend at: %q", backend.Address)
   139  		t.Cleanup(func() { backend.Stop() })
   140  		backends = append(backends, backend)
   141  	}
   142  	return backends
   143  }
   144  
   145  // setupBackends spins up three test backends, each listening on a port on
   146  // localhost. The three backends always reply with an empty response with no
   147  // error, and for streaming receive until hitting an EOF error.
   148  func setupBackends(t *testing.T, numBackends int) []string {
   149  	t.Helper()
   150  	addresses := make([]string, numBackends)
   151  	backends := startBackends(t, numBackends)
   152  	// Construct and start working backends.
   153  	for i := 0; i < numBackends; i++ {
   154  		addresses[i] = backends[i].Address
   155  	}
   156  	return addresses
   157  }
   158  
   159  // checkRoundRobinRPCs verifies that EmptyCall RPCs on the given ClientConn,
   160  // connected to a server exposing the test.grpc_testing.TestService, are
   161  // roundrobined across the given backend addresses.
   162  //
   163  // Returns a non-nil error if context deadline expires before RPCs start to get
   164  // roundrobined across the given backends.
   165  func checkRoundRobinRPCs(ctx context.Context, client testgrpc.TestServiceClient, addrs []resolver.Address) error {
   166  	wantAddrCount := make(map[string]int)
   167  	for _, addr := range addrs {
   168  		wantAddrCount[addr.Addr]++
   169  	}
   170  	gotAddrCount := make(map[string]int)
   171  	for ; ctx.Err() == nil; <-time.After(time.Millisecond) {
   172  		gotAddrCount = make(map[string]int)
   173  		// Perform 3 iterations.
   174  		var iterations [][]string
   175  		for i := 0; i < 3; i++ {
   176  			iteration := make([]string, len(addrs))
   177  			for c := 0; c < len(addrs); c++ {
   178  				var peer peer.Peer
   179  				client.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer))
   180  				iteration[c] = peer.Addr.String()
   181  			}
   182  			iterations = append(iterations, iteration)
   183  		}
   184  		// Ensure the first iteration contains all addresses in addrs.
   185  		for _, addr := range iterations[0] {
   186  			gotAddrCount[addr]++
   187  		}
   188  		if !cmp.Equal(gotAddrCount, wantAddrCount) {
   189  			continue
   190  		}
   191  		// Ensure all three iterations contain the same addresses.
   192  		if !cmp.Equal(iterations[0], iterations[1]) || !cmp.Equal(iterations[0], iterations[2]) {
   193  			continue
   194  		}
   195  		return nil
   196  	}
   197  	return fmt.Errorf("timeout when waiting for roundrobin distribution of RPCs across addresses: %v; got: %v", addrs, gotAddrCount)
   198  }
   199  
   200  // TestLeastRequestE2E tests the Least Request LB policy in an e2e style. The
   201  // Least Request balancer is configured as the top level balancer of the
   202  // channel, and is passed three addresses. Eventually, the test creates three
   203  // streams, which should be on certain backends according to the least request
   204  // algorithm. The randomness in the picker is injected in the test to be
   205  // deterministic, allowing the test to make assertions on the distribution.
   206  func (s) TestLeastRequestE2E(t *testing.T) {
   207  	defer func(u func() uint32) {
   208  		randuint32 = u
   209  	}(randuint32)
   210  	var index int
   211  	indexes := []uint32{
   212  		0, 0, 1, 1, 2, 2, // Triggers a round robin distribution.
   213  	}
   214  	randuint32 = func() uint32 {
   215  		ret := indexes[index%len(indexes)]
   216  		index++
   217  		return ret
   218  	}
   219  	addresses := setupBackends(t, 3)
   220  
   221  	mr := manual.NewBuilderWithScheme("lr-e2e")
   222  	defer mr.Close()
   223  
   224  	// Configure least request as top level balancer of channel.
   225  	lrscJSON := `
   226  {
   227    "loadBalancingConfig": [
   228      {
   229        "least_request_experimental": {
   230          "choiceCount": 2
   231        }
   232      }
   233    ]
   234  }`
   235  	sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   236  	firstThreeAddresses := []resolver.Address{
   237  		{Addr: addresses[0]},
   238  		{Addr: addresses[1]},
   239  		{Addr: addresses[2]},
   240  	}
   241  	mr.InitialState(resolver.State{
   242  		Addresses:     firstThreeAddresses,
   243  		ServiceConfig: sc,
   244  	})
   245  
   246  	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
   247  	if err != nil {
   248  		t.Fatalf("grpc.NewClient() failed: %v", err)
   249  	}
   250  	defer cc.Close()
   251  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   252  	defer cancel()
   253  	testServiceClient := testgrpc.NewTestServiceClient(cc)
   254  
   255  	// Wait for all 3 backends to round robin across. The happens because a
   256  	// SubConn transitioning into READY causes a new picker update. Once the
   257  	// picker update with all 3 backends is present, this test can start to make
   258  	// assertions based on those backends.
   259  	if err := checkRoundRobinRPCs(ctx, testServiceClient, firstThreeAddresses); err != nil {
   260  		t.Fatalf("error in expected round robin: %v", err)
   261  	}
   262  
   263  	// Map ordering of READY SubConns is non deterministic. Thus, perform 3 RPCs
   264  	// mocked from the random to each index to learn the addresses of SubConns
   265  	// at each index.
   266  	index = 0
   267  	peerAtIndex := make([]string, 3)
   268  	var peer0 peer.Peer
   269  	if _, err := testServiceClient.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer0)); err != nil {
   270  		t.Fatalf("testServiceClient.EmptyCall failed: %v", err)
   271  	}
   272  	peerAtIndex[0] = peer0.Addr.String()
   273  	if _, err := testServiceClient.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer0)); err != nil {
   274  		t.Fatalf("testServiceClient.EmptyCall failed: %v", err)
   275  	}
   276  	peerAtIndex[1] = peer0.Addr.String()
   277  	if _, err := testServiceClient.EmptyCall(ctx, &testpb.Empty{}, grpc.Peer(&peer0)); err != nil {
   278  		t.Fatalf("testServiceClient.EmptyCall failed: %v", err)
   279  	}
   280  	peerAtIndex[2] = peer0.Addr.String()
   281  
   282  	// Start streaming RPCs, but do not finish them. Each subsequent stream
   283  	// should be started according to the least request algorithm, and chosen
   284  	// between the indexes provided.
   285  	index = 0
   286  	indexes = []uint32{
   287  		0, 0, // Causes first stream to be on first address.
   288  		0, 1, // Compares first address (one RPC) to second (no RPCs), so choose second.
   289  		1, 2, // Compares second address (one RPC) to third (no RPCs), so choose third.
   290  		0, 3, // Causes another stream on first address.
   291  		1, 0, // Compares second address (one RPC) to first (two RPCs), so choose second.
   292  		2, 0, // Compares third address (one RPC) to first (two RPCs), so choose third.
   293  		0, 0, // Causes another stream on first address.
   294  		2, 2, // Causes a stream on third address.
   295  		2, 1, // Compares third address (three RPCs) to second (two RPCs), so choose third.
   296  	}
   297  	wantIndex := []uint32{0, 1, 2, 0, 1, 2, 0, 2, 1}
   298  
   299  	// Start streaming RPC's, but do not finish them. Each created stream should
   300  	// be started based on the least request algorithm and injected randomness
   301  	// (see indexes slice above for exact expectations).
   302  	for _, wantIndex := range wantIndex {
   303  		stream, err := testServiceClient.FullDuplexCall(ctx)
   304  		if err != nil {
   305  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   306  		}
   307  		p, ok := peer.FromContext(stream.Context())
   308  		if !ok {
   309  			t.Fatalf("testServiceClient.FullDuplexCall has no Peer")
   310  		}
   311  		if p.Addr.String() != peerAtIndex[wantIndex] {
   312  			t.Fatalf("testServiceClient.FullDuplexCall's Peer got: %v, want: %v", p.Addr.String(), peerAtIndex[wantIndex])
   313  		}
   314  	}
   315  }
   316  
   317  // TestLeastRequestPersistsCounts tests that the Least Request Balancer persists
   318  // counts once it gets a new picker update. It first updates the Least Request
   319  // Balancer with two backends, and creates a bunch of streams on them. Then, it
   320  // updates the Least Request Balancer with three backends, including the two
   321  // previous. Any created streams should then be started on the new backend.
   322  func (s) TestLeastRequestPersistsCounts(t *testing.T) {
   323  	defer func(u func() uint32) {
   324  		randuint32 = u
   325  	}(randuint32)
   326  	var index int
   327  	indexes := []uint32{
   328  		0, 0, 1, 1,
   329  	}
   330  	randuint32 = func() uint32 {
   331  		ret := indexes[index%len(indexes)]
   332  		index++
   333  		return ret
   334  	}
   335  	addresses := setupBackends(t, 3)
   336  
   337  	mr := manual.NewBuilderWithScheme("lr-e2e")
   338  	defer mr.Close()
   339  
   340  	// Configure least request as top level balancer of channel.
   341  	lrscJSON := `
   342  {
   343    "loadBalancingConfig": [
   344      {
   345        "least_request_experimental": {
   346          "choiceCount": 2
   347        }
   348      }
   349    ]
   350  }`
   351  	sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   352  	firstTwoAddresses := []resolver.Address{
   353  		{Addr: addresses[0]},
   354  		{Addr: addresses[1]},
   355  	}
   356  	mr.InitialState(resolver.State{
   357  		Addresses:     firstTwoAddresses,
   358  		ServiceConfig: sc,
   359  	})
   360  
   361  	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
   362  	if err != nil {
   363  		t.Fatalf("grpc.NewClient() failed: %v", err)
   364  	}
   365  	defer cc.Close()
   366  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   367  	defer cancel()
   368  	testServiceClient := testgrpc.NewTestServiceClient(cc)
   369  
   370  	// Wait for the two backends to round robin across. The happens because a
   371  	// SubConn transitioning into READY causes a new picker update. Once the
   372  	// picker update with the two backends is present, this test can start to
   373  	// populate those backends with streams.
   374  	if err := checkRoundRobinRPCs(ctx, testServiceClient, firstTwoAddresses); err != nil {
   375  		t.Fatalf("error in expected round robin: %v", err)
   376  	}
   377  
   378  	// Start 50 streaming RPCs, and leave them unfinished for the duration of
   379  	// the test. This will populate the first two addresses with many active
   380  	// RPCs.
   381  	for i := 0; i < 50; i++ {
   382  		_, err := testServiceClient.FullDuplexCall(ctx)
   383  		if err != nil {
   384  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   385  		}
   386  	}
   387  
   388  	// Update the least request balancer to choice count 3. Also update the
   389  	// address list adding a third address. Alongside the injected randomness,
   390  	// this should trigger the least request balancer to search all created
   391  	// SubConns. Thus, since address 3 is the new address and the first two
   392  	// addresses are populated with RPCs, once the picker update of all 3 READY
   393  	// SubConns takes effect, all new streams should be started on address 3.
   394  	index = 0
   395  	indexes = []uint32{
   396  		0, 1, 2, 3, 4, 5,
   397  	}
   398  	lrscJSON = `
   399  {
   400    "loadBalancingConfig": [
   401      {
   402        "least_request_experimental": {
   403          "choiceCount": 3
   404        }
   405      }
   406    ]
   407  }`
   408  	sc = internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   409  	fullAddresses := []resolver.Address{
   410  		{Addr: addresses[0]},
   411  		{Addr: addresses[1]},
   412  		{Addr: addresses[2]},
   413  	}
   414  	mr.UpdateState(resolver.State{
   415  		Addresses:     fullAddresses,
   416  		ServiceConfig: sc,
   417  	})
   418  	newAddress := fullAddresses[2]
   419  	// Poll for only address 3 to show up. This requires a polling loop because
   420  	// picker update with all three SubConns doesn't take into effect
   421  	// immediately, needs the third SubConn to become READY.
   422  	if err := checkRoundRobinRPCs(ctx, testServiceClient, []resolver.Address{newAddress}); err != nil {
   423  		t.Fatalf("error in expected round robin: %v", err)
   424  	}
   425  
   426  	// Start 25 rpcs, but don't finish them. They should all start on address 3,
   427  	// since the first two addresses both have 25 RPCs (and randomness
   428  	// injection/choiceCount causes all 3 to be compared every iteration).
   429  	for i := 0; i < 25; i++ {
   430  		stream, err := testServiceClient.FullDuplexCall(ctx)
   431  		if err != nil {
   432  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   433  		}
   434  		p, ok := peer.FromContext(stream.Context())
   435  		if !ok {
   436  			t.Fatalf("testServiceClient.FullDuplexCall has no Peer")
   437  		}
   438  		if p.Addr.String() != addresses[2] {
   439  			t.Fatalf("testServiceClient.FullDuplexCall's Peer got: %v, want: %v", p.Addr.String(), addresses[2])
   440  		}
   441  	}
   442  
   443  	// Now 25 RPC's are active on each address, the next three RPC's should
   444  	// round robin, since choiceCount is three and the injected random indexes
   445  	// cause it to search all three addresses for fewest outstanding requests on
   446  	// each iteration.
   447  	wantAddrCount := map[string]int{
   448  		addresses[0]: 1,
   449  		addresses[1]: 1,
   450  		addresses[2]: 1,
   451  	}
   452  	gotAddrCount := make(map[string]int)
   453  	for i := 0; i < len(addresses); i++ {
   454  		stream, err := testServiceClient.FullDuplexCall(ctx)
   455  		if err != nil {
   456  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   457  		}
   458  		p, ok := peer.FromContext(stream.Context())
   459  		if !ok {
   460  			t.Fatalf("testServiceClient.FullDuplexCall has no Peer")
   461  		}
   462  		if p.Addr != nil {
   463  			gotAddrCount[p.Addr.String()]++
   464  		}
   465  	}
   466  	if diff := cmp.Diff(gotAddrCount, wantAddrCount); diff != "" {
   467  		t.Fatalf("addr count (-got:, +want): %v", diff)
   468  	}
   469  }
   470  
   471  // TestConcurrentRPCs tests concurrent RPCs on the least request balancer. It
   472  // configures a channel with a least request balancer as the top level balancer,
   473  // and makes 100 RPCs asynchronously. This makes sure no race conditions happen
   474  // in this scenario.
   475  func (s) TestConcurrentRPCs(t *testing.T) {
   476  	addresses := setupBackends(t, 3)
   477  
   478  	mr := manual.NewBuilderWithScheme("lr-e2e")
   479  	defer mr.Close()
   480  
   481  	// Configure least request as top level balancer of channel.
   482  	lrscJSON := `
   483  {
   484    "loadBalancingConfig": [
   485      {
   486        "least_request_experimental": {
   487          "choiceCount": 2
   488        }
   489      }
   490    ]
   491  }`
   492  	sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   493  	firstTwoAddresses := []resolver.Address{
   494  		{Addr: addresses[0]},
   495  		{Addr: addresses[1]},
   496  	}
   497  	mr.InitialState(resolver.State{
   498  		Addresses:     firstTwoAddresses,
   499  		ServiceConfig: sc,
   500  	})
   501  
   502  	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
   503  	if err != nil {
   504  		t.Fatalf("grpc.NewClient() failed: %v", err)
   505  	}
   506  	defer cc.Close()
   507  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   508  	defer cancel()
   509  	testServiceClient := testgrpc.NewTestServiceClient(cc)
   510  
   511  	var wg sync.WaitGroup
   512  	for i := 0; i < 100; i++ {
   513  		wg.Add(1)
   514  		go func() {
   515  			defer wg.Done()
   516  			for j := 0; j < 5; j++ {
   517  				testServiceClient.EmptyCall(ctx, &testpb.Empty{})
   518  			}
   519  		}()
   520  	}
   521  	wg.Wait()
   522  }
   523  
   524  // Test tests that the least request balancer persists RPC counts once it gets
   525  // new picker updates and backends within an endpoint go down. It first updates
   526  // the balancer with two endpoints having two addresses each. It verifies the
   527  // requests are round robined across the first address of each endpoint. It then
   528  // stops the active backend in endpoint[0]. It verified that the balancer starts
   529  // using the second address in endpoint[0]. The test then creates a bunch of
   530  // streams on two endpoints. Then, it updates the balancer with three endpoints,
   531  // including the two previous. Any created streams should then be started on the
   532  // new endpoint. The test shuts down the active backed in endpoint[1] and
   533  // endpoint[2]. The test verifies that new RPCs are round robined across the
   534  // active backends in endpoint[1] and endpoint[2].
   535  func (s) TestLeastRequestEndpoints_MultipleAddresses(t *testing.T) {
   536  	defer func(u func() uint32) {
   537  		randuint32 = u
   538  	}(randuint32)
   539  	var index int
   540  	indexes := []uint32{
   541  		0, 0, 1, 1,
   542  	}
   543  	randuint32 = func() uint32 {
   544  		ret := indexes[index%len(indexes)]
   545  		index++
   546  		return ret
   547  	}
   548  	backends := startBackends(t, 6)
   549  	mr := manual.NewBuilderWithScheme("lr-e2e")
   550  	defer mr.Close()
   551  
   552  	// Configure least request as top level balancer of channel.
   553  	lrscJSON := `
   554  {
   555    "loadBalancingConfig": [
   556      {
   557        "least_request_experimental": {
   558          "choiceCount": 2
   559        }
   560      }
   561    ]
   562  }`
   563  	endpoints := []resolver.Endpoint{
   564  		{Addresses: []resolver.Address{{Addr: backends[0].Address}, {Addr: backends[1].Address}}},
   565  		{Addresses: []resolver.Address{{Addr: backends[2].Address}, {Addr: backends[3].Address}}},
   566  		{Addresses: []resolver.Address{{Addr: backends[4].Address}, {Addr: backends[5].Address}}},
   567  	}
   568  	sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   569  	firstTwoEndpoints := []resolver.Endpoint{endpoints[0], endpoints[1]}
   570  	mr.InitialState(resolver.State{
   571  		Endpoints:     firstTwoEndpoints,
   572  		ServiceConfig: sc,
   573  	})
   574  
   575  	cc, err := grpc.NewClient(mr.Scheme()+":///", grpc.WithResolvers(mr), grpc.WithTransportCredentials(insecure.NewCredentials()))
   576  	if err != nil {
   577  		t.Fatalf("grpc.NewClient() failed: %v", err)
   578  	}
   579  	defer cc.Close()
   580  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   581  	defer cancel()
   582  	testServiceClient := testgrpc.NewTestServiceClient(cc)
   583  
   584  	// Wait for the two backends to round robin across. The happens because a
   585  	// child pickfirst transitioning into READY causes a new picker update. Once
   586  	// the picker update with the two backends is present, this test can start
   587  	// to populate those backends with streams.
   588  	wantAddrs := []resolver.Address{
   589  		endpoints[0].Addresses[0],
   590  		endpoints[1].Addresses[0],
   591  	}
   592  	if err := checkRoundRobinRPCs(ctx, testServiceClient, wantAddrs); err != nil {
   593  		t.Fatalf("error in expected round robin: %v", err)
   594  	}
   595  
   596  	// Shut down one of the addresses in endpoints[0], the child pickfirst
   597  	// should fallback to the next address in endpoints[0].
   598  	backends[0].Stop()
   599  	wantAddrs = []resolver.Address{
   600  		endpoints[0].Addresses[1],
   601  		endpoints[1].Addresses[0],
   602  	}
   603  	if err := checkRoundRobinRPCs(ctx, testServiceClient, wantAddrs); err != nil {
   604  		t.Fatalf("error in expected round robin: %v", err)
   605  	}
   606  
   607  	// Start 50 streaming RPCs, and leave them unfinished for the duration of
   608  	// the test. This will populate the first two endpoints with many active
   609  	// RPCs.
   610  	for i := 0; i < 50; i++ {
   611  		_, err := testServiceClient.FullDuplexCall(ctx)
   612  		if err != nil {
   613  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   614  		}
   615  	}
   616  
   617  	// Update the least request balancer to choice count 3. Also update the
   618  	// address list adding a third endpoint. Alongside the injected randomness,
   619  	// this should trigger the least request balancer to search all created
   620  	// endpoints. Thus, since endpoint 3 is the new endpoint and the first two
   621  	// endpoint are populated with RPCs, once the picker update of all 3 READY
   622  	// pickfirsts takes effect, all new streams should be started on endpoint 3.
   623  	index = 0
   624  	indexes = []uint32{
   625  		0, 1, 2, 3, 4, 5,
   626  	}
   627  	lrscJSON = `
   628  {
   629    "loadBalancingConfig": [
   630      {
   631        "least_request_experimental": {
   632          "choiceCount": 3
   633        }
   634      }
   635    ]
   636  }`
   637  	sc = internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(lrscJSON)
   638  	mr.UpdateState(resolver.State{
   639  		Endpoints:     endpoints,
   640  		ServiceConfig: sc,
   641  	})
   642  	newAddress := endpoints[2].Addresses[0]
   643  	// Poll for only endpoint 3 to show up. This requires a polling loop because
   644  	// picker update with all three endpoints doesn't take into effect
   645  	// immediately, needs the third pickfirst to become READY.
   646  	if err := checkRoundRobinRPCs(ctx, testServiceClient, []resolver.Address{newAddress}); err != nil {
   647  		t.Fatalf("error in expected round robin: %v", err)
   648  	}
   649  
   650  	// Start 25 rpcs, but don't finish them. They should all start on endpoint 3,
   651  	// since the first two endpoints both have 25 RPCs (and randomness
   652  	// injection/choiceCount causes all 3 to be compared every iteration).
   653  	for i := 0; i < 25; i++ {
   654  		stream, err := testServiceClient.FullDuplexCall(ctx)
   655  		if err != nil {
   656  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   657  		}
   658  		p, ok := peer.FromContext(stream.Context())
   659  		if !ok {
   660  			t.Fatalf("testServiceClient.FullDuplexCall has no Peer")
   661  		}
   662  		if p.Addr.String() != newAddress.Addr {
   663  			t.Fatalf("testServiceClient.FullDuplexCall's Peer got: %v, want: %v", p.Addr.String(), newAddress)
   664  		}
   665  	}
   666  
   667  	// Now 25 RPC's are active on each endpoint, the next three RPC's should
   668  	// round robin, since choiceCount is three and the injected random indexes
   669  	// cause it to search all three endpoints for fewest outstanding requests on
   670  	// each iteration.
   671  	wantAddrCount := map[string]int{
   672  		endpoints[0].Addresses[1].Addr: 1,
   673  		endpoints[1].Addresses[0].Addr: 1,
   674  		endpoints[2].Addresses[0].Addr: 1,
   675  	}
   676  	gotAddrCount := make(map[string]int)
   677  	for i := 0; i < len(endpoints); i++ {
   678  		stream, err := testServiceClient.FullDuplexCall(ctx)
   679  		if err != nil {
   680  			t.Fatalf("testServiceClient.FullDuplexCall failed: %v", err)
   681  		}
   682  		p, ok := peer.FromContext(stream.Context())
   683  		if !ok {
   684  			t.Fatalf("testServiceClient.FullDuplexCall has no Peer")
   685  		}
   686  		if p.Addr != nil {
   687  			gotAddrCount[p.Addr.String()]++
   688  		}
   689  	}
   690  	if diff := cmp.Diff(gotAddrCount, wantAddrCount); diff != "" {
   691  		t.Fatalf("addr count (-got:, +want): %v", diff)
   692  	}
   693  
   694  	// Shutdown the active address for endpoint[1] and endpoint[2]. This should
   695  	// result in their streams failing. Now the requests should roundrobin b/w
   696  	// endpoint[1] and endpoint[2].
   697  	backends[2].Stop()
   698  	backends[4].Stop()
   699  	index = 0
   700  	indexes = []uint32{
   701  		0, 1, 2, 2, 1, 0,
   702  	}
   703  	wantAddrs = []resolver.Address{
   704  		endpoints[1].Addresses[1],
   705  		endpoints[2].Addresses[1],
   706  	}
   707  	if err := checkRoundRobinRPCs(ctx, testServiceClient, wantAddrs); err != nil {
   708  		t.Fatalf("error in expected round robin: %v", err)
   709  	}
   710  }
   711  
   712  // Test tests that the least request balancer properly surfaces resolver
   713  // errors.
   714  func (s) TestLeastRequestEndpoints_ResolverError(t *testing.T) {
   715  	const sc = `{"loadBalancingConfig": [{"least_request_experimental": {}}]}`
   716  	mr := manual.NewBuilderWithScheme("lr-e2e")
   717  	defer mr.Close()
   718  
   719  	cc, err := grpc.NewClient(
   720  		mr.Scheme()+":///",
   721  		grpc.WithResolvers(mr),
   722  		grpc.WithTransportCredentials(insecure.NewCredentials()),
   723  		grpc.WithDefaultServiceConfig(sc),
   724  	)
   725  	if err != nil {
   726  		t.Fatalf("grpc.NewClient() failed: %v", err)
   727  	}
   728  	defer cc.Close()
   729  
   730  	// We need to pass an endpoint with a valid address to the resolver before
   731  	// reporting an error - otherwise endpointsharding does not report the
   732  	// error through.
   733  	lis, err := testutils.LocalTCPListener()
   734  	if err != nil {
   735  		t.Fatalf("net.Listen() failed: %v", err)
   736  	}
   737  	// Act like a server that closes the connection without sending a server
   738  	// preface.
   739  	go func() {
   740  		conn, err := lis.Accept()
   741  		if err != nil {
   742  			t.Errorf("Unexpected error when accepting a connection: %v", err)
   743  		}
   744  		conn.Close()
   745  	}()
   746  	mr.UpdateState(resolver.State{
   747  		Endpoints: []resolver.Endpoint{{Addresses: []resolver.Address{{Addr: lis.Addr().String()}}}},
   748  	})
   749  	cc.Connect()
   750  
   751  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   752  	defer cancel()
   753  	testutils.AwaitState(ctx, t, cc, connectivity.TransientFailure)
   754  
   755  	// Report an error through the resolver
   756  	resolverErr := fmt.Errorf("simulated resolver error")
   757  	mr.CC().ReportError(resolverErr)
   758  
   759  	// Ensure the client returns the expected resolver error.
   760  	testServiceClient := testgrpc.NewTestServiceClient(cc)
   761  	for ; ctx.Err() == nil; <-time.After(defaultTestShortTimeout) {
   762  		_, err = testServiceClient.EmptyCall(ctx, &testpb.Empty{})
   763  		if strings.Contains(err.Error(), resolverErr.Error()) {
   764  			break
   765  		}
   766  	}
   767  	if ctx.Err() != nil {
   768  		t.Fatalf("Timeout when waiting for RPCs to fail with error containing %s. Last error: %v", resolverErr, err)
   769  	}
   770  }