google.golang.org/grpc@v1.72.2/test/balancer_switching_test.go (about) 1 /* 2 * 3 * Copyright 2022 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package test 20 21 import ( 22 "context" 23 "fmt" 24 "testing" 25 26 "google.golang.org/grpc" 27 "google.golang.org/grpc/balancer" 28 grpclbstate "google.golang.org/grpc/balancer/grpclb/state" 29 "google.golang.org/grpc/balancer/pickfirst" 30 "google.golang.org/grpc/credentials/insecure" 31 "google.golang.org/grpc/internal" 32 "google.golang.org/grpc/internal/balancer/stub" 33 "google.golang.org/grpc/internal/stubserver" 34 "google.golang.org/grpc/internal/testutils/fakegrpclb" 35 pfutil "google.golang.org/grpc/internal/testutils/pickfirst" 36 rrutil "google.golang.org/grpc/internal/testutils/roundrobin" 37 "google.golang.org/grpc/resolver" 38 "google.golang.org/grpc/resolver/manual" 39 40 testgrpc "google.golang.org/grpc/interop/grpc_testing" 41 testpb "google.golang.org/grpc/interop/grpc_testing" 42 ) 43 44 const ( 45 loadBalancedServiceName = "foo.bar.service" 46 loadBalancedServicePort = 443 47 wantGRPCLBTraceDesc = `Channel switches to new LB policy "grpclb"` 48 wantRoundRobinTraceDesc = `Channel switches to new LB policy "round_robin"` 49 pickFirstServiceConfig = `{"loadBalancingConfig": [{"pick_first":{}}]}` 50 grpclbServiceConfig = `{"loadBalancingConfig": [{"grpclb":{}}]}` 51 52 // This is the number of stub backends set up at the start of each test. The 53 // first backend is used for the "grpclb" policy and the rest are used for 54 // other LB policies to test balancer switching. 55 backendCount = 3 56 ) 57 58 // stubBackendsToResolverAddrs converts from a set of stub server backends to 59 // resolver addresses. Useful when pushing addresses to the manual resolver. 60 func stubBackendsToResolverAddrs(backends []*stubserver.StubServer) []resolver.Address { 61 addrs := make([]resolver.Address, len(backends)) 62 for i, backend := range backends { 63 addrs[i] = resolver.Address{Addr: backend.Address} 64 } 65 return addrs 66 } 67 68 // setupBackendsAndFakeGRPCLB sets up backendCount number of stub server 69 // backends and a fake grpclb server for tests which exercise balancer switch 70 // scenarios involving grpclb. 71 // 72 // The fake grpclb server always returns the first of the configured stub 73 // backends as backend addresses. So, the tests are free to use the other 74 // backends with other LB policies to verify balancer switching scenarios. 75 // 76 // Returns a cleanup function to be invoked by the caller. 77 func setupBackendsAndFakeGRPCLB(t *testing.T) ([]*stubserver.StubServer, *fakegrpclb.Server, func()) { 78 backends, backendsCleanup := startBackendsForBalancerSwitch(t) 79 80 lbServer, err := fakegrpclb.NewServer(fakegrpclb.ServerParams{ 81 LoadBalancedServiceName: loadBalancedServiceName, 82 LoadBalancedServicePort: loadBalancedServicePort, 83 BackendAddresses: []string{backends[0].Address}, 84 }) 85 if err != nil { 86 t.Fatalf("failed to create fake grpclb server: %v", err) 87 } 88 go func() { 89 if err := lbServer.Serve(); err != nil { 90 t.Errorf("fake grpclb Serve() failed: %v", err) 91 } 92 }() 93 94 return backends, lbServer, func() { 95 backendsCleanup() 96 lbServer.Stop() 97 } 98 } 99 100 // startBackendsForBalancerSwitch spins up a bunch of stub server backends 101 // exposing the TestService. Returns a cleanup function to be invoked by the 102 // caller. 103 func startBackendsForBalancerSwitch(t *testing.T) ([]*stubserver.StubServer, func()) { 104 t.Helper() 105 106 backends := make([]*stubserver.StubServer, backendCount) 107 for i := 0; i < backendCount; i++ { 108 backend := &stubserver.StubServer{ 109 EmptyCallF: func(context.Context, *testpb.Empty) (*testpb.Empty, error) { return &testpb.Empty{}, nil }, 110 } 111 if err := backend.StartServer(); err != nil { 112 t.Fatalf("Failed to start backend: %v", err) 113 } 114 t.Logf("Started TestService backend at: %q", backend.Address) 115 backends[i] = backend 116 } 117 return backends, func() { 118 for _, b := range backends { 119 b.Stop() 120 } 121 } 122 } 123 124 // TestBalancerSwitch_Basic tests the basic scenario of switching from one LB 125 // policy to another, as specified in the service config. 126 func (s) TestBalancerSwitch_Basic(t *testing.T) { 127 backends, cleanup := startBackendsForBalancerSwitch(t) 128 defer cleanup() 129 addrs := stubBackendsToResolverAddrs(backends) 130 131 r := manual.NewBuilderWithScheme("whatever") 132 133 r.InitialState(resolver.State{Addresses: addrs}) 134 135 cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 136 if err != nil { 137 t.Fatalf("grpc.NewClient() failed: %v", err) 138 } 139 defer cc.Close() 140 141 // Push a resolver update without an LB policy in the service config. The 142 // channel should pick the default LB policy, which is pick_first. 143 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 144 defer cancel() 145 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil { 146 t.Fatal(err) 147 } 148 149 // Push a resolver update with a service config specifying "round_robin". 150 r.UpdateState(resolver.State{ 151 Addresses: addrs, 152 ServiceConfig: parseServiceConfig(t, r, rrServiceConfig), 153 }) 154 client := testgrpc.NewTestServiceClient(cc) 155 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs); err != nil { 156 t.Fatal(err) 157 } 158 159 // Push another resolver update with a service config specifying "pick_first". 160 r.UpdateState(resolver.State{ 161 Addresses: addrs, 162 ServiceConfig: parseServiceConfig(t, r, pickFirstServiceConfig), 163 }) 164 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil { 165 t.Fatal(err) 166 } 167 } 168 169 // TestBalancerSwitch_grpclbToPickFirst tests the scenario where the channel 170 // starts off "grpclb", switches to "pick_first" and back. 171 func (s) TestBalancerSwitch_grpclbToPickFirst(t *testing.T) { 172 backends, lbServer, cleanup := setupBackendsAndFakeGRPCLB(t) 173 defer cleanup() 174 175 addrs := stubBackendsToResolverAddrs(backends) 176 r := manual.NewBuilderWithScheme("whatever") 177 target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName) 178 cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 179 if err != nil { 180 t.Fatalf("grpc.NewClient() failed: %v", err) 181 } 182 defer cc.Close() 183 cc.Connect() 184 185 // Push a resolver update with a GRPCLB service config and a single address 186 // pointing to the grpclb server we created above. This will cause the 187 // channel to switch to the "grpclb" balancer, which returns a single 188 // backend address. 189 grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig) 190 state := resolver.State{ServiceConfig: grpclbConfig} 191 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}})) 192 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 193 defer cancel() 194 client := testgrpc.NewTestServiceClient(cc) 195 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[0:1]); err != nil { 196 t.Fatal(err) 197 } 198 199 // Push a resolver update containing a non-existent grpclb server address. 200 // This should not lead to a balancer switch. 201 const nonExistentServer = "non-existent-grpclb-server-address" 202 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: nonExistentServer}}})) 203 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[:1]); err != nil { 204 t.Fatal(err) 205 } 206 207 // Push a resolver update containing no grpclb server address. This should 208 // lead to the channel using the default LB policy which is pick_first. The 209 // list of addresses pushed as part of this update is different from the one 210 // returned by the "grpclb" balancer. So, we should see RPCs going to the 211 // newly configured backends, as part of the balancer switch. 212 emptyConfig := parseServiceConfig(t, r, `{}`) 213 r.UpdateState(resolver.State{Addresses: addrs[1:], ServiceConfig: emptyConfig}) 214 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil { 215 t.Fatal(err) 216 } 217 } 218 219 // TestBalancerSwitch_pickFirstToGRPCLB tests the scenario where the channel 220 // starts off with "pick_first", switches to "grpclb" and back. 221 func (s) TestBalancerSwitch_pickFirstToGRPCLB(t *testing.T) { 222 backends, lbServer, cleanup := setupBackendsAndFakeGRPCLB(t) 223 defer cleanup() 224 225 addrs := stubBackendsToResolverAddrs(backends) 226 r := manual.NewBuilderWithScheme("whatever") 227 target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName) 228 cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 229 if err != nil { 230 t.Fatalf("grpc.NewClient() failed: %v", err) 231 } 232 defer cc.Close() 233 234 // Set an empty initial resolver state. This should lead to the channel 235 // using the default LB policy which is pick_first. 236 r.InitialState(resolver.State{Addresses: addrs[1:]}) 237 238 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 239 defer cancel() 240 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil { 241 t.Fatal(err) 242 } 243 244 // Push a resolver update with no service config and a single address pointing 245 // to the grpclb server we created above. This will cause the channel to 246 // switch to the "grpclb" balancer, which returns a single backend address. 247 grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig) 248 state := resolver.State{ServiceConfig: grpclbConfig} 249 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}})) 250 client := testgrpc.NewTestServiceClient(cc) 251 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[:1]); err != nil { 252 t.Fatal(err) 253 } 254 255 // Push a resolver update containing a non-existent grpclb server address. 256 // This should not lead to a balancer switch. 257 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: "nonExistentServer"}}})) 258 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[:1]); err != nil { 259 t.Fatal(err) 260 } 261 262 // Switch to "pick_first" again by sending no grpclb server addresses. 263 emptyConfig := parseServiceConfig(t, r, `{}`) 264 r.UpdateState(resolver.State{Addresses: addrs[1:], ServiceConfig: emptyConfig}) 265 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[1]); err != nil { 266 t.Fatal(err) 267 } 268 } 269 270 // TestBalancerSwitch_RoundRobinToGRPCLB tests the scenario where the channel 271 // starts off with "round_robin", switches to "grpclb" and back. 272 // 273 // Note that this test uses the deprecated `loadBalancingPolicy` field in the 274 // service config. 275 func (s) TestBalancerSwitch_RoundRobinToGRPCLB(t *testing.T) { 276 backends, lbServer, cleanup := setupBackendsAndFakeGRPCLB(t) 277 defer cleanup() 278 279 addrs := stubBackendsToResolverAddrs(backends) 280 r := manual.NewBuilderWithScheme("whatever") 281 target := fmt.Sprintf("%s:///%s", r.Scheme(), loadBalancedServiceName) 282 cc, err := grpc.NewClient(target, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 283 if err != nil { 284 t.Fatalf("grpc.NewClient() failed: %v", err) 285 } 286 defer cc.Close() 287 cc.Connect() 288 // Note the use of the deprecated `loadBalancingPolicy` field here instead 289 // of the now recommended `loadBalancingConfig` field. The logic in the 290 // ClientConn which decides which balancer to switch to looks at the 291 // following places in the given order of preference: 292 // - `loadBalancingConfig` field 293 // - addresses of type grpclb 294 // - `loadBalancingPolicy` field 295 // If we use the `loadBalancingPolicy` field, the switch to "grpclb" later on 296 // in the test will not happen as the ClientConn will continue to use the LB 297 // policy received in the first update. 298 scpr := parseServiceConfig(t, r, rrServiceConfig) 299 300 // Push a resolver update with the service config specifying "round_robin". 301 r.UpdateState(resolver.State{Addresses: addrs[1:], ServiceConfig: scpr}) 302 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 303 defer cancel() 304 client := testgrpc.NewTestServiceClient(cc) 305 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[1:]); err != nil { 306 t.Fatal(err) 307 } 308 309 // Push a resolver update with grpclb and a single balancer address 310 // pointing to the grpclb server we created above. This will cause the 311 // channel to switch to the "grpclb" balancer, which returns a single 312 // backend address. 313 grpclbConfig := parseServiceConfig(t, r, grpclbServiceConfig) 314 state := resolver.State{ServiceConfig: grpclbConfig} 315 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: []resolver.Address{{Addr: lbServer.Address()}}})) 316 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[:1]); err != nil { 317 t.Fatal(err) 318 } 319 320 // Switch back to "round_robin". 321 r.UpdateState(resolver.State{Addresses: addrs[1:], ServiceConfig: scpr}) 322 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[1:]); err != nil { 323 t.Fatal(err) 324 } 325 } 326 327 // TestBalancerSwitch_grpclbNotRegistered tests the scenario where the grpclb 328 // balancer is not registered. Verifies that the ClientConn falls back to the 329 // default LB policy or the LB policy specified in the service config, and that 330 // addresses of type "grpclb" are filtered out. 331 func (s) TestBalancerSwitch_grpclbNotRegistered(t *testing.T) { 332 // Unregister the grpclb balancer builder for the duration of this test. 333 grpclbBuilder := balancer.Get("grpclb") 334 internal.BalancerUnregister(grpclbBuilder.Name()) 335 defer balancer.Register(grpclbBuilder) 336 337 backends, cleanup := startBackendsForBalancerSwitch(t) 338 defer cleanup() 339 addrs := stubBackendsToResolverAddrs(backends) 340 341 r := manual.NewBuilderWithScheme("whatever") 342 cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 343 if err != nil { 344 t.Fatalf("grpc.NewClient() failed: %v", err) 345 } 346 defer cc.Close() 347 cc.Connect() 348 349 // Push a resolver update which contains a bunch of stub server backends and a 350 // grpclb server address. The latter should get the ClientConn to try and 351 // apply the grpclb policy. But since grpclb is not registered, it should 352 // fallback to the default LB policy which is pick_first. The ClientConn is 353 // also expected to filter out the grpclb address when sending the addresses 354 // list for pick_first. 355 grpclbAddr := []resolver.Address{{Addr: "non-existent-grpclb-server-address"}} 356 grpclbConfig := parseServiceConfig(t, r, `{"loadBalancingPolicy": "grpclb"}`) 357 state := resolver.State{ServiceConfig: grpclbConfig, Addresses: addrs} 358 r.UpdateState(grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: grpclbAddr})) 359 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 360 defer cancel() 361 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil { 362 t.Fatalf("Pick_first backend readiness check failed: %v", err) 363 } 364 365 // Push a resolver update with the same addresses, but with a service config 366 // specifying "round_robin". The ClientConn is expected to filter out the 367 // grpclb address when sending the addresses list to round_robin. 368 r.UpdateState(resolver.State{ 369 Addresses: addrs, 370 ServiceConfig: parseServiceConfig(t, r, rrServiceConfig), 371 }) 372 client := testgrpc.NewTestServiceClient(cc) 373 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs); err != nil { 374 t.Fatalf("Round robin RPCs failed: %v", err) 375 } 376 } 377 378 // TestBalancerSwitch_OldBalancerCallsShutdownInClose tests the scenario where 379 // the balancer being switched out calls Shutdown() in its Close() 380 // method. Verifies that this sequence of calls doesn't lead to a deadlock. 381 func (s) TestBalancerSwitch_OldBalancerCallsShutdownInClose(t *testing.T) { 382 // Register a stub balancer which calls Shutdown() from its Close(). 383 scChan := make(chan balancer.SubConn, 1) 384 uccsCalled := make(chan struct{}, 1) 385 stub.Register(t.Name(), stub.BalancerFuncs{ 386 UpdateClientConnState: func(data *stub.BalancerData, ccs balancer.ClientConnState) error { 387 sc, err := data.ClientConn.NewSubConn(ccs.ResolverState.Addresses, balancer.NewSubConnOptions{}) 388 if err != nil { 389 t.Errorf("failed to create subConn: %v", err) 390 } 391 scChan <- sc 392 close(uccsCalled) 393 return nil 394 }, 395 Close: func(*stub.BalancerData) { 396 (<-scChan).Shutdown() 397 }, 398 }) 399 400 r := manual.NewBuilderWithScheme("whatever") 401 cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 402 if err != nil { 403 t.Fatalf("grpc.NewClient() failed: %v", err) 404 } 405 cc.Connect() 406 defer cc.Close() 407 408 // Push a resolver update specifying our stub balancer as the LB policy. 409 scpr := parseServiceConfig(t, r, fmt.Sprintf(`{"loadBalancingPolicy": "%v"}`, t.Name())) 410 r.UpdateState(resolver.State{ 411 Addresses: []resolver.Address{{Addr: "dummy-address"}}, 412 ServiceConfig: scpr, 413 }) 414 415 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 416 defer cancel() 417 select { 418 case <-ctx.Done(): 419 t.Fatalf("timeout waiting for UpdateClientConnState to be called: %v", ctx.Err()) 420 case <-uccsCalled: 421 } 422 423 // The following service config update will switch balancer from our stub 424 // balancer to pick_first. The former will be closed, which will call 425 // sc.Shutdown() inline. 426 // 427 // This is to make sure the sc.Shutdown() from Close() doesn't cause a 428 // deadlock (e.g. trying to grab a mutex while it's already locked). 429 // 430 // Do it in a goroutine so this test will fail with a helpful message 431 // (though the goroutine will still leak). 432 done := make(chan struct{}) 433 go func() { 434 r.UpdateState(resolver.State{ 435 Addresses: []resolver.Address{{Addr: "dummy-address"}}, 436 ServiceConfig: parseServiceConfig(t, r, pickFirstServiceConfig), 437 }) 438 close(done) 439 }() 440 441 select { 442 case <-ctx.Done(): 443 t.Fatalf("timeout waiting for resolver.UpdateState to finish: %v", ctx.Err()) 444 case <-done: 445 } 446 } 447 448 // TestBalancerSwitch_Graceful tests the graceful switching of LB policies. It 449 // starts off by configuring "round_robin" on the channel and ensures that RPCs 450 // are successful. Then, it switches to a stub balancer which does not report a 451 // picker until instructed by the test do to so. At this point, the test 452 // verifies that RPCs are still successful using the old balancer. Then the test 453 // asks the new balancer to report a healthy picker and the test verifies that 454 // the RPCs get routed using the picker reported by the new balancer. 455 func (s) TestBalancerSwitch_Graceful(t *testing.T) { 456 backends, cleanup := startBackendsForBalancerSwitch(t) 457 defer cleanup() 458 addrs := stubBackendsToResolverAddrs(backends) 459 460 r := manual.NewBuilderWithScheme("whatever") 461 cc, err := grpc.NewClient(r.Scheme()+":///test.server", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithResolvers(r)) 462 if err != nil { 463 t.Fatalf("grpc.NewClient() failed: %v", err) 464 } 465 defer cc.Close() 466 cc.Connect() 467 // Push a resolver update with the service config specifying "round_robin". 468 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 469 defer cancel() 470 r.UpdateState(resolver.State{ 471 Addresses: addrs[1:], 472 ServiceConfig: parseServiceConfig(t, r, rrServiceConfig), 473 }) 474 client := testgrpc.NewTestServiceClient(cc) 475 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[1:]); err != nil { 476 t.Fatal(err) 477 } 478 479 // Register a stub balancer which uses a "pick_first" balancer underneath and 480 // signals on a channel when it receives ClientConn updates. But it does not 481 // forward the ccUpdate to the underlying "pick_first" balancer until the test 482 // asks it to do so. This allows us to test the graceful switch functionality. 483 // Until the test asks the stub balancer to forward the ccUpdate, RPCs should 484 // get routed to the old balancer. And once the test gives the go ahead, RPCs 485 // should get routed to the new balancer. 486 ccUpdateCh := make(chan struct{}) 487 waitToProceed := make(chan struct{}) 488 stub.Register(t.Name(), stub.BalancerFuncs{ 489 Init: func(bd *stub.BalancerData) { 490 pf := balancer.Get(pickfirst.Name) 491 bd.Data = pf.Build(bd.ClientConn, bd.BuildOptions) 492 }, 493 Close: func(bd *stub.BalancerData) { 494 bd.Data.(balancer.Balancer).Close() 495 }, 496 UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { 497 bal := bd.Data.(balancer.Balancer) 498 close(ccUpdateCh) 499 go func() { 500 <-waitToProceed 501 bal.UpdateClientConnState(ccs) 502 }() 503 return nil 504 }, 505 }) 506 507 // Push a resolver update with the service config specifying our stub 508 // balancer. We should see a trace event for this balancer switch. But RPCs 509 // should still be routed to the old balancer since our stub balancer does not 510 // report a ready picker until we ask it to do so. 511 r.UpdateState(resolver.State{ 512 Addresses: addrs[:1], 513 ServiceConfig: r.CC().ParseServiceConfig(fmt.Sprintf(`{"loadBalancingConfig": [{"%v": {}}]}`, t.Name())), 514 }) 515 select { 516 case <-ctx.Done(): 517 t.Fatal("Timeout when waiting for a ClientConnState update on the new balancer") 518 case <-ccUpdateCh: 519 } 520 if err := rrutil.CheckRoundRobinRPCs(ctx, client, addrs[1:]); err != nil { 521 t.Fatalf("RPCs routed to old balancer failed: %v", err) 522 } 523 524 // Ask our stub balancer to forward the earlier received ccUpdate to the 525 // underlying "pick_first" balancer which will result in a healthy picker 526 // being reported to the channel. RPCs should start using the new balancer. 527 close(waitToProceed) 528 if err := pfutil.CheckRPCsToBackend(ctx, cc, addrs[0]); err != nil { 529 t.Fatalf("RPCs routed to new balancer failed: %v", err) 530 } 531 }