TestPicker creates a lazy balancer under a stub balancer which block all calls to ExitIdle. This ensures the only way to trigger lazy to exit idle is through the picker. The test makes an RPC and ensures it succeeds.
(t *testing.T)
| 137 | // calls to ExitIdle. This ensures the only way to trigger lazy to exit idle is |
| 138 | // through the picker. The test makes an RPC and ensures it succeeds. |
| 139 | func (s) TestPicker(t *testing.T) { |
| 140 | backend := stubserver.StartTestService(t, nil) |
| 141 | defer backend.Stop() |
| 142 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 143 | defer cancel() |
| 144 | |
| 145 | bf := stub.BalancerFuncs{ |
| 146 | Init: func(bd *stub.BalancerData) { |
| 147 | bd.ChildBalancer = lazy.NewBalancer(bd.ClientConn, bd.BuildOptions, balancer.Get(pickfirst.Name).Build) |
| 148 | }, |
| 149 | ExitIdle: func(*stub.BalancerData) { |
| 150 | t.Log("Ignoring call to ExitIdle, calling the picker should make the lazy balancer exit IDLE state.") |
| 151 | }, |
| 152 | UpdateClientConnState: func(bd *stub.BalancerData, ccs balancer.ClientConnState) error { |
| 153 | return bd.ChildBalancer.UpdateClientConnState(ccs) |
| 154 | }, |
| 155 | Close: func(bd *stub.BalancerData) { |
| 156 | bd.ChildBalancer.Close() |
| 157 | }, |
| 158 | } |
| 159 | |
| 160 | name := strings.ReplaceAll(strings.ToLower(t.Name()), "/", "") |
| 161 | stub.Register(name, bf) |
| 162 | json := fmt.Sprintf(`{"loadBalancingConfig": [{%q: {}}]}`, name) |
| 163 | |
| 164 | opts := []grpc.DialOption{ |
| 165 | grpc.WithTransportCredentials(insecure.NewCredentials()), |
| 166 | grpc.WithDefaultServiceConfig(json), |
| 167 | } |
| 168 | cc, err := grpc.NewClient(backend.Address, opts...) |
| 169 | if err != nil { |
| 170 | t.Fatalf("grpc.NewClient(_) failed: %v", err) |
| 171 | } |
| 172 | defer cc.Close() |
| 173 | |
| 174 | // The channel should remain in IDLE as the ExitIdle calls are not |
| 175 | // propagated to the lazy balancer from the stub balancer. |
| 176 | cc.Connect() |
| 177 | shortCtx, shortCancel := context.WithTimeout(ctx, defaultTestShortTimeout) |
| 178 | defer shortCancel() |
| 179 | testutils.AwaitNoStateChange(shortCtx, t, cc, connectivity.Idle) |
| 180 | |
| 181 | // The picker from the lazy balancer should be send to the channel when the |
| 182 | // first resolver update is received by lazy. Making an RPC should trigger |
| 183 | // child creation. |
| 184 | client := testgrpc.NewTestServiceClient(cc) |
| 185 | if _, err := client.EmptyCall(ctx, &testpb.Empty{}); err != nil { |
| 186 | t.Errorf("client.EmptyCall() returned unexpected error: %v", err) |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | // Tests the scenario when a resolver produces a good state followed by a |
| 191 | // resolver error. The test verifies that the child balancer receives the good |
nothing calls this directly
no test coverage detected