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