TestUpdateStatePauses tests the scenario where a config update received by the RLS LB policy results in multiple UpdateState calls from the child policies. This test verifies that picker updates are paused when the config update is being processed by RLS LB policy and its child policies. The test u
(t *testing.T)
| 1316 | // UpdateState calls when handling an update from its parent in |
| 1317 | // UpdateClientConnState. |
| 1318 | func (s) TestUpdateStatePauses(t *testing.T) { |
| 1319 | // Override the hook to get notified when UpdateClientConnState is done. |
| 1320 | clientConnUpdateDone := make(chan struct{}, 1) |
| 1321 | origClientConnUpdateHook := clientConnUpdateHook |
| 1322 | clientConnUpdateHook = func() { clientConnUpdateDone <- struct{}{} } |
| 1323 | defer func() { clientConnUpdateHook = origClientConnUpdateHook }() |
| 1324 | |
| 1325 | // Register the top-level wrapping balancer which forwards calls to RLS. |
| 1326 | topLevelBalancerName := t.Name() + "top-level" |
| 1327 | var ccWrapper *testCCWrapper |
| 1328 | stub.Register(topLevelBalancerName, stub.BalancerFuncs{ |
| 1329 | Init: func(bd *stub.BalancerData) { |
| 1330 | ccWrapper = &testCCWrapper{ClientConn: bd.ClientConn} |
| 1331 | bd.ChildBalancer = balancer.Get(Name).Build(ccWrapper, bd.BuildOptions) |
| 1332 | }, |
| 1333 | ParseConfig: func(sc json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { |
| 1334 | parser := balancer.Get(Name).(balancer.ConfigParser) |
| 1335 | return parser.ParseConfig(sc) |
| 1336 | }, |
| 1337 | UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { |
| 1338 | return bd.ChildBalancer.UpdateClientConnState(ccs) |
| 1339 | }, |
| 1340 | Close: func(bd *stub.BalancerData) { |
| 1341 | bd.ChildBalancer.Close() |
| 1342 | }, |
| 1343 | }) |
| 1344 | |
| 1345 | // Register a child policy that wraps a pickfirst balancer and makes multiple calls |
| 1346 | // to UpdateState when handling a config update in UpdateClientConnState. When |
| 1347 | // this policy is used as a child policy of the RLS LB policy, it is expected |
| 1348 | // that the latter suppress these updates and push a single picker update on the |
| 1349 | // channel (after the config has been processed by all child policies). |
| 1350 | childPolicyName := t.Name() + "child" |
| 1351 | type childPolicyConfig struct { |
| 1352 | serviceconfig.LoadBalancingConfig |
| 1353 | Backend string // `json:"backend,omitempty"` |
| 1354 | } |
| 1355 | stub.Register(childPolicyName, stub.BalancerFuncs{ |
| 1356 | Init: func(bd *stub.BalancerData) { |
| 1357 | bd.ChildBalancer = balancer.Get(pickfirst.Name).Build(bd.ClientConn, bd.BuildOptions) |
| 1358 | }, |
| 1359 | Close: func(bd *stub.BalancerData) { |
| 1360 | bd.ChildBalancer.Close() |
| 1361 | }, |
| 1362 | ParseConfig: func(sc json.RawMessage) (serviceconfig.LoadBalancingConfig, error) { |
| 1363 | cfg := &childPolicyConfig{} |
| 1364 | if err := json.Unmarshal(sc, cfg); err != nil { |
| 1365 | return nil, err |
| 1366 | } |
| 1367 | return cfg, nil |
| 1368 | }, |
| 1369 | UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { |
| 1370 | bal := bd.ChildBalancer |
| 1371 | bd.ClientConn.UpdateState(balancer.State{ConnectivityState: connectivity.Idle, Picker: &testutils.TestConstPicker{Err: balancer.ErrNoSubConnAvailable}}) |
| 1372 | bd.ClientConn.UpdateState(balancer.State{ConnectivityState: connectivity.Connecting, Picker: &testutils.TestConstPicker{Err: balancer.ErrNoSubConnAvailable}}) |
| 1373 | |
| 1374 | cfg := ccs.BalancerConfig.(*childPolicyConfig) |
| 1375 | return bal.UpdateClientConnState(balancer.ClientConnState{ |
nothing calls this directly
no test coverage detected