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 }