1 /* 2 * Copyright 2018 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.services; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static io.grpc.InternalChannelz.id; 21 import static org.junit.Assert.assertEquals; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.when; 24 25 import com.google.common.base.Charsets; 26 import com.google.common.collect.ImmutableList; 27 import com.google.common.collect.ImmutableMap; 28 import com.google.protobuf.Any; 29 import com.google.protobuf.ByteString; 30 import com.google.protobuf.Int64Value; 31 import com.google.protobuf.Message; 32 import com.google.protobuf.util.Durations; 33 import com.google.protobuf.util.Timestamps; 34 import io.grpc.ConnectivityState; 35 import io.grpc.InternalChannelz; 36 import io.grpc.InternalChannelz.ChannelStats; 37 import io.grpc.InternalChannelz.ChannelTrace.Event; 38 import io.grpc.InternalChannelz.ChannelTrace.Event.Severity; 39 import io.grpc.InternalChannelz.RootChannelList; 40 import io.grpc.InternalChannelz.ServerList; 41 import io.grpc.InternalChannelz.ServerSocketsList; 42 import io.grpc.InternalChannelz.ServerStats; 43 import io.grpc.InternalChannelz.SocketOptions; 44 import io.grpc.InternalChannelz.SocketStats; 45 import io.grpc.InternalInstrumented; 46 import io.grpc.InternalWithLogId; 47 import io.grpc.channelz.v1.Address; 48 import io.grpc.channelz.v1.Address.OtherAddress; 49 import io.grpc.channelz.v1.Address.TcpIpAddress; 50 import io.grpc.channelz.v1.Address.UdsAddress; 51 import io.grpc.channelz.v1.Channel; 52 import io.grpc.channelz.v1.ChannelConnectivityState; 53 import io.grpc.channelz.v1.ChannelConnectivityState.State; 54 import io.grpc.channelz.v1.ChannelData; 55 import io.grpc.channelz.v1.ChannelRef; 56 import io.grpc.channelz.v1.ChannelTrace; 57 import io.grpc.channelz.v1.ChannelTraceEvent; 58 import io.grpc.channelz.v1.GetChannelRequest; 59 import io.grpc.channelz.v1.GetServerSocketsResponse; 60 import io.grpc.channelz.v1.GetServersResponse; 61 import io.grpc.channelz.v1.GetTopChannelsResponse; 62 import io.grpc.channelz.v1.Security; 63 import io.grpc.channelz.v1.Security.OtherSecurity; 64 import io.grpc.channelz.v1.Security.Tls; 65 import io.grpc.channelz.v1.Server; 66 import io.grpc.channelz.v1.ServerData; 67 import io.grpc.channelz.v1.ServerRef; 68 import io.grpc.channelz.v1.Socket; 69 import io.grpc.channelz.v1.SocketData; 70 import io.grpc.channelz.v1.SocketOption; 71 import io.grpc.channelz.v1.SocketOptionLinger; 72 import io.grpc.channelz.v1.SocketOptionTcpInfo; 73 import io.grpc.channelz.v1.SocketOptionTimeout; 74 import io.grpc.channelz.v1.SocketRef; 75 import io.grpc.channelz.v1.Subchannel; 76 import io.grpc.channelz.v1.SubchannelRef; 77 import io.grpc.services.ChannelzTestHelper.TestChannel; 78 import io.grpc.services.ChannelzTestHelper.TestListenSocket; 79 import io.grpc.services.ChannelzTestHelper.TestServer; 80 import io.grpc.services.ChannelzTestHelper.TestSocket; 81 import io.netty.channel.unix.DomainSocketAddress; 82 import java.net.Inet4Address; 83 import java.net.InetSocketAddress; 84 import java.net.SocketAddress; 85 import java.security.cert.Certificate; 86 import java.util.Arrays; 87 import java.util.Collections; 88 import java.util.Map.Entry; 89 import org.junit.Test; 90 import org.junit.runner.RunWith; 91 import org.junit.runners.JUnit4; 92 93 @RunWith(JUnit4.class) 94 public final class ChannelzProtoUtilTest { 95 96 private final TestChannel channel = new TestChannel(); 97 private final ChannelRef channelRef = ChannelRef 98 .newBuilder() 99 .setName(channel.toString()) 100 .setChannelId(channel.getLogId().getId()) 101 .build(); 102 private final ChannelData channelData = ChannelData 103 .newBuilder() 104 .setTarget("sometarget") 105 .setState(ChannelConnectivityState.newBuilder().setState(State.READY)) 106 .setCallsStarted(1) 107 .setCallsSucceeded(2) 108 .setCallsFailed(3) 109 .setLastCallStartedTimestamp(Timestamps.fromNanos(4)) 110 .build(); 111 private final Channel channelProto = Channel 112 .newBuilder() 113 .setRef(channelRef) 114 .setData(channelData) 115 .build(); 116 117 private final TestChannel subchannel = new TestChannel(); 118 private final SubchannelRef subchannelRef = SubchannelRef 119 .newBuilder() 120 .setName(subchannel.toString()) 121 .setSubchannelId(subchannel.getLogId().getId()) 122 .build(); 123 private final ChannelData subchannelData = ChannelData 124 .newBuilder() 125 .setTarget("sometarget") 126 .setState(ChannelConnectivityState.newBuilder().setState(State.READY)) 127 .setCallsStarted(1) 128 .setCallsSucceeded(2) 129 .setCallsFailed(3) 130 .setLastCallStartedTimestamp(Timestamps.fromNanos(4)) 131 .build(); 132 private final Subchannel subchannelProto = Subchannel 133 .newBuilder() 134 .setRef(subchannelRef) 135 .setData(subchannelData) 136 .build(); 137 138 private final TestServer server = new TestServer(); 139 private final ServerRef serverRef = ServerRef 140 .newBuilder() 141 .setName(server.toString()) 142 .setServerId(server.getLogId().getId()) 143 .build(); 144 private final ServerData serverData = ServerData 145 .newBuilder() 146 .setCallsStarted(1) 147 .setCallsSucceeded(2) 148 .setCallsFailed(3) 149 .setLastCallStartedTimestamp(Timestamps.fromNanos(4)) 150 .build(); 151 private final Server serverProto = Server 152 .newBuilder() 153 .setRef(serverRef) 154 .setData(serverData) 155 .build(); 156 157 private final SocketOption sockOptLingerDisabled = SocketOption 158 .newBuilder() 159 .setName("SO_LINGER") 160 .setAdditional( 161 Any.pack(SocketOptionLinger.getDefaultInstance())) 162 .build(); 163 164 private final SocketOption sockOptlinger10s = SocketOption 165 .newBuilder() 166 .setName("SO_LINGER") 167 .setAdditional( 168 Any.pack(SocketOptionLinger 169 .newBuilder() 170 .setActive(true) 171 .setDuration(Durations.fromSeconds(10)) 172 .build())) 173 .build(); 174 175 private final SocketOption sockOptTimeout200ms = SocketOption 176 .newBuilder() 177 .setName("SO_TIMEOUT") 178 .setAdditional( 179 Any.pack(SocketOptionTimeout 180 .newBuilder() 181 .setDuration(Durations.fromMillis(200)) 182 .build()) 183 ).build(); 184 185 private final SocketOption sockOptAdditional = SocketOption 186 .newBuilder() 187 .setName("SO_MADE_UP_OPTION") 188 .setValue("some-made-up-value") 189 .build(); 190 191 private final InternalChannelz.TcpInfo channelzTcpInfo 192 = new InternalChannelz.TcpInfo.Builder() 193 .setState(70) 194 .setCaState(71) 195 .setRetransmits(72) 196 .setProbes(73) 197 .setBackoff(74) 198 .setOptions(75) 199 .setSndWscale(76) 200 .setRcvWscale(77) 201 .setRto(78) 202 .setAto(79) 203 .setSndMss(710) 204 .setRcvMss(711) 205 .setUnacked(712) 206 .setSacked(713) 207 .setLost(714) 208 .setRetrans(715) 209 .setFackets(716) 210 .setLastDataSent(717) 211 .setLastAckSent(718) 212 .setLastDataRecv(719) 213 .setLastAckRecv(720) 214 .setPmtu(721) 215 .setRcvSsthresh(722) 216 .setRtt(723) 217 .setRttvar(724) 218 .setSndSsthresh(725) 219 .setSndCwnd(726) 220 .setAdvmss(727) 221 .setReordering(728) 222 .build(); 223 224 private final SocketOption socketOptionTcpInfo = SocketOption 225 .newBuilder() 226 .setName("TCP_INFO") 227 .setAdditional( 228 Any.pack( 229 SocketOptionTcpInfo.newBuilder() 230 .setTcpiState(70) 231 .setTcpiCaState(71) 232 .setTcpiRetransmits(72) 233 .setTcpiProbes(73) 234 .setTcpiBackoff(74) 235 .setTcpiOptions(75) 236 .setTcpiSndWscale(76) 237 .setTcpiRcvWscale(77) 238 .setTcpiRto(78) 239 .setTcpiAto(79) 240 .setTcpiSndMss(710) 241 .setTcpiRcvMss(711) 242 .setTcpiUnacked(712) 243 .setTcpiSacked(713) 244 .setTcpiLost(714) 245 .setTcpiRetrans(715) 246 .setTcpiFackets(716) 247 .setTcpiLastDataSent(717) 248 .setTcpiLastAckSent(718) 249 .setTcpiLastDataRecv(719) 250 .setTcpiLastAckRecv(720) 251 .setTcpiPmtu(721) 252 .setTcpiRcvSsthresh(722) 253 .setTcpiRtt(723) 254 .setTcpiRttvar(724) 255 .setTcpiSndSsthresh(725) 256 .setTcpiSndCwnd(726) 257 .setTcpiAdvmss(727) 258 .setTcpiReordering(728) 259 .build())) 260 .build(); 261 262 private final TestListenSocket listenSocket = new TestListenSocket(); 263 private final SocketRef listenSocketRef = SocketRef 264 .newBuilder() 265 .setName(listenSocket.toString()) 266 .setSocketId(id(listenSocket)) 267 .build(); 268 private final Address listenAddress = Address 269 .newBuilder() 270 .setTcpipAddress( 271 TcpIpAddress 272 .newBuilder() 273 .setIpAddress(ByteString.copyFrom( 274 ((InetSocketAddress) listenSocket.listenAddress).getAddress().getAddress())) 275 .setPort(1234)) 276 .build(); 277 278 private final TestSocket socket = new TestSocket(); 279 private final SocketRef socketRef = SocketRef 280 .newBuilder() 281 .setName(socket.toString()) 282 .setSocketId(socket.getLogId().getId()) 283 .build(); 284 private final SocketData socketDataWithDataNoSockOpts = SocketData 285 .newBuilder() 286 .setStreamsStarted(1) 287 .setLastLocalStreamCreatedTimestamp(Timestamps.fromNanos(2)) 288 .setLastRemoteStreamCreatedTimestamp(Timestamps.fromNanos(3)) 289 .setStreamsSucceeded(4) 290 .setStreamsFailed(5) 291 .setMessagesSent(6) 292 .setMessagesReceived(7) 293 .setKeepAlivesSent(8) 294 .setLastMessageSentTimestamp(Timestamps.fromNanos(9)) 295 .setLastMessageReceivedTimestamp(Timestamps.fromNanos(10)) 296 .setLocalFlowControlWindow(Int64Value.newBuilder().setValue(11)) 297 .setRemoteFlowControlWindow(Int64Value.newBuilder().setValue(12)) 298 .build(); 299 private final Address localAddress = Address 300 .newBuilder() 301 .setTcpipAddress( 302 TcpIpAddress 303 .newBuilder() 304 .setIpAddress(ByteString.copyFrom( 305 ((InetSocketAddress) socket.local).getAddress().getAddress())) 306 .setPort(1000)) 307 .build(); 308 private final Address remoteAddress = Address 309 .newBuilder() 310 .setTcpipAddress( 311 TcpIpAddress 312 .newBuilder() 313 .setIpAddress(ByteString.copyFrom( 314 ((InetSocketAddress) socket.remote).getAddress().getAddress())) 315 .setPort(1000)) 316 .build(); 317 318 private final ChannelTrace channelTrace = ChannelTrace 319 .newBuilder() 320 .setNumEventsLogged(1234) 321 .setCreationTimestamp(Timestamps.fromNanos(1000)) 322 .build(); 323 324 @Test toChannelRef()325 public void toChannelRef() { 326 assertEquals(channelRef, ChannelzProtoUtil.toChannelRef(channel)); 327 } 328 329 @Test toSubchannelRef()330 public void toSubchannelRef() { 331 assertEquals(subchannelRef, ChannelzProtoUtil.toSubchannelRef(subchannel)); 332 } 333 334 @Test toServerRef()335 public void toServerRef() { 336 assertEquals(serverRef, ChannelzProtoUtil.toServerRef(server)); 337 } 338 339 @Test toSocketRef()340 public void toSocketRef() { 341 assertEquals(socketRef, ChannelzProtoUtil.toSocketRef(socket)); 342 } 343 344 @Test toState()345 public void toState() { 346 for (ConnectivityState connectivityState : ConnectivityState.values()) { 347 assertEquals( 348 connectivityState.name(), 349 ChannelzProtoUtil.toState(connectivityState).getValueDescriptor().getName()); 350 } 351 assertEquals(State.UNKNOWN, ChannelzProtoUtil.toState(null)); 352 } 353 354 @Test toSocket_withDataNoOptions()355 public void toSocket_withDataNoOptions() throws Exception { 356 assertEquals( 357 Socket 358 .newBuilder() 359 .setRef(socketRef) 360 .setLocal(localAddress) 361 .setRemote(remoteAddress) 362 .setData(socketDataWithDataNoSockOpts) 363 .build(), 364 ChannelzProtoUtil.toSocket(socket)); 365 } 366 367 @Test toSocket_noDataWithOptions()368 public void toSocket_noDataWithOptions() throws Exception { 369 assertEquals( 370 Socket 371 .newBuilder() 372 .setRef(listenSocketRef) 373 .setLocal(listenAddress) 374 .setData( 375 SocketData 376 .newBuilder() 377 .addOption( 378 SocketOption 379 .newBuilder() 380 .setName("listen_option") 381 .setValue("listen_option_value"))) 382 .build(), 383 ChannelzProtoUtil.toSocket(listenSocket)); 384 } 385 386 @Test toSocket_withDataWithOptions()387 public void toSocket_withDataWithOptions() throws Exception { 388 socket.socketOptions 389 = new SocketOptions(null, null, null, ImmutableMap.of("test_name", "test_value")); 390 assertEquals( 391 Socket 392 .newBuilder() 393 .setRef(socketRef) 394 .setLocal(localAddress) 395 .setRemote(remoteAddress) 396 .setData( 397 SocketData 398 .newBuilder(socketDataWithDataNoSockOpts) 399 .addOption( 400 SocketOption.newBuilder() 401 .setName("test_name").setValue("test_value"))) 402 .build(), 403 ChannelzProtoUtil.toSocket(socket)); 404 } 405 406 @Test extractSocketData()407 public void extractSocketData() throws Exception { 408 // no options 409 assertEquals( 410 socketDataWithDataNoSockOpts, 411 ChannelzProtoUtil.extractSocketData(socket.getStats().get())); 412 413 // with options 414 socket.socketOptions = toBuilder(socket.socketOptions) 415 .setSocketOptionLingerSeconds(10) 416 .setTcpInfo(channelzTcpInfo) 417 .build(); 418 assertEquals( 419 socketDataWithDataNoSockOpts 420 .toBuilder() 421 .addOption(sockOptlinger10s) 422 .addOption(socketOptionTcpInfo) 423 .build(), 424 ChannelzProtoUtil.extractSocketData(socket.getStats().get())); 425 } 426 427 @Test toSocketData()428 public void toSocketData() throws Exception { 429 assertEquals( 430 socketDataWithDataNoSockOpts 431 .toBuilder() 432 .build(), 433 ChannelzProtoUtil.extractSocketData(socket.getStats().get())); 434 } 435 436 @Test socketSecurityTls()437 public void socketSecurityTls() throws Exception { 438 Certificate local = mock(Certificate.class); 439 Certificate remote = mock(Certificate.class); 440 when(local.getEncoded()).thenReturn("localcert".getBytes(Charsets.UTF_8)); 441 when(remote.getEncoded()).thenReturn("remotecert".getBytes(Charsets.UTF_8)); 442 443 socket.security = new InternalChannelz.Security( 444 new InternalChannelz.Tls("TLS_NULL_WITH_NULL_NULL", local, remote)); 445 assertEquals( 446 Security.newBuilder().setTls( 447 Tls.newBuilder() 448 .setStandardName("TLS_NULL_WITH_NULL_NULL") 449 .setLocalCertificate(ByteString.copyFrom("localcert", Charsets.UTF_8)) 450 .setRemoteCertificate(ByteString.copyFrom("remotecert", Charsets.UTF_8))) 451 .build(), 452 ChannelzProtoUtil.toSocket(socket).getSecurity()); 453 454 socket.security = new InternalChannelz.Security( 455 new InternalChannelz.Tls("TLS_NULL_WITH_NULL_NULL", /*localCert=*/ null, remote)); 456 assertEquals( 457 Security.newBuilder().setTls( 458 Tls.newBuilder() 459 .setStandardName("TLS_NULL_WITH_NULL_NULL") 460 .setRemoteCertificate(ByteString.copyFrom("remotecert", Charsets.UTF_8))) 461 .build(), 462 ChannelzProtoUtil.toSocket(socket).getSecurity()); 463 464 socket.security = new InternalChannelz.Security( 465 new InternalChannelz.Tls("TLS_NULL_WITH_NULL_NULL", local, /*remoteCert=*/ null)); 466 assertEquals( 467 Security.newBuilder().setTls( 468 Tls.newBuilder() 469 .setStandardName("TLS_NULL_WITH_NULL_NULL") 470 .setLocalCertificate(ByteString.copyFrom("localcert", Charsets.UTF_8))) 471 .build(), 472 ChannelzProtoUtil.toSocket(socket).getSecurity()); 473 } 474 475 @Test socketSecurityOther()476 public void socketSecurityOther() throws Exception { 477 // what is packed here is not important, just pick some proto message 478 Message contents = GetChannelRequest.newBuilder().setChannelId(1).build(); 479 Any packed = Any.pack(contents); 480 socket.security 481 = new InternalChannelz.Security( 482 new InternalChannelz.OtherSecurity("other_security", packed)); 483 assertEquals( 484 Security.newBuilder().setOther( 485 OtherSecurity.newBuilder().setName("other_security").setValue(packed)) 486 .build(), 487 ChannelzProtoUtil.toSocket(socket).getSecurity()); 488 } 489 490 @Test toAddress_inet()491 public void toAddress_inet() throws Exception { 492 InetSocketAddress inet4 = new InetSocketAddress(Inet4Address.getByName("10.0.0.1"), 1000); 493 assertEquals( 494 Address.newBuilder().setTcpipAddress( 495 TcpIpAddress 496 .newBuilder() 497 .setIpAddress(ByteString.copyFrom(inet4.getAddress().getAddress())) 498 .setPort(1000)) 499 .build(), 500 ChannelzProtoUtil.toAddress(inet4)); 501 } 502 503 @Test toAddress_uds()504 public void toAddress_uds() throws Exception { 505 String path = "/tmp/foo"; 506 DomainSocketAddress uds = new DomainSocketAddress(path); 507 assertEquals( 508 Address.newBuilder().setUdsAddress( 509 UdsAddress 510 .newBuilder() 511 .setFilename(path)) 512 .build(), 513 ChannelzProtoUtil.toAddress(uds)); 514 } 515 516 @Test toAddress_other()517 public void toAddress_other() throws Exception { 518 final String name = "my name"; 519 SocketAddress other = new SocketAddress() { 520 @Override 521 public String toString() { 522 return name; 523 } 524 }; 525 assertEquals( 526 Address.newBuilder().setOtherAddress( 527 OtherAddress 528 .newBuilder() 529 .setName(name)) 530 .build(), 531 ChannelzProtoUtil.toAddress(other)); 532 } 533 534 @Test toServer()535 public void toServer() throws Exception { 536 // no listen sockets 537 assertEquals(serverProto, ChannelzProtoUtil.toServer(server)); 538 539 // 1 listen socket 540 server.serverStats = toBuilder(server.serverStats) 541 .setListenSockets(ImmutableList.<InternalInstrumented<SocketStats>>of(listenSocket)) 542 .build(); 543 assertEquals( 544 serverProto 545 .toBuilder() 546 .addListenSocket(listenSocketRef) 547 .build(), 548 ChannelzProtoUtil.toServer(server)); 549 550 // multiple listen sockets 551 TestListenSocket otherListenSocket = new TestListenSocket(); 552 SocketRef otherListenSocketRef = ChannelzProtoUtil.toSocketRef(otherListenSocket); 553 server.serverStats = toBuilder(server.serverStats) 554 .setListenSockets( 555 ImmutableList.<InternalInstrumented<SocketStats>>of(listenSocket, otherListenSocket)) 556 .build(); 557 assertEquals( 558 serverProto 559 .toBuilder() 560 .addListenSocket(listenSocketRef) 561 .addListenSocket(otherListenSocketRef) 562 .build(), 563 ChannelzProtoUtil.toServer(server)); 564 } 565 566 @Test toServerData()567 public void toServerData() throws Exception { 568 assertEquals(serverData, ChannelzProtoUtil.toServerData(server.serverStats)); 569 } 570 571 @Test toChannel()572 public void toChannel() throws Exception { 573 assertEquals(channelProto, ChannelzProtoUtil.toChannel(channel)); 574 575 channel.stats = toBuilder(channel.stats) 576 .setSubchannels(ImmutableList.<InternalWithLogId>of(subchannel)) 577 .build(); 578 579 assertEquals( 580 channelProto 581 .toBuilder() 582 .addSubchannelRef(subchannelRef) 583 .build(), 584 ChannelzProtoUtil.toChannel(channel)); 585 586 TestChannel otherSubchannel = new TestChannel(); 587 channel.stats = toBuilder(channel.stats) 588 .setSubchannels(ImmutableList.<InternalWithLogId>of(subchannel, otherSubchannel)) 589 .build(); 590 assertEquals( 591 channelProto 592 .toBuilder() 593 .addSubchannelRef(subchannelRef) 594 .addSubchannelRef(ChannelzProtoUtil.toSubchannelRef(otherSubchannel)) 595 .build(), 596 ChannelzProtoUtil.toChannel(channel)); 597 } 598 599 @Test extractChannelData()600 public void extractChannelData() { 601 assertEquals(channelData, ChannelzProtoUtil.extractChannelData(channel.stats)); 602 } 603 604 @Test toSubchannel_noChildren()605 public void toSubchannel_noChildren() throws Exception { 606 assertEquals( 607 subchannelProto, 608 ChannelzProtoUtil.toSubchannel(subchannel)); 609 } 610 611 @Test toSubchannel_socketChildren()612 public void toSubchannel_socketChildren() throws Exception { 613 subchannel.stats = toBuilder(subchannel.stats) 614 .setSockets(ImmutableList.<InternalWithLogId>of(socket)) 615 .build(); 616 617 assertEquals( 618 subchannelProto.toBuilder() 619 .addSocketRef(socketRef) 620 .build(), 621 ChannelzProtoUtil.toSubchannel(subchannel)); 622 623 TestSocket otherSocket = new TestSocket(); 624 subchannel.stats = toBuilder(subchannel.stats) 625 .setSockets(ImmutableList.<InternalWithLogId>of(socket, otherSocket)) 626 .build(); 627 assertEquals( 628 subchannelProto 629 .toBuilder() 630 .addSocketRef(socketRef) 631 .addSocketRef(ChannelzProtoUtil.toSocketRef(otherSocket)) 632 .build(), 633 ChannelzProtoUtil.toSubchannel(subchannel)); 634 } 635 636 @Test toSubchannel_subchannelChildren()637 public void toSubchannel_subchannelChildren() throws Exception { 638 TestChannel subchannel1 = new TestChannel(); 639 subchannel.stats = toBuilder(subchannel.stats) 640 .setSubchannels(ImmutableList.<InternalWithLogId>of(subchannel1)) 641 .build(); 642 assertEquals( 643 subchannelProto.toBuilder() 644 .addSubchannelRef(ChannelzProtoUtil.toSubchannelRef(subchannel1)) 645 .build(), 646 ChannelzProtoUtil.toSubchannel(subchannel)); 647 648 TestChannel subchannel2 = new TestChannel(); 649 subchannel.stats = toBuilder(subchannel.stats) 650 .setSubchannels(ImmutableList.<InternalWithLogId>of(subchannel1, subchannel2)) 651 .build(); 652 assertEquals( 653 subchannelProto 654 .toBuilder() 655 .addSubchannelRef(ChannelzProtoUtil.toSubchannelRef(subchannel1)) 656 .addSubchannelRef(ChannelzProtoUtil.toSubchannelRef(subchannel2)) 657 .build(), 658 ChannelzProtoUtil.toSubchannel(subchannel)); 659 } 660 661 @Test toGetTopChannelsResponse()662 public void toGetTopChannelsResponse() { 663 // empty results 664 assertEquals( 665 GetTopChannelsResponse.newBuilder().setEnd(true).build(), 666 ChannelzProtoUtil.toGetTopChannelResponse( 667 new RootChannelList( 668 Collections.<InternalInstrumented<ChannelStats>>emptyList(), true))); 669 670 // 1 result, paginated 671 assertEquals( 672 GetTopChannelsResponse 673 .newBuilder() 674 .addChannel(channelProto) 675 .build(), 676 ChannelzProtoUtil.toGetTopChannelResponse( 677 new RootChannelList( 678 ImmutableList.<InternalInstrumented<ChannelStats>>of(channel), false))); 679 680 // 1 result, end 681 assertEquals( 682 GetTopChannelsResponse 683 .newBuilder() 684 .addChannel(channelProto) 685 .setEnd(true) 686 .build(), 687 ChannelzProtoUtil.toGetTopChannelResponse( 688 new RootChannelList( 689 ImmutableList.<InternalInstrumented<ChannelStats>>of(channel), true))); 690 691 // 2 results, end 692 TestChannel channel2 = new TestChannel(); 693 assertEquals( 694 GetTopChannelsResponse 695 .newBuilder() 696 .addChannel(channelProto) 697 .addChannel(ChannelzProtoUtil.toChannel(channel2)) 698 .setEnd(true) 699 .build(), 700 ChannelzProtoUtil.toGetTopChannelResponse( 701 new RootChannelList( 702 ImmutableList.<InternalInstrumented<ChannelStats>>of(channel, channel2), true))); 703 } 704 705 @Test toGetServersResponse()706 public void toGetServersResponse() { 707 // empty results 708 assertEquals( 709 GetServersResponse.getDefaultInstance(), 710 ChannelzProtoUtil.toGetServersResponse( 711 new ServerList(Collections.<InternalInstrumented<ServerStats>>emptyList(), false))); 712 713 // 1 result, paginated 714 assertEquals( 715 GetServersResponse 716 .newBuilder() 717 .addServer(serverProto) 718 .build(), 719 ChannelzProtoUtil.toGetServersResponse( 720 new ServerList(ImmutableList.<InternalInstrumented<ServerStats>>of(server), false))); 721 722 // 1 result, end 723 assertEquals( 724 GetServersResponse 725 .newBuilder() 726 .addServer(serverProto) 727 .setEnd(true) 728 .build(), 729 ChannelzProtoUtil.toGetServersResponse( 730 new ServerList(ImmutableList.<InternalInstrumented<ServerStats>>of(server), true))); 731 732 TestServer server2 = new TestServer(); 733 // 2 results, end 734 assertEquals( 735 GetServersResponse 736 .newBuilder() 737 .addServer(serverProto) 738 .addServer(ChannelzProtoUtil.toServer(server2)) 739 .setEnd(true) 740 .build(), 741 ChannelzProtoUtil.toGetServersResponse( 742 new ServerList( 743 ImmutableList.<InternalInstrumented<ServerStats>>of(server, server2), true))); 744 } 745 746 @Test toGetServerSocketsResponse()747 public void toGetServerSocketsResponse() { 748 // empty results 749 assertEquals( 750 GetServerSocketsResponse.getDefaultInstance(), 751 ChannelzProtoUtil.toGetServerSocketsResponse( 752 new ServerSocketsList(Collections.<InternalWithLogId>emptyList(), false))); 753 754 // 1 result, paginated 755 assertEquals( 756 GetServerSocketsResponse 757 .newBuilder() 758 .addSocketRef(socketRef) 759 .build(), 760 ChannelzProtoUtil.toGetServerSocketsResponse( 761 new ServerSocketsList(ImmutableList.<InternalWithLogId>of(socket), false))); 762 763 // 1 result, end 764 assertEquals( 765 GetServerSocketsResponse 766 .newBuilder() 767 .addSocketRef(socketRef) 768 .setEnd(true) 769 .build(), 770 ChannelzProtoUtil.toGetServerSocketsResponse( 771 new ServerSocketsList(ImmutableList.<InternalWithLogId>of(socket), true))); 772 773 TestSocket socket2 = new TestSocket(); 774 // 2 results, end 775 assertEquals( 776 GetServerSocketsResponse 777 .newBuilder() 778 .addSocketRef(socketRef) 779 .addSocketRef(ChannelzProtoUtil.toSocketRef(socket2)) 780 .setEnd(true) 781 .build(), 782 ChannelzProtoUtil.toGetServerSocketsResponse( 783 new ServerSocketsList(ImmutableList.<InternalWithLogId>of(socket, socket2), true))); 784 } 785 786 @Test toSocketOptionLinger()787 public void toSocketOptionLinger() { 788 assertEquals(sockOptLingerDisabled, ChannelzProtoUtil.toSocketOptionLinger(-1)); 789 assertEquals(sockOptlinger10s, ChannelzProtoUtil.toSocketOptionLinger(10)); 790 } 791 792 @Test toSocketOptionTimeout()793 public void toSocketOptionTimeout() { 794 assertEquals( 795 sockOptTimeout200ms, ChannelzProtoUtil.toSocketOptionTimeout("SO_TIMEOUT", 200)); 796 } 797 798 @Test toSocketOptionAdditional()799 public void toSocketOptionAdditional() { 800 assertEquals( 801 sockOptAdditional, 802 ChannelzProtoUtil.toSocketOptionAdditional("SO_MADE_UP_OPTION", "some-made-up-value")); 803 } 804 805 @Test toSocketOptionTcpInfo()806 public void toSocketOptionTcpInfo() { 807 assertEquals( 808 socketOptionTcpInfo, 809 ChannelzProtoUtil.toSocketOptionTcpInfo(channelzTcpInfo)); 810 } 811 812 @Test toSocketOptionsList()813 public void toSocketOptionsList() { 814 assertThat( 815 ChannelzProtoUtil.toSocketOptionsList( 816 new InternalChannelz.SocketOptions.Builder().build())) 817 .isEmpty(); 818 819 assertThat( 820 ChannelzProtoUtil.toSocketOptionsList( 821 new InternalChannelz.SocketOptions.Builder().setSocketOptionLingerSeconds(10).build())) 822 .containsExactly(sockOptlinger10s); 823 824 assertThat( 825 ChannelzProtoUtil.toSocketOptionsList( 826 new InternalChannelz.SocketOptions.Builder().setSocketOptionTimeoutMillis(200).build())) 827 .containsExactly(sockOptTimeout200ms); 828 829 assertThat( 830 ChannelzProtoUtil.toSocketOptionsList( 831 new InternalChannelz.SocketOptions 832 .Builder() 833 .addOption("SO_MADE_UP_OPTION", "some-made-up-value") 834 .build())) 835 .containsExactly(sockOptAdditional); 836 837 SocketOption otherOption = SocketOption 838 .newBuilder() 839 .setName("SO_MADE_UP_OPTION2") 840 .setValue("some-made-up-value2") 841 .build(); 842 assertThat( 843 ChannelzProtoUtil.toSocketOptionsList( 844 new InternalChannelz.SocketOptions.Builder() 845 .addOption("SO_MADE_UP_OPTION", "some-made-up-value") 846 .addOption("SO_MADE_UP_OPTION2", "some-made-up-value2") 847 .build())) 848 .containsExactly(sockOptAdditional, otherOption); 849 } 850 851 @Test channelTrace_withoutEvents()852 public void channelTrace_withoutEvents() { 853 ChannelStats stats = toBuilder(channel.stats) 854 .setChannelTrace(new InternalChannelz.ChannelTrace.Builder() 855 .setNumEventsLogged(1234) 856 .setCreationTimeNanos(1000) 857 .build()) 858 .build(); 859 860 ChannelData protoStats = channelData.toBuilder().setTrace(channelTrace).build(); 861 assertEquals(ChannelzProtoUtil.extractChannelData(stats), protoStats); 862 } 863 864 @Test channelTrace_withEvents()865 public void channelTrace_withEvents() { 866 Event event1 = new Event.Builder() 867 .setDescription("event1") 868 .setSeverity(Severity.CT_ERROR) 869 .setTimestampNanos(12) 870 .setSubchannelRef(subchannel) 871 .build(); 872 Event event2 = new Event.Builder() 873 .setDescription("event2") 874 .setTimestampNanos(34) 875 .setSeverity(Severity.CT_INFO) 876 .setChannelRef(channel) 877 .build(); 878 879 ChannelStats stats = 880 toBuilder(channel.stats) 881 .setChannelTrace( 882 new InternalChannelz.ChannelTrace.Builder() 883 .setNumEventsLogged(1234) 884 .setCreationTimeNanos(1000) 885 .setEvents(Arrays.asList(event1, event2)) 886 .build()) 887 .build(); 888 889 ChannelTraceEvent protoEvent1 = ChannelTraceEvent 890 .newBuilder() 891 .setDescription("event1") 892 .setTimestamp(Timestamps.fromNanos(12)) 893 .setSeverity(ChannelTraceEvent.Severity.CT_ERROR) 894 .setSubchannelRef(subchannelRef) 895 .build(); 896 ChannelTraceEvent protoEvent2 = ChannelTraceEvent 897 .newBuilder() 898 .setDescription("event2") 899 .setTimestamp(Timestamps.fromNanos(34)) 900 .setSeverity(ChannelTraceEvent.Severity.CT_INFO) 901 .setChannelRef(channelRef) 902 .build(); 903 ChannelData protoStats = channelData 904 .toBuilder() 905 .setTrace(channelTrace 906 .toBuilder() 907 .addAllEvents(Arrays.asList(protoEvent1, protoEvent2)) 908 .build()) 909 .build(); 910 assertEquals(ChannelzProtoUtil.extractChannelData(stats), protoStats); 911 } 912 toBuilder(ChannelStats stats)913 private static ChannelStats.Builder toBuilder(ChannelStats stats) { 914 ChannelStats.Builder builder = new ChannelStats.Builder() 915 .setTarget(stats.target) 916 .setState(stats.state) 917 .setCallsStarted(stats.callsStarted) 918 .setCallsSucceeded(stats.callsSucceeded) 919 .setCallsFailed(stats.callsFailed) 920 .setLastCallStartedNanos(stats.lastCallStartedNanos); 921 if (!stats.subchannels.isEmpty()) { 922 builder.setSubchannels(stats.subchannels); 923 } 924 if (!stats.sockets.isEmpty()) { 925 builder.setSockets(stats.sockets); 926 } 927 return builder; 928 } 929 930 toBuilder(SocketOptions options)931 private static SocketOptions.Builder toBuilder(SocketOptions options) { 932 SocketOptions.Builder builder = new SocketOptions.Builder() 933 .setSocketOptionTimeoutMillis(options.soTimeoutMillis) 934 .setSocketOptionLingerSeconds(options.lingerSeconds); 935 for (Entry<String, String> entry : options.others.entrySet()) { 936 builder.addOption(entry.getKey(), entry.getValue()); 937 } 938 return builder; 939 } 940 toBuilder(ServerStats stats)941 private static ServerStats.Builder toBuilder(ServerStats stats) { 942 return new ServerStats.Builder() 943 .setCallsStarted(stats.callsStarted) 944 .setCallsSucceeded(stats.callsSucceeded) 945 .setCallsFailed(stats.callsFailed) 946 .setLastCallStartedNanos(stats.lastCallStartedNanos) 947 .setListenSockets(stats.listenSockets); 948 } 949 } 950