diff --git a/clientconn.go b/clientconn.go index 91508fb4e48..524159a985a 100644 --- a/clientconn.go +++ b/clientconn.go @@ -1204,6 +1204,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) close(ac.stateChan) ac.stateChan = make(chan struct{}) ac.state = s + ac.channelz.ChannelMetrics.State.Store(&s) if lastErr == nil { channelz.Infof(logger, ac.channelz, "Subchannel Connectivity change to %v", s) } else { diff --git a/test/channelz_test.go b/test/channelz_test.go index e223c5cce1e..5e883d5342d 100644 --- a/test/channelz_test.go +++ b/test/channelz_test.go @@ -131,6 +131,43 @@ func (s) TestCZGetChannel(t *testing.T) { } } +func (s) TestCZGetSubChannel(t *testing.T) { + e := tcpClearRREnv + e.balancer = "" + te := newTest(t, e) + te.startServer(&testServer{security: e.security}) + r := manual.NewBuilderWithScheme("whatever") + addrs := []resolver.Address{{Addr: te.srvAddr}} + r.InitialState(resolver.State{Addresses: addrs}) + te.resolverScheme = r.Scheme() + te.clientConn(grpc.WithResolvers(r)) + defer te.tearDown() + if err := verifyResultWithDelay(func() (bool, error) { + tcs, _ := channelz.GetTopChannels(0, 0) + if len(tcs) != 1 { + return false, fmt.Errorf("there should only be one top channel, not %d", len(tcs)) + } + scs := tcs[0].SubChans() + if len(scs) != 1 { + return false, fmt.Errorf("there should be one subchannel, not %d", len(scs)) + } + var scid int64 + for scid = range scs { + } + sc := channelz.GetSubChannel(scid) + if sc == nil { + return false, fmt.Errorf("subchannel with id %v is nil", scid) + } + state := sc.ChannelMetrics.State.Load() + if state == nil || *state != connectivity.Ready { + return false, fmt.Errorf("Got subchannel state=%v; want %q", state, connectivity.Ready) + } + return true, nil + }); err != nil { + t.Fatal(err) + } +} + func (s) TestCZGetServer(t *testing.T) { e := tcpClearRREnv te := newTest(t, e)