google.golang.org/grpc@v1.74.2/balancer/rls/balancer_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 rls 20 21 import ( 22 "context" 23 "encoding/json" 24 "errors" 25 "fmt" 26 "sync" 27 "testing" 28 "time" 29 30 "github.com/google/go-cmp/cmp" 31 "google.golang.org/grpc" 32 "google.golang.org/grpc/balancer" 33 "google.golang.org/grpc/balancer/pickfirst" 34 "google.golang.org/grpc/balancer/rls/internal/test/e2e" 35 "google.golang.org/grpc/codes" 36 "google.golang.org/grpc/connectivity" 37 "google.golang.org/grpc/credentials" 38 "google.golang.org/grpc/credentials/insecure" 39 "google.golang.org/grpc/internal" 40 "google.golang.org/grpc/internal/balancer/stub" 41 internalserviceconfig "google.golang.org/grpc/internal/serviceconfig" 42 "google.golang.org/grpc/internal/testutils" 43 rlstest "google.golang.org/grpc/internal/testutils/rls" 44 "google.golang.org/grpc/metadata" 45 "google.golang.org/grpc/resolver" 46 "google.golang.org/grpc/resolver/manual" 47 "google.golang.org/grpc/serviceconfig" 48 "google.golang.org/grpc/testdata" 49 50 rlspb "google.golang.org/grpc/internal/proto/grpc_lookup_v1" 51 "google.golang.org/protobuf/types/known/durationpb" 52 ) 53 54 // TestConfigUpdate_ControlChannel tests the scenario where a config update 55 // changes the RLS server name. Verifies that the new control channel is created 56 // and the old one is closed. 57 func (s) TestConfigUpdate_ControlChannel(t *testing.T) { 58 // Start two RLS servers. 59 lis1 := testutils.NewListenerWrapper(t, nil) 60 rlsServer1, rlsReqCh1 := rlstest.SetupFakeRLSServer(t, lis1) 61 lis2 := testutils.NewListenerWrapper(t, nil) 62 rlsServer2, rlsReqCh2 := rlstest.SetupFakeRLSServer(t, lis2) 63 64 // Build RLS service config with the RLS server pointing to the first one. 65 // Set a very low value for maxAge to ensure that the entry expires soon. 66 rlsConfig := buildBasicRLSConfigWithChildPolicy(t, t.Name(), rlsServer1.Address) 67 rlsConfig.RouteLookupConfig.MaxAge = durationpb.New(defaultTestShortTimeout) 68 69 // Start a couple of test backends, and set up the fake RLS servers to return 70 // these as a target in the RLS response. 71 backendCh1, backendAddress1 := startBackend(t) 72 rlsServer1.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 73 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress1}}} 74 }) 75 backendCh2, backendAddress2 := startBackend(t) 76 rlsServer2.SetResponseCallback(func(context.Context, *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 77 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress2}}} 78 }) 79 80 // Register a manual resolver and push the RLS service config through it. 81 r := startManualResolverWithConfig(t, rlsConfig) 82 83 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 84 if err != nil { 85 t.Fatalf("Failed to create gRPC client: %v", err) 86 } 87 defer cc.Close() 88 89 // Make an RPC and ensure it gets routed to the test backend. 90 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 91 defer cancel() 92 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh1) 93 94 // Ensure a connection is established to the first RLS server. 95 val, err := lis1.NewConnCh.Receive(ctx) 96 if err != nil { 97 t.Fatal("Timeout expired when waiting for LB policy to create control channel") 98 } 99 conn1 := val.(*testutils.ConnWrapper) 100 101 // Make sure an RLS request is sent out. 102 verifyRLSRequest(t, rlsReqCh1, true) 103 104 // Change lookup_service field of the RLS config to point to the second one. 105 rlsConfig.RouteLookupConfig.LookupService = rlsServer2.Address 106 107 // Push the config update through the manual resolver. 108 scJSON, err := rlsConfig.ServiceConfigJSON() 109 if err != nil { 110 t.Fatal(err) 111 } 112 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 113 r.UpdateState(resolver.State{ServiceConfig: sc}) 114 115 // Ensure a connection is established to the second RLS server. 116 if _, err := lis2.NewConnCh.Receive(ctx); err != nil { 117 t.Fatal("Timeout expired when waiting for LB policy to create control channel") 118 } 119 120 // Ensure the connection to the old one is closed. 121 if _, err := conn1.CloseCh.Receive(ctx); err != nil { 122 t.Fatal("Timeout expired when waiting for LB policy to close control channel") 123 } 124 125 // Make an RPC and expect it to get routed to the second test backend through 126 // the second RLS server. 127 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh2) 128 verifyRLSRequest(t, rlsReqCh2, true) 129 } 130 131 // TestConfigUpdate_ControlChannelWithCreds tests the scenario where a config 132 // update specified an RLS server name, and the parent ClientConn specifies 133 // transport credentials. The RLS server and the test backend are configured to 134 // accept those transport credentials. This test verifies that the parent 135 // channel credentials are correctly propagated to the control channel. 136 func (s) TestConfigUpdate_ControlChannelWithCreds(t *testing.T) { 137 serverCreds, err := credentials.NewServerTLSFromFile(testdata.Path("x509/server1_cert.pem"), testdata.Path("x509/server1_key.pem")) 138 if err != nil { 139 t.Fatalf("credentials.NewServerTLSFromFile(server1.pem, server1.key) = %v", err) 140 } 141 clientCreds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "") 142 if err != nil { 143 t.Fatalf("credentials.NewClientTLSFromFile(ca.pem) = %v", err) 144 } 145 146 // Start an RLS server with the wrapped listener and credentials. 147 lis := testutils.NewListenerWrapper(t, nil) 148 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, lis, grpc.Creds(serverCreds)) 149 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 150 151 // Build RLS service config. 152 rlsConfig := buildBasicRLSConfigWithChildPolicy(t, t.Name(), rlsServer.Address) 153 154 // Start a test backend which uses the same credentials as the RLS server, 155 // and set up the fake RLS server to return this as the target in the RLS 156 // response. 157 backendCh, backendAddress := startBackend(t, grpc.Creds(serverCreds)) 158 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 159 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress}}} 160 }) 161 162 // Register a manual resolver and push the RLS service config through it. 163 r := startManualResolverWithConfig(t, rlsConfig) 164 165 // Dial with credentials and expect the RLS server to receive the same. The 166 // server certificate used for the RLS server and the backend specifies a 167 // DNS SAN of "*.test.example.com". Hence we use a dial target which is a 168 // subdomain of the same here. 169 cc, err := grpc.NewClient(r.Scheme()+":///rls.test.example.com", grpc.WithResolvers(r), grpc.WithTransportCredentials(clientCreds)) 170 if err != nil { 171 t.Fatalf("Failed to create gRPC client: %v", err) 172 } 173 defer cc.Close() 174 175 // Make an RPC and ensure it gets routed to the test backend. 176 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 177 defer cancel() 178 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh) 179 180 // Make sure an RLS request is sent out. 181 verifyRLSRequest(t, rlsReqCh, true) 182 183 // Ensure a connection is established to the first RLS server. 184 if _, err := lis.NewConnCh.Receive(ctx); err != nil { 185 t.Fatal("Timeout expired when waiting for LB policy to create control channel") 186 } 187 } 188 189 // TestConfigUpdate_ControlChannelServiceConfig tests the scenario where RLS LB 190 // policy's configuration specifies the service config for the control channel 191 // via the `routeLookupChannelServiceConfig` field. This test verifies that the 192 // provided service config is applied for the control channel. 193 func (s) TestConfigUpdate_ControlChannelServiceConfig(t *testing.T) { 194 // Start an RLS server and set the throttler to never throttle requests. 195 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 196 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 197 198 // Register a balancer to be used for the control channel, and set up a 199 // callback to get notified when the balancer receives a clientConn updates. 200 ccUpdateCh := testutils.NewChannel() 201 bf := &e2e.BalancerFuncs{ 202 UpdateClientConnState: func(cfg *e2e.RLSChildPolicyConfig) error { 203 if cfg.Backend != rlsServer.Address { 204 return fmt.Errorf("control channel LB policy received config with backend %q, want %q", cfg.Backend, rlsServer.Address) 205 } 206 ccUpdateCh.Replace(nil) 207 return nil 208 }, 209 } 210 controlChannelPolicyName := "test-control-channel-" + t.Name() 211 e2e.RegisterRLSChildPolicy(controlChannelPolicyName, bf) 212 t.Logf("Registered child policy with name %q", controlChannelPolicyName) 213 214 // Build RLS service config and set the `routeLookupChannelServiceConfig` 215 // field to a service config which uses the above balancer. 216 rlsConfig := buildBasicRLSConfigWithChildPolicy(t, t.Name(), rlsServer.Address) 217 rlsConfig.RouteLookupChannelServiceConfig = fmt.Sprintf(`{"loadBalancingConfig" : [{%q: {"backend": %q} }]}`, controlChannelPolicyName, rlsServer.Address) 218 219 // Start a test backend, and set up the fake RLS server to return this as a 220 // target in the RLS response. 221 backendCh, backendAddress := startBackend(t) 222 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 223 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress}}} 224 }) 225 226 // Register a manual resolver and push the RLS service config through it. 227 r := startManualResolverWithConfig(t, rlsConfig) 228 229 cc, err := grpc.NewClient(r.Scheme()+":///rls.test.example.com", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 230 if err != nil { 231 t.Fatalf("Failed to create gRPC client: %v", err) 232 } 233 defer cc.Close() 234 235 // Make an RPC and ensure it gets routed to the test backend. 236 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 237 defer cancel() 238 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh) 239 240 // Make sure an RLS request is sent out. 241 verifyRLSRequest(t, rlsReqCh, true) 242 243 // Verify that the control channel is using the LB policy we injected via the 244 // routeLookupChannelServiceConfig field. 245 if _, err := ccUpdateCh.Receive(ctx); err != nil { 246 t.Fatalf("timeout when waiting for control channel LB policy to receive a clientConn update") 247 } 248 } 249 250 // TestConfigUpdate_DefaultTarget tests the scenario where a config update 251 // changes the default target. Verifies that RPCs get routed to the new default 252 // target after the config has been applied. 253 func (s) TestConfigUpdate_DefaultTarget(t *testing.T) { 254 // Start an RLS server and set the throttler to always throttle requests. 255 rlsServer, _ := rlstest.SetupFakeRLSServer(t, nil) 256 overrideAdaptiveThrottler(t, alwaysThrottlingThrottler()) 257 258 // Build RLS service config with a default target. 259 rlsConfig := buildBasicRLSConfigWithChildPolicy(t, t.Name(), rlsServer.Address) 260 backendCh1, backendAddress1 := startBackend(t) 261 rlsConfig.RouteLookupConfig.DefaultTarget = backendAddress1 262 263 // Register a manual resolver and push the RLS service config through it. 264 r := startManualResolverWithConfig(t, rlsConfig) 265 266 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 267 if err != nil { 268 t.Fatalf("Failed to create gRPC client: %v", err) 269 } 270 defer cc.Close() 271 272 // Make an RPC and ensure it gets routed to the default target. 273 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 274 defer cancel() 275 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh1) 276 277 // Change default_target field of the RLS config. 278 backendCh2, backendAddress2 := startBackend(t) 279 rlsConfig.RouteLookupConfig.DefaultTarget = backendAddress2 280 281 // Push the config update through the manual resolver. 282 scJSON, err := rlsConfig.ServiceConfigJSON() 283 if err != nil { 284 t.Fatal(err) 285 } 286 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 287 r.UpdateState(resolver.State{ServiceConfig: sc}) 288 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh2) 289 } 290 291 // TestConfigUpdate_ChildPolicyConfigs verifies that config changes which affect 292 // child policy configuration are propagated correctly. 293 func (s) TestConfigUpdate_ChildPolicyConfigs(t *testing.T) { 294 // Start an RLS server and set the throttler to never throttle requests. 295 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 296 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 297 298 // Start a default backend and a test backend. 299 _, defBackendAddress := startBackend(t) 300 testBackendCh, testBackendAddress := startBackend(t) 301 302 // Set up the RLS server to respond with the test backend. 303 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 304 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{testBackendAddress}}} 305 }) 306 307 // Set up a test balancer callback to push configs received by child policies. 308 defBackendConfigsCh := make(chan *e2e.RLSChildPolicyConfig, 1) 309 testBackendConfigsCh := make(chan *e2e.RLSChildPolicyConfig, 1) 310 bf := &e2e.BalancerFuncs{ 311 UpdateClientConnState: func(cfg *e2e.RLSChildPolicyConfig) error { 312 switch cfg.Backend { 313 case defBackendAddress: 314 defBackendConfigsCh <- cfg 315 case testBackendAddress: 316 testBackendConfigsCh <- cfg 317 default: 318 t.Errorf("Received child policy configs for unknown target %q", cfg.Backend) 319 } 320 return nil 321 }, 322 } 323 324 // Register an LB policy to act as the child policy for RLS LB policy. 325 childPolicyName := "test-child-policy" + t.Name() 326 e2e.RegisterRLSChildPolicy(childPolicyName, bf) 327 t.Logf("Registered child policy with name %q", childPolicyName) 328 329 // Build RLS service config with default target. 330 rlsConfig := buildBasicRLSConfig(childPolicyName, rlsServer.Address) 331 rlsConfig.RouteLookupConfig.DefaultTarget = defBackendAddress 332 333 // Register a manual resolver and push the RLS service config through it. 334 r := startManualResolverWithConfig(t, rlsConfig) 335 336 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 337 if err != nil { 338 t.Fatalf("grpc.NewClient() failed: %v", err) 339 } 340 defer cc.Close() 341 cc.Connect() 342 343 // At this point, the RLS LB policy should have received its config, and 344 // should have created a child policy for the default target. 345 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 346 defer cancel() 347 wantCfg := &e2e.RLSChildPolicyConfig{Backend: defBackendAddress} 348 select { 349 case <-ctx.Done(): 350 t.Fatal("Timed out when waiting for the default target child policy to receive its config") 351 case gotCfg := <-defBackendConfigsCh: 352 if !cmp.Equal(gotCfg, wantCfg) { 353 t.Fatalf("Default target child policy received config %+v, want %+v", gotCfg, wantCfg) 354 } 355 } 356 357 // Make an RPC and ensure it gets routed to the test backend. 358 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, testBackendCh) 359 360 // Make sure an RLS request is sent out. 361 verifyRLSRequest(t, rlsReqCh, true) 362 363 // As part of handling the above RPC, the RLS LB policy should have created 364 // a child policy for the test target. 365 wantCfg = &e2e.RLSChildPolicyConfig{Backend: testBackendAddress} 366 select { 367 case <-ctx.Done(): 368 t.Fatal("Timed out when waiting for the test target child policy to receive its config") 369 case gotCfg := <-testBackendConfigsCh: 370 if !cmp.Equal(gotCfg, wantCfg) { 371 t.Fatalf("Test target child policy received config %+v, want %+v", gotCfg, wantCfg) 372 } 373 } 374 375 // Push an RLS config update with a change in the child policy config. 376 childPolicyBuilder := balancer.Get(childPolicyName) 377 childPolicyParser := childPolicyBuilder.(balancer.ConfigParser) 378 lbCfg, err := childPolicyParser.ParseConfig([]byte(`{"Random": "random"}`)) 379 if err != nil { 380 t.Fatal(err) 381 } 382 rlsConfig.ChildPolicy.Config = lbCfg 383 scJSON, err := rlsConfig.ServiceConfigJSON() 384 if err != nil { 385 t.Fatal(err) 386 } 387 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 388 r.UpdateState(resolver.State{ServiceConfig: sc}) 389 390 // Expect the child policy for the test backend to receive the update. 391 wantCfg = &e2e.RLSChildPolicyConfig{ 392 Backend: testBackendAddress, 393 Random: "random", 394 } 395 select { 396 case <-ctx.Done(): 397 t.Fatal("Timed out when waiting for the test target child policy to receive its config") 398 case gotCfg := <-testBackendConfigsCh: 399 if !cmp.Equal(gotCfg, wantCfg) { 400 t.Fatalf("Test target child policy received config %+v, want %+v", gotCfg, wantCfg) 401 } 402 } 403 404 // Expect the child policy for the default backend to receive the update. 405 wantCfg = &e2e.RLSChildPolicyConfig{ 406 Backend: defBackendAddress, 407 Random: "random", 408 } 409 select { 410 case <-ctx.Done(): 411 t.Fatal("Timed out when waiting for the default target child policy to receive its config") 412 case gotCfg := <-defBackendConfigsCh: 413 if !cmp.Equal(gotCfg, wantCfg) { 414 t.Fatalf("Default target child policy received config %+v, want %+v", gotCfg, wantCfg) 415 } 416 } 417 } 418 419 // TestConfigUpdate_ChildPolicyChange verifies that a child policy change is 420 // handled by closing the old balancer and creating a new one. 421 func (s) TestConfigUpdate_ChildPolicyChange(t *testing.T) { 422 // Start an RLS server and set the throttler to never throttle requests. 423 rlsServer, _ := rlstest.SetupFakeRLSServer(t, nil) 424 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 425 426 // Set up balancer callbacks. 427 configsCh1 := make(chan *e2e.RLSChildPolicyConfig, 1) 428 closeCh1 := make(chan struct{}, 1) 429 bf := &e2e.BalancerFuncs{ 430 UpdateClientConnState: func(cfg *e2e.RLSChildPolicyConfig) error { 431 configsCh1 <- cfg 432 return nil 433 }, 434 Close: func() { 435 closeCh1 <- struct{}{} 436 }, 437 } 438 439 // Register an LB policy to act as the child policy for RLS LB policy. 440 childPolicyName1 := "test-child-policy-1" + t.Name() 441 e2e.RegisterRLSChildPolicy(childPolicyName1, bf) 442 t.Logf("Registered child policy with name %q", childPolicyName1) 443 444 // Build RLS service config with a dummy default target. 445 const defaultBackend = "default-backend" 446 rlsConfig := buildBasicRLSConfig(childPolicyName1, rlsServer.Address) 447 rlsConfig.RouteLookupConfig.DefaultTarget = defaultBackend 448 449 // Register a manual resolver and push the RLS service config through it. 450 r := startManualResolverWithConfig(t, rlsConfig) 451 452 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 453 if err != nil { 454 t.Fatalf("grpc.NewClient() failed: %v", err) 455 } 456 defer cc.Close() 457 cc.Connect() 458 459 // At this point, the RLS LB policy should have received its config, and 460 // should have created a child policy for the default target. 461 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 462 defer cancel() 463 wantCfg := &e2e.RLSChildPolicyConfig{Backend: defaultBackend} 464 select { 465 case <-ctx.Done(): 466 t.Fatal("Timed out when waiting for the first child policy to receive its config") 467 case gotCfg := <-configsCh1: 468 if !cmp.Equal(gotCfg, wantCfg) { 469 t.Fatalf("First child policy received config %+v, want %+v", gotCfg, wantCfg) 470 } 471 } 472 473 // Set up balancer callbacks for the second policy. 474 configsCh2 := make(chan *e2e.RLSChildPolicyConfig, 1) 475 bf = &e2e.BalancerFuncs{ 476 UpdateClientConnState: func(cfg *e2e.RLSChildPolicyConfig) error { 477 configsCh2 <- cfg 478 return nil 479 }, 480 } 481 482 // Register a second LB policy to act as the child policy for RLS LB policy. 483 childPolicyName2 := "test-child-policy-2" + t.Name() 484 e2e.RegisterRLSChildPolicy(childPolicyName2, bf) 485 t.Logf("Registered child policy with name %q", childPolicyName2) 486 487 // Push an RLS config update with a change in the child policy name. 488 rlsConfig.ChildPolicy = &internalserviceconfig.BalancerConfig{Name: childPolicyName2} 489 scJSON, err := rlsConfig.ServiceConfigJSON() 490 if err != nil { 491 t.Fatal(err) 492 } 493 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 494 r.UpdateState(resolver.State{ServiceConfig: sc}) 495 496 // The above update should result in the first LB policy being shutdown and 497 // the second LB policy receiving a config update. 498 select { 499 case <-ctx.Done(): 500 t.Fatal("Timed out when waiting for the first child policy to be shutdown") 501 case <-closeCh1: 502 } 503 504 select { 505 case <-ctx.Done(): 506 t.Fatal("Timed out when waiting for the second child policy to receive its config") 507 case gotCfg := <-configsCh2: 508 if !cmp.Equal(gotCfg, wantCfg) { 509 t.Fatalf("First child policy received config %+v, want %+v", gotCfg, wantCfg) 510 } 511 } 512 } 513 514 // TestConfigUpdate_BadChildPolicyConfigs tests the scenario where a config 515 // update is rejected by the child policy. Verifies that the child policy 516 // wrapper goes "lame" and the error from the child policy is reported back to 517 // the caller of the RPC. 518 func (s) TestConfigUpdate_BadChildPolicyConfigs(t *testing.T) { 519 // Start an RLS server and set the throttler to never throttle requests. 520 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 521 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 522 523 // Set up the RLS server to respond with a bad target field which is expected 524 // to cause the child policy's ParseTarget to fail and should result in the LB 525 // policy creating a lame child policy wrapper. 526 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 527 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{e2e.RLSChildPolicyBadTarget}}} 528 }) 529 530 // Build RLS service config with a default target. This default backend is 531 // expected to be healthy (even though we don't attempt to route RPCs to it) 532 // and ensures that the overall connectivity state of the RLS LB policy is not 533 // TRANSIENT_FAILURE. This is required to make sure that the pick for the bad 534 // child policy actually gets delegated to the child policy picker. 535 rlsConfig := buildBasicRLSConfigWithChildPolicy(t, t.Name(), rlsServer.Address) 536 _, addr := startBackend(t) 537 rlsConfig.RouteLookupConfig.DefaultTarget = addr 538 539 // Register a manual resolver and push the RLS service config through it. 540 r := startManualResolverWithConfig(t, rlsConfig) 541 542 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 543 if err != nil { 544 t.Fatalf("Failed to create gRPC client: %v", err) 545 } 546 defer cc.Close() 547 548 // Make an RPC and ensure that if fails with the expected error. 549 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 550 defer cancel() 551 makeTestRPCAndVerifyError(ctx, t, cc, codes.Unavailable, e2e.ErrParseConfigBadTarget) 552 553 // Make sure an RLS request is sent out. 554 verifyRLSRequest(t, rlsReqCh, true) 555 } 556 557 // TestConfigUpdate_DataCacheSizeDecrease tests the scenario where a config 558 // update decreases the data cache size. Verifies that entries are evicted from 559 // the cache. 560 func (s) TestConfigUpdate_DataCacheSizeDecrease(t *testing.T) { 561 // Override the clientConn update hook to get notified. 562 clientConnUpdateDone := make(chan struct{}, 1) 563 origClientConnUpdateHook := clientConnUpdateHook 564 clientConnUpdateHook = func() { clientConnUpdateDone <- struct{}{} } 565 defer func() { clientConnUpdateHook = origClientConnUpdateHook }() 566 567 // Override the cache entry size func, and always return 1. 568 origEntrySizeFunc := computeDataCacheEntrySize 569 computeDataCacheEntrySize = func(cacheKey, *cacheEntry) int64 { return 1 } 570 defer func() { computeDataCacheEntrySize = origEntrySizeFunc }() 571 572 // Override the minEvictionDuration to ensure that when the config update 573 // reduces the cache size, the resize operation is not stopped because 574 // we find an entry whose minExpiryDuration has not elapsed. 575 origMinEvictDuration := minEvictDuration 576 minEvictDuration = time.Duration(0) 577 defer func() { minEvictDuration = origMinEvictDuration }() 578 579 // Start an RLS server and set the throttler to never throttle requests. 580 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 581 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 582 583 // Register an LB policy to act as the child policy for RLS LB policy. 584 childPolicyName := "test-child-policy" + t.Name() 585 e2e.RegisterRLSChildPolicy(childPolicyName, nil) 586 t.Logf("Registered child policy with name %q", childPolicyName) 587 588 // Build RLS service config with header matchers. 589 rlsConfig := buildBasicRLSConfig(childPolicyName, rlsServer.Address) 590 591 // Start a couple of test backends, and set up the fake RLS server to return 592 // these as targets in the RLS response, based on request keys. 593 backendCh1, backendAddress1 := startBackend(t) 594 backendCh2, backendAddress2 := startBackend(t) 595 rlsServer.SetResponseCallback(func(_ context.Context, req *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 596 if req.KeyMap["k1"] == "v1" { 597 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress1}}} 598 } 599 if req.KeyMap["k2"] == "v2" { 600 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress2}}} 601 } 602 return &rlstest.RouteLookupResponse{Err: errors.New("no keys in request metadata")} 603 }) 604 605 // Register a manual resolver and push the RLS service config through it. 606 r := startManualResolverWithConfig(t, rlsConfig) 607 608 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 609 if err != nil { 610 t.Fatalf("grpc.NewClient() failed: %v", err) 611 } 612 defer cc.Close() 613 cc.Connect() 614 615 <-clientConnUpdateDone 616 617 // Make an RPC and ensure it gets routed to the first backend. 618 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 619 defer cancel() 620 ctxOutgoing := metadata.AppendToOutgoingContext(ctx, "n1", "v1") 621 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh1) 622 623 // Make sure an RLS request is sent out. 624 verifyRLSRequest(t, rlsReqCh, true) 625 626 // Make another RPC with a different set of headers. This will force the LB 627 // policy to send out a new RLS request, resulting in a new data cache 628 // entry. 629 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n2", "v2") 630 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh2) 631 632 // Make sure an RLS request is sent out. 633 verifyRLSRequest(t, rlsReqCh, true) 634 635 // We currently have two cache entries. Setting the size to 1, will cause 636 // the entry corresponding to backend1 to be evicted. 637 rlsConfig.RouteLookupConfig.CacheSizeBytes = 1 638 639 // Push the config update through the manual resolver. 640 scJSON, err := rlsConfig.ServiceConfigJSON() 641 if err != nil { 642 t.Fatal(err) 643 } 644 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 645 r.UpdateState(resolver.State{ServiceConfig: sc}) 646 647 <-clientConnUpdateDone 648 649 // Make an RPC to match the cache entry which got evicted above, and expect 650 // an RLS request to be made to fetch the targets. 651 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n1", "v1") 652 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh1) 653 654 // Make sure an RLS request is sent out. 655 verifyRLSRequest(t, rlsReqCh, true) 656 } 657 658 // Test that when a data cache entry is evicted due to config change 659 // in cache size, the picker is updated accordingly. 660 func (s) TestPickerUpdateOnDataCacheSizeDecrease(t *testing.T) { 661 // Override the clientConn update hook to get notified. 662 clientConnUpdateDone := make(chan struct{}, 1) 663 origClientConnUpdateHook := clientConnUpdateHook 664 clientConnUpdateHook = func() { clientConnUpdateDone <- struct{}{} } 665 defer func() { clientConnUpdateHook = origClientConnUpdateHook }() 666 667 // Override the cache entry size func, and always return 1. 668 origEntrySizeFunc := computeDataCacheEntrySize 669 computeDataCacheEntrySize = func(cacheKey, *cacheEntry) int64 { return 1 } 670 defer func() { computeDataCacheEntrySize = origEntrySizeFunc }() 671 672 // Override the backoff strategy to return a large backoff which 673 // will make sure the date cache entry remains in backoff for the 674 // duration of the test. 675 origBackoffStrategy := defaultBackoffStrategy 676 defaultBackoffStrategy = &fakeBackoffStrategy{backoff: defaultTestTimeout} 677 defer func() { defaultBackoffStrategy = origBackoffStrategy }() 678 679 // Override the minEvictionDuration to ensure that when the config update 680 // reduces the cache size, the resize operation is not stopped because 681 // we find an entry whose minExpiryDuration has not elapsed. 682 origMinEvictDuration := minEvictDuration 683 minEvictDuration = time.Duration(0) 684 defer func() { minEvictDuration = origMinEvictDuration }() 685 686 // Register the top-level wrapping balancer which forwards calls to RLS. 687 topLevelBalancerName := t.Name() + "top-level" 688 var ccWrapper *testCCWrapper 689 stub.Register(topLevelBalancerName, stub.BalancerFuncs{ 690 Init: func(bd *stub.BalancerData) { 691 ccWrapper = &testCCWrapper{ClientConn: bd.ClientConn} 692 bd.ChildBalancer = balancer.Get(Name).Build(ccWrapper, bd.BuildOptions) 693 }, 694 ParseConfig: func(sc json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { 695 parser := balancer.Get(Name).(balancer.ConfigParser) 696 return parser.ParseConfig(sc) 697 }, 698 UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { 699 return bd.ChildBalancer.UpdateClientConnState(ccs) 700 }, 701 Close: func(bd *stub.BalancerData) { 702 bd.ChildBalancer.Close() 703 }, 704 }) 705 706 // Start an RLS server and set the throttler to never throttle requests. 707 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 708 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 709 710 // Register an LB policy to act as the child policy for RLS LB policy. 711 childPolicyName := "test-child-policy" + t.Name() 712 e2e.RegisterRLSChildPolicy(childPolicyName, nil) 713 t.Logf("Registered child policy with name %q", childPolicyName) 714 715 // Start a couple of test backends, and set up the fake RLS server to return 716 // these as targets in the RLS response, based on request keys. 717 // Start a couple of test backends, and set up the fake RLS server to return 718 // these as targets in the RLS response, based on request keys. 719 backendCh1, backendAddress1 := startBackend(t) 720 backendCh2, backendAddress2 := startBackend(t) 721 rlsServer.SetResponseCallback(func(_ context.Context, req *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 722 if req.KeyMap["k1"] == "v1" { 723 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress1}}} 724 } 725 if req.KeyMap["k2"] == "v2" { 726 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress2}}} 727 } 728 return &rlstest.RouteLookupResponse{Err: errors.New("no keys in request metadata")} 729 }) 730 731 // Register a manual resolver and push the RLS service config through it. 732 r := manual.NewBuilderWithScheme("rls-e2e") 733 headers := ` 734 [ 735 { 736 "key": "k1", 737 "names": [ 738 "n1" 739 ] 740 }, 741 { 742 "key": "k2", 743 "names": [ 744 "n2" 745 ] 746 } 747 ] 748 ` 749 750 configJSON := ` 751 { 752 "loadBalancingConfig": [ 753 { 754 "%s": { 755 "routeLookupConfig": { 756 "grpcKeybuilders": [{ 757 "names": [{"service": "grpc.testing.TestService"}], 758 "headers": %s 759 }], 760 "lookupService": "%s", 761 "cacheSizeBytes": %d 762 }, 763 "childPolicy": [{"%s": {}}], 764 "childPolicyConfigTargetFieldName": "Backend" 765 } 766 } 767 ] 768 }` 769 scJSON := fmt.Sprintf(configJSON, topLevelBalancerName, headers, rlsServer.Address, 1000, childPolicyName) 770 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 771 r.InitialState(resolver.State{ServiceConfig: sc}) 772 773 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 774 if err != nil { 775 t.Fatalf("create grpc.NewClient() failed: %v", err) 776 } 777 defer cc.Close() 778 cc.Connect() 779 780 <-clientConnUpdateDone 781 782 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 783 defer cancel() 784 // Make an RPC call with empty metadata, which will eventually throw 785 // the error as no metadata will match from rlsServer response 786 // callback defined above. This will cause the control channel to 787 // throw the error and cause the item to get into backoff. 788 makeTestRPCAndVerifyError(ctx, t, cc, codes.Unavailable, nil) 789 790 ctxOutgoing := metadata.AppendToOutgoingContext(ctx, "n1", "v1") 791 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh1) 792 verifyRLSRequest(t, rlsReqCh, true) 793 794 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n2", "v2") 795 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh2) 796 verifyRLSRequest(t, rlsReqCh, true) 797 798 initialStateCnt := len(ccWrapper.getStates()) 799 // Setting the size to 1 will cause the entries to be 800 // evicted. 801 scJSON1 := fmt.Sprintf(` 802 { 803 "loadBalancingConfig": [ 804 { 805 "%s": { 806 "routeLookupConfig": { 807 "grpcKeybuilders": [{ 808 "names": [{"service": "grpc.testing.TestService"}], 809 "headers": %s 810 }], 811 "lookupService": "%s", 812 "cacheSizeBytes": 2 813 }, 814 "childPolicy": [{"%s": {}}], 815 "childPolicyConfigTargetFieldName": "Backend" 816 } 817 } 818 ] 819 }`, topLevelBalancerName, headers, rlsServer.Address, childPolicyName) 820 sc1 := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON1) 821 r.UpdateState(resolver.State{ServiceConfig: sc1}) 822 <-clientConnUpdateDone 823 finalStateCnt := len(ccWrapper.getStates()) 824 825 if finalStateCnt != initialStateCnt+1 { 826 t.Errorf("Unexpected balancer state count: got %v, want %v", finalStateCnt, initialStateCnt) 827 } 828 } 829 830 // TestDataCachePurging verifies that the LB policy periodically evicts expired 831 // entries from the data cache. 832 func (s) TestDataCachePurging(t *testing.T) { 833 // Override the frequency of the data cache purger to a small one. 834 origDataCachePurgeTicker := dataCachePurgeTicker 835 ticker := time.NewTicker(defaultTestShortTimeout) 836 defer ticker.Stop() 837 dataCachePurgeTicker = func() *time.Ticker { return ticker } 838 defer func() { dataCachePurgeTicker = origDataCachePurgeTicker }() 839 840 // Override the data cache purge hook to get notified. 841 dataCachePurgeDone := make(chan struct{}, 1) 842 origDataCachePurgeHook := dataCachePurgeHook 843 dataCachePurgeHook = func() { dataCachePurgeDone <- struct{}{} } 844 defer func() { dataCachePurgeHook = origDataCachePurgeHook }() 845 846 // Start an RLS server and set the throttler to never throttle requests. 847 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 848 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 849 850 // Register an LB policy to act as the child policy for RLS LB policy. 851 childPolicyName := "test-child-policy" + t.Name() 852 e2e.RegisterRLSChildPolicy(childPolicyName, nil) 853 t.Logf("Registered child policy with name %q", childPolicyName) 854 855 // Build RLS service config with header matchers and lookupService pointing to 856 // the fake RLS server created above. Set a very low value for maxAge to 857 // ensure that the entry expires soon. 858 rlsConfig := buildBasicRLSConfig(childPolicyName, rlsServer.Address) 859 rlsConfig.RouteLookupConfig.MaxAge = durationpb.New(time.Millisecond) 860 861 // Start a test backend, and set up the fake RLS server to return this as a 862 // target in the RLS response. 863 backendCh, backendAddress := startBackend(t) 864 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 865 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress}}} 866 }) 867 868 // Register a manual resolver and push the RLS service config through it. 869 r := startManualResolverWithConfig(t, rlsConfig) 870 871 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 872 if err != nil { 873 t.Fatalf("Failed to create gRPC client: %v", err) 874 } 875 defer cc.Close() 876 877 // Make an RPC and ensure it gets routed to the test backend. 878 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 879 defer cancel() 880 ctxOutgoing := metadata.AppendToOutgoingContext(ctx, "n1", "v1") 881 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh) 882 883 // Make sure an RLS request is sent out. 884 verifyRLSRequest(t, rlsReqCh, true) 885 886 // Make another RPC with different headers. This will force the LB policy to 887 // send out a new RLS request, resulting in a new data cache entry. 888 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n2", "v2") 889 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh) 890 891 // Make sure an RLS request is sent out. 892 verifyRLSRequest(t, rlsReqCh, true) 893 894 // Wait for the data cache purging to happen before proceeding. 895 <-dataCachePurgeDone 896 897 // Perform the same RPCs again and verify that they result in RLS requests. 898 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n1", "v1") 899 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh) 900 901 // Make sure an RLS request is sent out. 902 verifyRLSRequest(t, rlsReqCh, true) 903 904 // Make another RPC with different headers. This will force the LB policy to 905 // send out a new RLS request, resulting in a new data cache entry. 906 ctxOutgoing = metadata.AppendToOutgoingContext(ctx, "n2", "v2") 907 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh) 908 909 // Make sure an RLS request is sent out. 910 verifyRLSRequest(t, rlsReqCh, true) 911 } 912 913 // TestControlChannelConnectivityStateMonitoring tests the scenario where the 914 // control channel goes down and comes back up again and verifies that backoff 915 // state is reset for cache entries in this scenario. 916 func (s) TestControlChannelConnectivityStateMonitoring(t *testing.T) { 917 // Create a restartable listener which can close existing connections. 918 l, err := testutils.LocalTCPListener() 919 if err != nil { 920 t.Fatalf("net.Listen() failed: %v", err) 921 } 922 lis := testutils.NewRestartableListener(l) 923 924 // Start an RLS server with the restartable listener and set the throttler to 925 // never throttle requests. 926 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, lis) 927 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 928 929 // Override the reset backoff hook to get notified. 930 resetBackoffDone := make(chan struct{}, 1) 931 origResetBackoffHook := resetBackoffHook 932 resetBackoffHook = func() { resetBackoffDone <- struct{}{} } 933 defer func() { resetBackoffHook = origResetBackoffHook }() 934 935 // Override the backoff strategy to return a large backoff which 936 // will make sure the date cache entry remains in backoff for the 937 // duration of the test. 938 origBackoffStrategy := defaultBackoffStrategy 939 defaultBackoffStrategy = &fakeBackoffStrategy{backoff: defaultTestTimeout} 940 defer func() { defaultBackoffStrategy = origBackoffStrategy }() 941 942 // Register an LB policy to act as the child policy for RLS LB policy. 943 childPolicyName := "test-child-policy" + t.Name() 944 e2e.RegisterRLSChildPolicy(childPolicyName, nil) 945 t.Logf("Registered child policy with name %q", childPolicyName) 946 947 // Build RLS service config with header matchers, and a very low value for 948 // maxAge to ensure that cache entries become invalid very soon. 949 rlsConfig := buildBasicRLSConfig(childPolicyName, rlsServer.Address) 950 rlsConfig.RouteLookupConfig.MaxAge = durationpb.New(defaultTestShortTimeout) 951 952 // Start a test backend, and set up the fake RLS server to return this as a 953 // target in the RLS response. 954 backendCh, backendAddress := startBackend(t) 955 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 956 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{backendAddress}}} 957 }) 958 959 // Register a manual resolver and push the RLS service config through it. 960 r := startManualResolverWithConfig(t, rlsConfig) 961 962 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 963 if err != nil { 964 t.Fatalf("Failed to create gRPC client: %v", err) 965 } 966 defer cc.Close() 967 968 // Make an RPC and ensure it gets routed to the test backend. 969 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 970 defer cancel() 971 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh) 972 973 // Make sure an RLS request is sent out. 974 verifyRLSRequest(t, rlsReqCh, true) 975 976 // Stop the RLS server. 977 lis.Stop() 978 979 // Make another RPC similar to the first one. Since the above cache entry 980 // would have expired by now, this should trigger another RLS request. And 981 // since the RLS server is down, RLS request will fail and the cache entry 982 // will enter backoff, and we have overridden the default backoff strategy to 983 // return a value which will keep this entry in backoff for the whole duration 984 // of the test. 985 makeTestRPCAndVerifyError(ctx, t, cc, codes.Unavailable, nil) 986 987 // Restart the RLS server. 988 lis.Restart() 989 990 // When we closed the RLS server earlier, the existing transport to the RLS 991 // server would have closed, and the RLS control channel would have moved to 992 // TRANSIENT_FAILURE with a subConn backoff before moving to IDLE. This 993 // backoff will last for about a second. We need to keep retrying RPCs for the 994 // subConn to eventually come out of backoff and attempt to reconnect. 995 // 996 // Make this RPC with a different set of headers leading to the creation of 997 // a new cache entry and a new RLS request. This RLS request will also fail 998 // till the control channel comes moves back to READY. So, override the 999 // backoff strategy to perform a small backoff on this entry. 1000 defaultBackoffStrategy = &fakeBackoffStrategy{backoff: defaultTestShortTimeout} 1001 ctxOutgoing := metadata.AppendToOutgoingContext(ctx, "n1", "v1") 1002 makeTestRPCAndExpectItToReachBackend(ctxOutgoing, t, cc, backendCh) 1003 1004 select { 1005 case <-ctx.Done(): 1006 t.Fatalf("Timed out waiting for resetBackoffDone") 1007 case <-resetBackoffDone: 1008 } 1009 1010 // The fact that the above RPC succeeded indicates that the control channel 1011 // has moved back to READY. The connectivity state monitoring code should have 1012 // realized this and should have reset all backoff timers (which in this case 1013 // is the cache entry corresponding to the first RPC). Retrying that RPC now 1014 // should succeed with an RLS request being sent out. 1015 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, backendCh) 1016 verifyRLSRequest(t, rlsReqCh, true) 1017 } 1018 1019 // testCCWrapper wraps a balancer.ClientConn and overrides UpdateState and 1020 // stores all state updates pushed by the RLS LB policy. 1021 type testCCWrapper struct { 1022 balancer.ClientConn 1023 1024 mu sync.Mutex 1025 states []balancer.State 1026 } 1027 1028 func (t *testCCWrapper) UpdateState(bs balancer.State) { 1029 t.mu.Lock() 1030 t.states = append(t.states, bs) 1031 t.mu.Unlock() 1032 t.ClientConn.UpdateState(bs) 1033 } 1034 1035 func (t *testCCWrapper) getStates() []balancer.State { 1036 t.mu.Lock() 1037 defer t.mu.Unlock() 1038 1039 states := make([]balancer.State, len(t.states)) 1040 copy(states, t.states) 1041 return states 1042 } 1043 1044 // TestUpdateStatePauses tests the scenario where a config update received by 1045 // the RLS LB policy results in multiple UpdateState calls from the child 1046 // policies. This test verifies that picker updates are paused when the config 1047 // update is being processed by RLS LB policy and its child policies. 1048 // 1049 // The test uses a wrapping balancer as the top-level LB policy on the channel. 1050 // The wrapping balancer wraps an RLS LB policy as a child policy and forwards 1051 // all calls to it. It also records the UpdateState() calls from the RLS LB 1052 // policy and makes it available for inspection by the test. 1053 // 1054 // The test uses another wrapped balancer (which wraps a pickfirst balancer) as 1055 // the child policy of the RLS LB policy. This balancer makes multiple 1056 // UpdateState calls when handling an update from its parent in 1057 // UpdateClientConnState. 1058 func (s) TestUpdateStatePauses(t *testing.T) { 1059 // Override the hook to get notified when UpdateClientConnState is done. 1060 clientConnUpdateDone := make(chan struct{}, 1) 1061 origClientConnUpdateHook := clientConnUpdateHook 1062 clientConnUpdateHook = func() { clientConnUpdateDone <- struct{}{} } 1063 defer func() { clientConnUpdateHook = origClientConnUpdateHook }() 1064 1065 // Register the top-level wrapping balancer which forwards calls to RLS. 1066 topLevelBalancerName := t.Name() + "top-level" 1067 var ccWrapper *testCCWrapper 1068 stub.Register(topLevelBalancerName, stub.BalancerFuncs{ 1069 Init: func(bd *stub.BalancerData) { 1070 ccWrapper = &testCCWrapper{ClientConn: bd.ClientConn} 1071 bd.ChildBalancer = balancer.Get(Name).Build(ccWrapper, bd.BuildOptions) 1072 }, 1073 ParseConfig: func(sc json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { 1074 parser := balancer.Get(Name).(balancer.ConfigParser) 1075 return parser.ParseConfig(sc) 1076 }, 1077 UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { 1078 return bd.ChildBalancer.UpdateClientConnState(ccs) 1079 }, 1080 Close: func(bd *stub.BalancerData) { 1081 bd.ChildBalancer.Close() 1082 }, 1083 }) 1084 1085 // Register a child policy that wraps a pickfirst balancer and makes multiple calls 1086 // to UpdateState when handling a config update in UpdateClientConnState. When 1087 // this policy is used as a child policy of the RLS LB policy, it is expected 1088 // that the latter suppress these updates and push a single picker update on the 1089 // channel (after the config has been processed by all child policies). 1090 childPolicyName := t.Name() + "child" 1091 type childPolicyConfig struct { 1092 serviceconfig.LoadBalancingConfig 1093 Backend string // `json:"backend,omitempty"` 1094 } 1095 stub.Register(childPolicyName, stub.BalancerFuncs{ 1096 Init: func(bd *stub.BalancerData) { 1097 bd.ChildBalancer = balancer.Get(pickfirst.Name).Build(bd.ClientConn, bd.BuildOptions) 1098 }, 1099 Close: func(bd *stub.BalancerData) { 1100 bd.ChildBalancer.Close() 1101 }, 1102 ParseConfig: func(sc json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { 1103 cfg := &childPolicyConfig{} 1104 if err := json.Unmarshal(sc, cfg); err != nil { 1105 return nil, err 1106 } 1107 return cfg, nil 1108 }, 1109 UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { 1110 bal := bd.ChildBalancer 1111 bd.ClientConn.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &testutils.TestConstPicker{Err: balancer.ErrNoSubConnAvailable}}) 1112 bd.ClientConn.UpdateState(balancer.State{ConnectivityState: connectivity.Connecting, Picker: &testutils.TestConstPicker{Err: balancer.ErrNoSubConnAvailable}}) 1113 1114 cfg := ccs.BalancerConfig.(*childPolicyConfig) 1115 return bal.UpdateClientConnState(balancer.ClientConnState{ 1116 ResolverState: resolver.State{Addresses: []resolver.Address{{Addr: cfg.Backend}}}, 1117 }) 1118 }, 1119 }) 1120 1121 // Start an RLS server and set the throttler to never throttle requests. 1122 rlsServer, rlsReqCh := rlstest.SetupFakeRLSServer(t, nil) 1123 overrideAdaptiveThrottler(t, neverThrottlingThrottler()) 1124 1125 // Start a test backend and set the RLS server to respond with it. 1126 testBackendCh, testBackendAddress := startBackend(t) 1127 rlsServer.SetResponseCallback(func(_ context.Context, _ *rlspb.RouteLookupRequest) *rlstest.RouteLookupResponse { 1128 return &rlstest.RouteLookupResponse{Resp: &rlspb.RouteLookupResponse{Targets: []string{testBackendAddress}}} 1129 }) 1130 1131 // Register a manual resolver and push the RLS service config through it. 1132 r := manual.NewBuilderWithScheme("rls-e2e") 1133 scJSON := fmt.Sprintf(` 1134 { 1135 "loadBalancingConfig": [ 1136 { 1137 "%s": { 1138 "routeLookupConfig": { 1139 "grpcKeybuilders": [{ 1140 "names": [{"service": "grpc.testing.TestService"}] 1141 }], 1142 "lookupService": "%s", 1143 "cacheSizeBytes": 1000 1144 }, 1145 "childPolicy": [{"%s": {}}], 1146 "childPolicyConfigTargetFieldName": "Backend" 1147 } 1148 } 1149 ] 1150 }`, topLevelBalancerName, rlsServer.Address, childPolicyName) 1151 sc := internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 1152 r.InitialState(resolver.State{ServiceConfig: sc}) 1153 1154 cc, err := grpc.NewClient(r.Scheme()+":///", grpc.WithResolvers(r), grpc.WithTransportCredentials(insecure.NewCredentials())) 1155 if err != nil { 1156 t.Fatalf("grpc.NewClient() failed: %v", err) 1157 } 1158 defer cc.Close() 1159 cc.Connect() 1160 1161 // Wait for the clientconn update to be processed by the RLS LB policy. 1162 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 1163 defer cancel() 1164 select { 1165 case <-ctx.Done(): 1166 case <-clientConnUpdateDone: 1167 } 1168 1169 // It is important to note that at this point no child policies have been 1170 // created because we have not attempted any RPC so far. When we attempt an 1171 // RPC (below), child policies will be created and their configs will be 1172 // pushed to them. But this config update will not happen in the context of 1173 // a config update on the parent. 1174 1175 // Make an RPC and ensure it gets routed to the test backend. 1176 makeTestRPCAndExpectItToReachBackend(ctx, t, cc, testBackendCh) 1177 1178 // Make sure an RLS request is sent out. 1179 verifyRLSRequest(t, rlsReqCh, true) 1180 1181 // Wait for the control channel to become READY, before reading the states 1182 // out of the wrapping top-level balancer. 1183 // 1184 // makeTestRPCAndExpectItToReachBackend repeatedly sends RPCs with short 1185 // deadlines until one succeeds. See its docstring for details. 1186 // 1187 // The following sequence of events is possible: 1188 // 1. When the first RPC is attempted above, a pending cache entry is 1189 // created, an RLS request is sent out, and the pick is queued. The 1190 // channel is in CONNECTING state. 1191 // 2. When the RLS response arrives, the pending cache entry is moved to the 1192 // data cache, a child policy is created for the target specified in the 1193 // response and a new picker is returned. The channel is still in 1194 // CONNECTING, and retried pick is again queued. 1195 // 3. The child policy moves through the standard set of states, IDLE --> 1196 // CONNECTING --> READY. And for each of these state changes, a new 1197 // picker is sent on the channel. But the overall connectivity state of 1198 // the channel is still CONNECTING. 1199 // 4. Right around the time when the child policy becomes READY, the 1200 // deadline associated with the first RPC made by 1201 // makeTestRPCAndExpectItToReachBackend() could expire, and it could send 1202 // a new one. And because the internal state of the LB policy now 1203 // contains a child policy which is READY, this RPC will succeed. But the 1204 // RLS LB policy has yet to push a new picker on the channel. 1205 // 5. If we read the states seen by the top-level wrapping LB policy without 1206 // waiting for the channel to become READY, there is a possibility that we 1207 // might not see the READY state in there. And if that happens, we will 1208 // see two extra states in the last check made in the test, and thereby 1209 // the test would fail. Waiting for the channel to become READY here 1210 // ensures that the test does not flake because of this rare sequence of 1211 // events. 1212 testutils.AwaitState(ctx, t, cc, connectivity.Ready) 1213 1214 // Cache the state changes seen up to this point. 1215 states0 := ccWrapper.getStates() 1216 1217 // Push an updated service config. As mentioned earlier, the previous config 1218 // updates on the child policies did not happen in the context of a config 1219 // update on the parent. Hence, this update is required to force the 1220 // scenario which we are interesting in testing here, i.e child policies get 1221 // config updates as part of the parent policy getting its config update. 1222 scJSON = fmt.Sprintf(` 1223 { 1224 "loadBalancingConfig": [ 1225 { 1226 "%s": { 1227 "routeLookupConfig": { 1228 "grpcKeybuilders": [{ 1229 "names": [ 1230 {"service": "grpc.testing.TestService"}, 1231 {"service": "grpc.health.v1.Health"} 1232 ] 1233 }], 1234 "lookupService": "%s", 1235 "cacheSizeBytes": 1000 1236 }, 1237 "childPolicy": [{"%s": {}}], 1238 "childPolicyConfigTargetFieldName": "Backend" 1239 } 1240 } 1241 ] 1242 }`, topLevelBalancerName, rlsServer.Address, childPolicyName) 1243 sc = internal.ParseServiceConfig.(func(string) *serviceconfig.ParseResult)(scJSON) 1244 r.UpdateState(resolver.State{ServiceConfig: sc}) 1245 1246 // Wait for the clientconn update to be processed by the RLS LB policy. 1247 select { 1248 case <-ctx.Done(): 1249 case <-clientConnUpdateDone: 1250 } 1251 1252 // Even though the child policies used in this test make multiple calls to 1253 // UpdateState as part of handling their configs, we expect the RLS policy 1254 // to inhibit picker updates during this time frame, and send a single 1255 // picker once the config update is completely handled. 1256 states1 := ccWrapper.getStates() 1257 if len(states1) != len(states0)+1 { 1258 t.Fatalf("more than one state update seen. before %v, after %v", states0, states1) 1259 } 1260 }