@@ -29,6 +29,7 @@ import (
29
29
"google.golang.org/grpc/balancer"
30
30
"google.golang.org/grpc/balancer/roundrobin"
31
31
"google.golang.org/grpc/connectivity"
32
+ "google.golang.org/grpc/internal/balancer/stub"
32
33
"google.golang.org/grpc/internal/hierarchy"
33
34
"google.golang.org/grpc/resolver"
34
35
"google.golang.org/grpc/serviceconfig"
@@ -263,3 +264,63 @@ func subConnFromPicker(p balancer.Picker) func() balancer.SubConn {
263
264
return scst .SubConn
264
265
}
265
266
}
267
+
268
+ const initIdleBalancerName = "test-init-Idle-balancer"
269
+
270
+ var errTestInitIdle = fmt .Errorf ("init Idle balancer error 0" )
271
+
272
+ func init () {
273
+ stub .Register (initIdleBalancerName , stub.BalancerFuncs {
274
+ UpdateClientConnState : func (bd * stub.BalancerData , opts balancer.ClientConnState ) error {
275
+ bd .ClientConn .NewSubConn (opts .ResolverState .Addresses , balancer.NewSubConnOptions {})
276
+ return nil
277
+ },
278
+ UpdateSubConnState : func (bd * stub.BalancerData , sc balancer.SubConn , state balancer.SubConnState ) {
279
+ err := fmt .Errorf ("wrong picker error" )
280
+ if state .ConnectivityState == connectivity .Idle {
281
+ err = errTestInitIdle
282
+ }
283
+ bd .ClientConn .UpdateState (balancer.State {
284
+ ConnectivityState : state .ConnectivityState ,
285
+ Picker : & testutils.TestConstPicker {Err : err },
286
+ })
287
+ },
288
+ })
289
+ }
290
+
291
+ // TestInitialIdle covers the case that if the child reports Idle, the overall
292
+ // state will be Idle.
293
+ func TestInitialIdle (t * testing.T ) {
294
+ cc := testutils .NewTestClientConn (t )
295
+ wtb := wtbBuilder .Build (cc , balancer.BuildOptions {})
296
+
297
+ // Start with "cluster_1: round_robin".
298
+ config1 , err := wtbParser .ParseConfig ([]byte (`{"targets":{"cluster_1":{"weight":1,"childPolicy":[{"test-init-Idle-balancer":""}]}}}` ))
299
+ if err != nil {
300
+ t .Fatalf ("failed to parse balancer config: %v" , err )
301
+ }
302
+
303
+ // Send the config, and an address with hierarchy path ["cluster_1"].
304
+ wantAddrs := []resolver.Address {
305
+ {Addr : testBackendAddrStrs [0 ], Attributes : nil },
306
+ }
307
+ if err := wtb .UpdateClientConnState (balancer.ClientConnState {
308
+ ResolverState : resolver.State {Addresses : []resolver.Address {
309
+ hierarchy .Set (wantAddrs [0 ], []string {"cds:cluster_1" }),
310
+ }},
311
+ BalancerConfig : config1 ,
312
+ }); err != nil {
313
+ t .Fatalf ("failed to update ClientConn state: %v" , err )
314
+ }
315
+
316
+ // Verify that a subconn is created with the address, and the hierarchy path
317
+ // in the address is cleared.
318
+ for range wantAddrs {
319
+ sc := <- cc .NewSubConnCh
320
+ wtb .UpdateSubConnState (sc , balancer.SubConnState {ConnectivityState : connectivity .Idle })
321
+ }
322
+
323
+ if state1 := <- cc .NewStateCh ; state1 != connectivity .Idle {
324
+ t .Fatalf ("Received aggregated state: %v, want Idle" , state1 )
325
+ }
326
+ }
0 commit comments