google.golang.org/grpc@v1.62.1/channelz/service/service_test.go (about)

     1  /*
     2   *
     3   * Copyright 2018 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 service
    20  
    21  import (
    22  	"context"
    23  	"fmt"
    24  	"net"
    25  	"strconv"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/golang/protobuf/proto"
    31  	"github.com/golang/protobuf/ptypes"
    32  	"github.com/google/go-cmp/cmp"
    33  	"google.golang.org/grpc/connectivity"
    34  	"google.golang.org/grpc/credentials"
    35  	"google.golang.org/grpc/internal/channelz"
    36  	"google.golang.org/grpc/internal/grpctest"
    37  	"google.golang.org/protobuf/testing/protocmp"
    38  
    39  	channelzpb "google.golang.org/grpc/channelz/grpc_channelz_v1"
    40  )
    41  
    42  func init() {
    43  	channelz.TurnOn()
    44  }
    45  
    46  type s struct {
    47  	grpctest.Tester
    48  }
    49  
    50  func Test(t *testing.T) {
    51  	grpctest.RunSubTests(t, s{})
    52  }
    53  
    54  type protoToSocketOptFunc func([]*channelzpb.SocketOption) *channelz.SocketOptionData
    55  
    56  // protoToSocketOpt is used in function socketProtoToStruct to extract socket option
    57  // data from unmarshaled proto message.
    58  // It is only defined under linux environment on x86 architecture.
    59  var protoToSocketOpt protoToSocketOptFunc
    60  
    61  const defaultTestTimeout = 10 * time.Second
    62  
    63  type dummyChannel struct {
    64  	state                    connectivity.State
    65  	target                   string
    66  	callsStarted             int64
    67  	callsSucceeded           int64
    68  	callsFailed              int64
    69  	lastCallStartedTimestamp time.Time
    70  }
    71  
    72  func (d *dummyChannel) ChannelzMetric() *channelz.ChannelInternalMetric {
    73  	return &channelz.ChannelInternalMetric{
    74  		State:                    d.state,
    75  		Target:                   d.target,
    76  		CallsStarted:             d.callsStarted,
    77  		CallsSucceeded:           d.callsSucceeded,
    78  		CallsFailed:              d.callsFailed,
    79  		LastCallStartedTimestamp: d.lastCallStartedTimestamp,
    80  	}
    81  }
    82  
    83  type dummyServer struct {
    84  	callsStarted             int64
    85  	callsSucceeded           int64
    86  	callsFailed              int64
    87  	lastCallStartedTimestamp time.Time
    88  }
    89  
    90  func (d *dummyServer) ChannelzMetric() *channelz.ServerInternalMetric {
    91  	return &channelz.ServerInternalMetric{
    92  		CallsStarted:             d.callsStarted,
    93  		CallsSucceeded:           d.callsSucceeded,
    94  		CallsFailed:              d.callsFailed,
    95  		LastCallStartedTimestamp: d.lastCallStartedTimestamp,
    96  	}
    97  }
    98  
    99  type dummySocket struct {
   100  	streamsStarted                   int64
   101  	streamsSucceeded                 int64
   102  	streamsFailed                    int64
   103  	messagesSent                     int64
   104  	messagesReceived                 int64
   105  	keepAlivesSent                   int64
   106  	lastLocalStreamCreatedTimestamp  time.Time
   107  	lastRemoteStreamCreatedTimestamp time.Time
   108  	lastMessageSentTimestamp         time.Time
   109  	lastMessageReceivedTimestamp     time.Time
   110  	localFlowControlWindow           int64
   111  	remoteFlowControlWindow          int64
   112  	socketOptions                    *channelz.SocketOptionData
   113  	localAddr                        net.Addr
   114  	remoteAddr                       net.Addr
   115  	security                         credentials.ChannelzSecurityValue
   116  	remoteName                       string
   117  }
   118  
   119  func (d *dummySocket) ChannelzMetric() *channelz.SocketInternalMetric {
   120  	return &channelz.SocketInternalMetric{
   121  		StreamsStarted:                   d.streamsStarted,
   122  		StreamsSucceeded:                 d.streamsSucceeded,
   123  		StreamsFailed:                    d.streamsFailed,
   124  		MessagesSent:                     d.messagesSent,
   125  		MessagesReceived:                 d.messagesReceived,
   126  		KeepAlivesSent:                   d.keepAlivesSent,
   127  		LastLocalStreamCreatedTimestamp:  d.lastLocalStreamCreatedTimestamp,
   128  		LastRemoteStreamCreatedTimestamp: d.lastRemoteStreamCreatedTimestamp,
   129  		LastMessageSentTimestamp:         d.lastMessageSentTimestamp,
   130  		LastMessageReceivedTimestamp:     d.lastMessageReceivedTimestamp,
   131  		LocalFlowControlWindow:           d.localFlowControlWindow,
   132  		RemoteFlowControlWindow:          d.remoteFlowControlWindow,
   133  		SocketOptions:                    d.socketOptions,
   134  		LocalAddr:                        d.localAddr,
   135  		RemoteAddr:                       d.remoteAddr,
   136  		Security:                         d.security,
   137  		RemoteName:                       d.remoteName,
   138  	}
   139  }
   140  
   141  func channelProtoToStruct(c *channelzpb.Channel) (*dummyChannel, error) {
   142  	dc := &dummyChannel{}
   143  	pdata := c.GetData()
   144  	switch pdata.GetState().GetState() {
   145  	case channelzpb.ChannelConnectivityState_UNKNOWN:
   146  		// TODO: what should we set here?
   147  	case channelzpb.ChannelConnectivityState_IDLE:
   148  		dc.state = connectivity.Idle
   149  	case channelzpb.ChannelConnectivityState_CONNECTING:
   150  		dc.state = connectivity.Connecting
   151  	case channelzpb.ChannelConnectivityState_READY:
   152  		dc.state = connectivity.Ready
   153  	case channelzpb.ChannelConnectivityState_TRANSIENT_FAILURE:
   154  		dc.state = connectivity.TransientFailure
   155  	case channelzpb.ChannelConnectivityState_SHUTDOWN:
   156  		dc.state = connectivity.Shutdown
   157  	}
   158  	dc.target = pdata.GetTarget()
   159  	dc.callsStarted = pdata.CallsStarted
   160  	dc.callsSucceeded = pdata.CallsSucceeded
   161  	dc.callsFailed = pdata.CallsFailed
   162  	if err := pdata.GetLastCallStartedTimestamp().CheckValid(); err != nil {
   163  		return nil, err
   164  	}
   165  	dc.lastCallStartedTimestamp = pdata.GetLastCallStartedTimestamp().AsTime()
   166  	return dc, nil
   167  }
   168  
   169  func serverProtoToStruct(s *channelzpb.Server) (*dummyServer, error) {
   170  	ds := &dummyServer{}
   171  	pdata := s.GetData()
   172  	ds.callsStarted = pdata.CallsStarted
   173  	ds.callsSucceeded = pdata.CallsSucceeded
   174  	ds.callsFailed = pdata.CallsFailed
   175  	if err := pdata.GetLastCallStartedTimestamp().CheckValid(); err != nil {
   176  		return nil, err
   177  	}
   178  	ds.lastCallStartedTimestamp = pdata.GetLastCallStartedTimestamp().AsTime()
   179  	return ds, nil
   180  }
   181  
   182  func socketProtoToStruct(s *channelzpb.Socket) (*dummySocket, error) {
   183  	ds := &dummySocket{}
   184  	pdata := s.GetData()
   185  	ds.streamsStarted = pdata.GetStreamsStarted()
   186  	ds.streamsSucceeded = pdata.GetStreamsSucceeded()
   187  	ds.streamsFailed = pdata.GetStreamsFailed()
   188  	ds.messagesSent = pdata.GetMessagesSent()
   189  	ds.messagesReceived = pdata.GetMessagesReceived()
   190  	ds.keepAlivesSent = pdata.GetKeepAlivesSent()
   191  	if err := pdata.GetLastLocalStreamCreatedTimestamp().CheckValid(); err != nil {
   192  		return nil, err
   193  	}
   194  	ds.lastLocalStreamCreatedTimestamp = pdata.GetLastLocalStreamCreatedTimestamp().AsTime()
   195  	if err := pdata.GetLastRemoteStreamCreatedTimestamp().CheckValid(); err != nil {
   196  		return nil, err
   197  	}
   198  	ds.lastRemoteStreamCreatedTimestamp = pdata.GetLastRemoteStreamCreatedTimestamp().AsTime()
   199  	if err := pdata.GetLastMessageSentTimestamp().CheckValid(); err != nil {
   200  		return nil, err
   201  	}
   202  	ds.lastMessageSentTimestamp = pdata.GetLastMessageSentTimestamp().AsTime()
   203  	if err := pdata.GetLastMessageReceivedTimestamp().CheckValid(); err != nil {
   204  		return nil, err
   205  	}
   206  	ds.lastMessageReceivedTimestamp = pdata.GetLastMessageReceivedTimestamp().AsTime()
   207  	if v := pdata.GetLocalFlowControlWindow(); v != nil {
   208  		ds.localFlowControlWindow = v.Value
   209  	}
   210  	if v := pdata.GetRemoteFlowControlWindow(); v != nil {
   211  		ds.remoteFlowControlWindow = v.Value
   212  	}
   213  	if v := pdata.GetOption(); v != nil && protoToSocketOpt != nil {
   214  		ds.socketOptions = protoToSocketOpt(v)
   215  	}
   216  	if v := s.GetSecurity(); v != nil {
   217  		ds.security = protoToSecurity(v)
   218  	}
   219  	if local := s.GetLocal(); local != nil {
   220  		ds.localAddr = protoToAddr(local)
   221  	}
   222  	if remote := s.GetRemote(); remote != nil {
   223  		ds.remoteAddr = protoToAddr(remote)
   224  	}
   225  	ds.remoteName = s.GetRemoteName()
   226  	return ds, nil
   227  }
   228  
   229  func protoToSecurity(protoSecurity *channelzpb.Security) credentials.ChannelzSecurityValue {
   230  	switch v := protoSecurity.Model.(type) {
   231  	case *channelzpb.Security_Tls_:
   232  		return &credentials.TLSChannelzSecurityValue{StandardName: v.Tls.GetStandardName(), LocalCertificate: v.Tls.GetLocalCertificate(), RemoteCertificate: v.Tls.GetRemoteCertificate()}
   233  	case *channelzpb.Security_Other:
   234  		sv := &credentials.OtherChannelzSecurityValue{Name: v.Other.GetName()}
   235  		var x ptypes.DynamicAny
   236  		if err := ptypes.UnmarshalAny(v.Other.GetValue(), &x); err == nil {
   237  			sv.Value = x.Message
   238  		}
   239  		return sv
   240  	}
   241  	return nil
   242  }
   243  
   244  func protoToAddr(a *channelzpb.Address) net.Addr {
   245  	switch v := a.Address.(type) {
   246  	case *channelzpb.Address_TcpipAddress:
   247  		if port := v.TcpipAddress.GetPort(); port != 0 {
   248  			return &net.TCPAddr{IP: v.TcpipAddress.GetIpAddress(), Port: int(port)}
   249  		}
   250  		return &net.IPAddr{IP: v.TcpipAddress.GetIpAddress()}
   251  	case *channelzpb.Address_UdsAddress_:
   252  		return &net.UnixAddr{Name: v.UdsAddress.GetFilename(), Net: "unix"}
   253  	case *channelzpb.Address_OtherAddress_:
   254  		// TODO:
   255  	}
   256  	return nil
   257  }
   258  
   259  func convertSocketRefSliceToMap(sktRefs []*channelzpb.SocketRef) map[int64]string {
   260  	m := make(map[int64]string)
   261  	for _, sr := range sktRefs {
   262  		m[sr.SocketId] = sr.Name
   263  	}
   264  	return m
   265  }
   266  
   267  type OtherSecurityValue struct {
   268  	LocalCertificate  []byte `protobuf:"bytes,1,opt,name=local_certificate,json=localCertificate,proto3" json:"local_certificate,omitempty"`
   269  	RemoteCertificate []byte `protobuf:"bytes,2,opt,name=remote_certificate,json=remoteCertificate,proto3" json:"remote_certificate,omitempty"`
   270  }
   271  
   272  func (m *OtherSecurityValue) Reset()         { *m = OtherSecurityValue{} }
   273  func (m *OtherSecurityValue) String() string { return proto.CompactTextString(m) }
   274  func (*OtherSecurityValue) ProtoMessage()    {}
   275  
   276  func init() {
   277  	// Ad-hoc registering the proto type here to facilitate UnmarshalAny of OtherSecurityValue.
   278  	proto.RegisterType((*OtherSecurityValue)(nil), "grpc.credentials.OtherChannelzSecurityValue")
   279  }
   280  
   281  func (s) TestGetTopChannels(t *testing.T) {
   282  	tcs := []*dummyChannel{
   283  		{
   284  			state:                    connectivity.Connecting,
   285  			target:                   "test.channelz:1234",
   286  			callsStarted:             6,
   287  			callsSucceeded:           2,
   288  			callsFailed:              3,
   289  			lastCallStartedTimestamp: time.Now().UTC(),
   290  		},
   291  		{
   292  			state:                    connectivity.Connecting,
   293  			target:                   "test.channelz:1234",
   294  			callsStarted:             1,
   295  			callsSucceeded:           2,
   296  			callsFailed:              3,
   297  			lastCallStartedTimestamp: time.Now().UTC(),
   298  		},
   299  		{
   300  			state:          connectivity.Shutdown,
   301  			target:         "test.channelz:8888",
   302  			callsStarted:   0,
   303  			callsSucceeded: 0,
   304  			callsFailed:    0,
   305  		},
   306  		{},
   307  	}
   308  
   309  	for _, c := range tcs {
   310  		id := channelz.RegisterChannel(c, nil, "")
   311  		defer channelz.RemoveEntry(id)
   312  	}
   313  	s := newCZServer()
   314  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   315  	defer cancel()
   316  	resp, _ := s.GetTopChannels(ctx, &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
   317  	if !resp.GetEnd() {
   318  		t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
   319  	}
   320  	for i, c := range resp.GetChannel() {
   321  		channel, err := channelProtoToStruct(c)
   322  		if err != nil {
   323  			t.Fatal(err)
   324  		}
   325  		if diff := cmp.Diff(tcs[i], channel, protocmp.Transform(), cmp.AllowUnexported(dummyChannel{})); diff != "" {
   326  			t.Fatalf("unexpected channel, diff (-want +got):\n%s", diff)
   327  		}
   328  	}
   329  	for i := 0; i < 50; i++ {
   330  		id := channelz.RegisterChannel(tcs[0], nil, "")
   331  		defer channelz.RemoveEntry(id)
   332  	}
   333  	resp, _ = s.GetTopChannels(ctx, &channelzpb.GetTopChannelsRequest{StartChannelId: 0})
   334  	if resp.GetEnd() {
   335  		t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
   336  	}
   337  }
   338  
   339  func (s) TestGetServers(t *testing.T) {
   340  	ss := []*dummyServer{
   341  		{
   342  			callsStarted:             6,
   343  			callsSucceeded:           2,
   344  			callsFailed:              3,
   345  			lastCallStartedTimestamp: time.Now().UTC(),
   346  		},
   347  		{
   348  			callsStarted:             1,
   349  			callsSucceeded:           2,
   350  			callsFailed:              3,
   351  			lastCallStartedTimestamp: time.Now().UTC(),
   352  		},
   353  		{
   354  			callsStarted:             1,
   355  			callsSucceeded:           0,
   356  			callsFailed:              0,
   357  			lastCallStartedTimestamp: time.Now().UTC(),
   358  		},
   359  	}
   360  
   361  	for _, s := range ss {
   362  		id := channelz.RegisterServer(s, "")
   363  		defer channelz.RemoveEntry(id)
   364  	}
   365  	svr := newCZServer()
   366  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   367  	defer cancel()
   368  	resp, _ := svr.GetServers(ctx, &channelzpb.GetServersRequest{StartServerId: 0})
   369  	if !resp.GetEnd() {
   370  		t.Fatalf("resp.GetEnd() want true, got %v", resp.GetEnd())
   371  	}
   372  	for i, s := range resp.GetServer() {
   373  		server, err := serverProtoToStruct(s)
   374  		if err != nil {
   375  			t.Fatal(err)
   376  		}
   377  		if diff := cmp.Diff(ss[i], server, protocmp.Transform(), cmp.AllowUnexported(dummyServer{})); diff != "" {
   378  			t.Fatalf("unexpected server, diff (-want +got):\n%s", diff)
   379  		}
   380  	}
   381  	for i := 0; i < 50; i++ {
   382  		id := channelz.RegisterServer(ss[0], "")
   383  		defer channelz.RemoveEntry(id)
   384  	}
   385  	resp, _ = svr.GetServers(ctx, &channelzpb.GetServersRequest{StartServerId: 0})
   386  	if resp.GetEnd() {
   387  		t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
   388  	}
   389  }
   390  
   391  func (s) TestGetServerSockets(t *testing.T) {
   392  	svrID := channelz.RegisterServer(&dummyServer{}, "")
   393  	defer channelz.RemoveEntry(svrID)
   394  	refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
   395  	ids := make([]*channelz.Identifier, 3)
   396  	ids[0], _ = channelz.RegisterListenSocket(&dummySocket{}, svrID, refNames[0])
   397  	ids[1], _ = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[1])
   398  	ids[2], _ = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[2])
   399  	for _, id := range ids {
   400  		defer channelz.RemoveEntry(id)
   401  	}
   402  	svr := newCZServer()
   403  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   404  	defer cancel()
   405  	resp, _ := svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.Int(), StartSocketId: 0})
   406  	if !resp.GetEnd() {
   407  		t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
   408  	}
   409  	// GetServerSockets only return normal sockets.
   410  	want := map[int64]string{
   411  		ids[1].Int(): refNames[1],
   412  		ids[2].Int(): refNames[2],
   413  	}
   414  	if !cmp.Equal(convertSocketRefSliceToMap(resp.GetSocketRef()), want) {
   415  		t.Fatalf("GetServerSockets want: %#v, got: %#v", want, resp.GetSocketRef())
   416  	}
   417  
   418  	for i := 0; i < 50; i++ {
   419  		id, _ := channelz.RegisterNormalSocket(&dummySocket{}, svrID, "")
   420  		defer channelz.RemoveEntry(id)
   421  	}
   422  	resp, _ = svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.Int(), StartSocketId: 0})
   423  	if resp.GetEnd() {
   424  		t.Fatalf("resp.GetEnd() want false, got %v", resp.GetEnd())
   425  	}
   426  }
   427  
   428  // This test makes a GetServerSockets with a non-zero start ID, and expect only
   429  // sockets with ID >= the given start ID.
   430  func (s) TestGetServerSocketsNonZeroStartID(t *testing.T) {
   431  	svrID := channelz.RegisterServer(&dummyServer{}, "")
   432  	defer channelz.RemoveEntry(svrID)
   433  	refNames := []string{"listen socket 1", "normal socket 1", "normal socket 2"}
   434  	ids := make([]*channelz.Identifier, 3)
   435  	ids[0], _ = channelz.RegisterListenSocket(&dummySocket{}, svrID, refNames[0])
   436  	ids[1], _ = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[1])
   437  	ids[2], _ = channelz.RegisterNormalSocket(&dummySocket{}, svrID, refNames[2])
   438  	for _, id := range ids {
   439  		defer channelz.RemoveEntry(id)
   440  	}
   441  	svr := newCZServer()
   442  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   443  	defer cancel()
   444  	// Make GetServerSockets with startID = ids[1]+1, so socket-1 won't be
   445  	// included in the response.
   446  	resp, _ := svr.GetServerSockets(ctx, &channelzpb.GetServerSocketsRequest{ServerId: svrID.Int(), StartSocketId: ids[1].Int() + 1})
   447  	if !resp.GetEnd() {
   448  		t.Fatalf("resp.GetEnd() want: true, got: %v", resp.GetEnd())
   449  	}
   450  	// GetServerSockets only return normal socket-2, socket-1 should be
   451  	// filtered by start ID.
   452  	want := map[int64]string{
   453  		ids[2].Int(): refNames[2],
   454  	}
   455  	if !cmp.Equal(convertSocketRefSliceToMap(resp.GetSocketRef()), want) {
   456  		t.Fatalf("GetServerSockets want: %#v, got: %#v", want, resp.GetSocketRef())
   457  	}
   458  }
   459  
   460  func (s) TestGetChannel(t *testing.T) {
   461  	refNames := []string{"top channel 1", "nested channel 1", "sub channel 2", "nested channel 3"}
   462  	ids := make([]*channelz.Identifier, 4)
   463  	ids[0] = channelz.RegisterChannel(&dummyChannel{}, nil, refNames[0])
   464  	channelz.AddTraceEvent(logger, ids[0], 0, &channelz.TraceEventDesc{
   465  		Desc:     "Channel Created",
   466  		Severity: channelz.CtInfo,
   467  	})
   468  
   469  	ids[1] = channelz.RegisterChannel(&dummyChannel{}, ids[0], refNames[1])
   470  	channelz.AddTraceEvent(logger, ids[1], 0, &channelz.TraceEventDesc{
   471  		Desc:     "Channel Created",
   472  		Severity: channelz.CtInfo,
   473  		Parent: &channelz.TraceEventDesc{
   474  			Desc:     fmt.Sprintf("Nested Channel(id:%d) created", ids[1].Int()),
   475  			Severity: channelz.CtInfo,
   476  		},
   477  	})
   478  
   479  	var err error
   480  	ids[2], err = channelz.RegisterSubChannel(&dummyChannel{}, ids[0], refNames[2])
   481  	if err != nil {
   482  		t.Fatalf("channelz.RegisterSubChannel() failed: %v", err)
   483  	}
   484  	channelz.AddTraceEvent(logger, ids[2], 0, &channelz.TraceEventDesc{
   485  		Desc:     "SubChannel Created",
   486  		Severity: channelz.CtInfo,
   487  		Parent: &channelz.TraceEventDesc{
   488  			Desc:     fmt.Sprintf("SubChannel(id:%d) created", ids[2].Int()),
   489  			Severity: channelz.CtInfo,
   490  		},
   491  	})
   492  
   493  	ids[3] = channelz.RegisterChannel(&dummyChannel{}, ids[1], refNames[3])
   494  	channelz.AddTraceEvent(logger, ids[3], 0, &channelz.TraceEventDesc{
   495  		Desc:     "Channel Created",
   496  		Severity: channelz.CtInfo,
   497  		Parent: &channelz.TraceEventDesc{
   498  			Desc:     fmt.Sprintf("Nested Channel(id:%d) created", ids[3].Int()),
   499  			Severity: channelz.CtInfo,
   500  		},
   501  	})
   502  	channelz.AddTraceEvent(logger, ids[0], 0, &channelz.TraceEventDesc{
   503  		Desc:     fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready),
   504  		Severity: channelz.CtInfo,
   505  	})
   506  	channelz.AddTraceEvent(logger, ids[0], 0, &channelz.TraceEventDesc{
   507  		Desc:     "Resolver returns an empty address list",
   508  		Severity: channelz.CtWarning,
   509  	})
   510  
   511  	for _, id := range ids {
   512  		defer channelz.RemoveEntry(id)
   513  	}
   514  
   515  	svr := newCZServer()
   516  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   517  	defer cancel()
   518  	resp, _ := svr.GetChannel(ctx, &channelzpb.GetChannelRequest{ChannelId: ids[0].Int()})
   519  	metrics := resp.GetChannel()
   520  	subChans := metrics.GetSubchannelRef()
   521  	if len(subChans) != 1 || subChans[0].GetName() != refNames[2] || subChans[0].GetSubchannelId() != ids[2].Int() {
   522  		t.Fatalf("metrics.GetSubChannelRef() want %#v, got %#v", []*channelzpb.SubchannelRef{{SubchannelId: ids[2].Int(), Name: refNames[2]}}, subChans)
   523  	}
   524  	nestedChans := metrics.GetChannelRef()
   525  	if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[1] || nestedChans[0].GetChannelId() != ids[1].Int() {
   526  		t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: ids[1].Int(), Name: refNames[1]}}, nestedChans)
   527  	}
   528  	trace := metrics.GetData().GetTrace()
   529  	want := []struct {
   530  		desc     string
   531  		severity channelzpb.ChannelTraceEvent_Severity
   532  		childID  int64
   533  		childRef string
   534  	}{
   535  		{desc: "Channel Created", severity: channelzpb.ChannelTraceEvent_CT_INFO},
   536  		{desc: fmt.Sprintf("Nested Channel(id:%d) created", ids[1].Int()), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: ids[1].Int(), childRef: refNames[1]},
   537  		{desc: fmt.Sprintf("SubChannel(id:%d) created", ids[2].Int()), severity: channelzpb.ChannelTraceEvent_CT_INFO, childID: ids[2].Int(), childRef: refNames[2]},
   538  		{desc: fmt.Sprintf("Channel Connectivity change to %v", connectivity.Ready), severity: channelzpb.ChannelTraceEvent_CT_INFO},
   539  		{desc: "Resolver returns an empty address list", severity: channelzpb.ChannelTraceEvent_CT_WARNING},
   540  	}
   541  
   542  	for i, e := range trace.Events {
   543  		if !strings.Contains(e.GetDescription(), want[i].desc) {
   544  			t.Fatalf("trace: GetDescription want %#v, got %#v", want[i].desc, e.GetDescription())
   545  		}
   546  		if e.GetSeverity() != want[i].severity {
   547  			t.Fatalf("trace: GetSeverity want %#v, got %#v", want[i].severity, e.GetSeverity())
   548  		}
   549  		if want[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
   550  			t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
   551  		}
   552  		if e.GetChannelRef().GetChannelId() != want[i].childID || e.GetChannelRef().GetName() != want[i].childRef {
   553  			if e.GetSubchannelRef().GetSubchannelId() != want[i].childID || e.GetSubchannelRef().GetName() != want[i].childRef {
   554  				t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", want[i].childID, want[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
   555  			}
   556  		}
   557  	}
   558  	resp, _ = svr.GetChannel(ctx, &channelzpb.GetChannelRequest{ChannelId: ids[1].Int()})
   559  	metrics = resp.GetChannel()
   560  	nestedChans = metrics.GetChannelRef()
   561  	if len(nestedChans) != 1 || nestedChans[0].GetName() != refNames[3] || nestedChans[0].GetChannelId() != ids[3].Int() {
   562  		t.Fatalf("metrics.GetChannelRef() want %#v, got %#v", []*channelzpb.ChannelRef{{ChannelId: ids[3].Int(), Name: refNames[3]}}, nestedChans)
   563  	}
   564  }
   565  
   566  func (s) TestGetSubChannel(t *testing.T) {
   567  	var (
   568  		subchanCreated            = "SubChannel Created"
   569  		subchanConnectivityChange = fmt.Sprintf("Subchannel Connectivity change to %v", connectivity.Ready)
   570  		subChanPickNewAddress     = fmt.Sprintf("Subchannel picks a new address %q to connect", "0.0.0.0")
   571  	)
   572  
   573  	refNames := []string{"top channel 1", "sub channel 1", "socket 1", "socket 2"}
   574  	ids := make([]*channelz.Identifier, 4)
   575  	ids[0] = channelz.RegisterChannel(&dummyChannel{}, nil, refNames[0])
   576  	channelz.AddTraceEvent(logger, ids[0], 0, &channelz.TraceEventDesc{
   577  		Desc:     "Channel Created",
   578  		Severity: channelz.CtInfo,
   579  	})
   580  	var err error
   581  	ids[1], err = channelz.RegisterSubChannel(&dummyChannel{}, ids[0], refNames[1])
   582  	if err != nil {
   583  		t.Fatalf("channelz.RegisterSubChannel() failed: %v", err)
   584  	}
   585  	channelz.AddTraceEvent(logger, ids[1], 0, &channelz.TraceEventDesc{
   586  		Desc:     subchanCreated,
   587  		Severity: channelz.CtInfo,
   588  		Parent: &channelz.TraceEventDesc{
   589  			Desc:     fmt.Sprintf("Nested Channel(id:%d) created", ids[0].Int()),
   590  			Severity: channelz.CtInfo,
   591  		},
   592  	})
   593  	ids[2], _ = channelz.RegisterNormalSocket(&dummySocket{}, ids[1], refNames[2])
   594  	ids[3], _ = channelz.RegisterNormalSocket(&dummySocket{}, ids[1], refNames[3])
   595  	channelz.AddTraceEvent(logger, ids[1], 0, &channelz.TraceEventDesc{
   596  		Desc:     subchanConnectivityChange,
   597  		Severity: channelz.CtInfo,
   598  	})
   599  	channelz.AddTraceEvent(logger, ids[1], 0, &channelz.TraceEventDesc{
   600  		Desc:     subChanPickNewAddress,
   601  		Severity: channelz.CtInfo,
   602  	})
   603  	for _, id := range ids {
   604  		defer channelz.RemoveEntry(id)
   605  	}
   606  	svr := newCZServer()
   607  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   608  	defer cancel()
   609  	resp, _ := svr.GetSubchannel(ctx, &channelzpb.GetSubchannelRequest{SubchannelId: ids[1].Int()})
   610  	metrics := resp.GetSubchannel()
   611  	want := map[int64]string{
   612  		ids[2].Int(): refNames[2],
   613  		ids[3].Int(): refNames[3],
   614  	}
   615  	if !cmp.Equal(convertSocketRefSliceToMap(metrics.GetSocketRef()), want) {
   616  		t.Fatalf("metrics.GetSocketRef() want %#v: got: %#v", want, metrics.GetSocketRef())
   617  	}
   618  
   619  	trace := metrics.GetData().GetTrace()
   620  	wantTrace := []struct {
   621  		desc     string
   622  		severity channelzpb.ChannelTraceEvent_Severity
   623  		childID  int64
   624  		childRef string
   625  	}{
   626  		{desc: subchanCreated, severity: channelzpb.ChannelTraceEvent_CT_INFO},
   627  		{desc: subchanConnectivityChange, severity: channelzpb.ChannelTraceEvent_CT_INFO},
   628  		{desc: subChanPickNewAddress, severity: channelzpb.ChannelTraceEvent_CT_INFO},
   629  	}
   630  	for i, e := range trace.Events {
   631  		if e.GetDescription() != wantTrace[i].desc {
   632  			t.Fatalf("trace: GetDescription want %#v, got %#v", wantTrace[i].desc, e.GetDescription())
   633  		}
   634  		if e.GetSeverity() != wantTrace[i].severity {
   635  			t.Fatalf("trace: GetSeverity want %#v, got %#v", wantTrace[i].severity, e.GetSeverity())
   636  		}
   637  		if wantTrace[i].childID == 0 && (e.GetChannelRef() != nil || e.GetSubchannelRef() != nil) {
   638  			t.Fatalf("trace: GetChannelRef() should return nil, as there is no reference")
   639  		}
   640  		if e.GetChannelRef().GetChannelId() != wantTrace[i].childID || e.GetChannelRef().GetName() != wantTrace[i].childRef {
   641  			if e.GetSubchannelRef().GetSubchannelId() != wantTrace[i].childID || e.GetSubchannelRef().GetName() != wantTrace[i].childRef {
   642  				t.Fatalf("trace: GetChannelRef/GetSubchannelRef want (child ID: %d, child name: %q), got %#v and %#v", wantTrace[i].childID, wantTrace[i].childRef, e.GetChannelRef(), e.GetSubchannelRef())
   643  			}
   644  		}
   645  	}
   646  }
   647  
   648  func (s) TestGetSocket(t *testing.T) {
   649  	ss := []*dummySocket{
   650  		{
   651  			streamsStarted:                   10,
   652  			streamsSucceeded:                 2,
   653  			streamsFailed:                    3,
   654  			messagesSent:                     20,
   655  			messagesReceived:                 10,
   656  			keepAlivesSent:                   2,
   657  			lastLocalStreamCreatedTimestamp:  time.Now().UTC(),
   658  			lastRemoteStreamCreatedTimestamp: time.Now().UTC(),
   659  			lastMessageSentTimestamp:         time.Now().UTC(),
   660  			lastMessageReceivedTimestamp:     time.Now().UTC(),
   661  			localFlowControlWindow:           65536,
   662  			remoteFlowControlWindow:          1024,
   663  			localAddr:                        &net.TCPAddr{IP: net.ParseIP("1.0.0.1"), Port: 10001},
   664  			remoteAddr:                       &net.TCPAddr{IP: net.ParseIP("12.0.0.1"), Port: 10002},
   665  			remoteName:                       "remote.remote",
   666  		},
   667  		{
   668  			streamsStarted:                   10,
   669  			streamsSucceeded:                 2,
   670  			streamsFailed:                    3,
   671  			messagesSent:                     20,
   672  			messagesReceived:                 10,
   673  			keepAlivesSent:                   2,
   674  			lastRemoteStreamCreatedTimestamp: time.Now().UTC(),
   675  			lastMessageSentTimestamp:         time.Now().UTC(),
   676  			lastMessageReceivedTimestamp:     time.Now().UTC(),
   677  			localFlowControlWindow:           65536,
   678  			remoteFlowControlWindow:          1024,
   679  			localAddr:                        &net.UnixAddr{Name: "file.path", Net: "unix"},
   680  			remoteAddr:                       &net.UnixAddr{Name: "another.path", Net: "unix"},
   681  			remoteName:                       "remote.remote",
   682  		},
   683  		{
   684  			streamsStarted:                  5,
   685  			streamsSucceeded:                2,
   686  			streamsFailed:                   3,
   687  			messagesSent:                    20,
   688  			messagesReceived:                10,
   689  			keepAlivesSent:                  2,
   690  			lastLocalStreamCreatedTimestamp: time.Now().UTC(),
   691  			lastMessageSentTimestamp:        time.Now().UTC(),
   692  			lastMessageReceivedTimestamp:    time.Now().UTC(),
   693  			localFlowControlWindow:          65536,
   694  			remoteFlowControlWindow:         10240,
   695  			localAddr:                       &net.IPAddr{IP: net.ParseIP("1.0.0.1")},
   696  			remoteAddr:                      &net.IPAddr{IP: net.ParseIP("9.0.0.1")},
   697  			remoteName:                      "",
   698  		},
   699  		{
   700  			localAddr: &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 10001},
   701  		},
   702  		{
   703  			security: &credentials.TLSChannelzSecurityValue{
   704  				StandardName:      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
   705  				RemoteCertificate: []byte{48, 130, 2, 156, 48, 130, 2, 5, 160},
   706  			},
   707  		},
   708  		{
   709  			security: &credentials.OtherChannelzSecurityValue{
   710  				Name: "XXXX",
   711  			},
   712  		},
   713  		{
   714  			security: &credentials.OtherChannelzSecurityValue{
   715  				Name:  "YYYY",
   716  				Value: &OtherSecurityValue{LocalCertificate: []byte{1, 2, 3}, RemoteCertificate: []byte{4, 5, 6}},
   717  			},
   718  		},
   719  	}
   720  	svr := newCZServer()
   721  	ids := make([]*channelz.Identifier, len(ss))
   722  	svrID := channelz.RegisterServer(&dummyServer{}, "")
   723  	defer channelz.RemoveEntry(svrID)
   724  	for i, s := range ss {
   725  		ids[i], _ = channelz.RegisterNormalSocket(s, svrID, strconv.Itoa(i))
   726  		defer channelz.RemoveEntry(ids[i])
   727  	}
   728  	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   729  	defer cancel()
   730  	for i, s := range ss {
   731  		resp, _ := svr.GetSocket(ctx, &channelzpb.GetSocketRequest{SocketId: ids[i].Int()})
   732  		got, want := resp.GetSocket().GetRef(), &channelzpb.SocketRef{SocketId: ids[i].Int(), Name: strconv.Itoa(i)}
   733  		if !cmp.Equal(got, want, protocmp.Transform()) {
   734  			t.Fatalf("resp.GetSocket() returned metrics.GetRef() = %#v, want %#v", got, want)
   735  		}
   736  		socket, err := socketProtoToStruct(resp.GetSocket())
   737  		if err != nil {
   738  			t.Fatal(err)
   739  		}
   740  		if diff := cmp.Diff(s, socket, protocmp.Transform(), cmp.AllowUnexported(dummySocket{})); diff != "" {
   741  			t.Fatalf("unexpected socket, diff (-want +got):\n%s", diff)
   742  		}
   743  	}
   744  }