### Question:
OkHttpClientTransport implements ConnectionClientTransport, TransportExceptionHandler { @Override public void ping(final PingCallback callback, Executor executor) { checkState(frameWriter != null); long data = 0; Http2Ping p; boolean writePing; synchronized (lock) { if (stopped) { Http2Ping.notifyFailed(callback, executor, getPingFailure()); return; } if (ping != null) { p = ping; writePing = false; } else { data = random.nextLong(); Stopwatch stopwatch = stopwatchFactory.get(); stopwatch.start(); p = ping = new Http2Ping(data, stopwatch); writePing = true; transportTracer.reportKeepAliveSent(); } } if (writePing) { frameWriter.ping(false, (int) (data >>> 32), (int) data); } p.addCallback(callback, executor); } OkHttpClientTransport(InetSocketAddress address, String authority, @Nullable String userAgent,
      Executor executor, @Nullable SSLSocketFactory sslSocketFactory,
      @Nullable HostnameVerifier hostnameVerifier, ConnectionSpec connectionSpec,
      int maxMessageSize, int initialWindowSize, @Nullable ProxyParameters proxy,
      Runnable tooManyPingsRunnable, int maxInboundMetadataSize, TransportTracer transportTracer); @VisibleForTesting  OkHttpClientTransport(
      String userAgent,
      Executor executor,
      FrameReader frameReader,
      FrameWriter testFrameWriter,
      int nextStreamId,
      Socket socket,
      Supplier<Stopwatch> stopwatchFactory,
      @Nullable Runnable connectingCallback,
      SettableFuture<Void> connectedFuture,
      int maxMessageSize,
      int initialWindowSize,
      Runnable tooManyPingsRunnable,
      TransportTracer transportTracer); @Override void ping(final PingCallback callback, Executor executor); @Override OkHttpClientStream newStream(final MethodDescriptor<?, ?> method,
      final Metadata headers, CallOptions callOptions); @Override Runnable start(Listener listener); @Override String toString(); @Override InternalLogId getLogId(); @Override void shutdown(Status reason); @Override void shutdownNow(Status reason); @Override Attributes getAttributes(); @Override void onException(Throwable failureCause); @Override ListenableFuture<SocketStats> getStats(); @Override SocketAddress getAddress();  }### Answer:
@Test public void ping() throws Exception { initTransport(); PingCallbackImpl callback1 = new PingCallbackImpl(); clientTransport.ping(callback1, MoreExecutors.directExecutor()); assertEquals(1, getTransportStats(clientTransport).keepAlivesSent); PingCallbackImpl callback2 = new PingCallbackImpl(); clientTransport.ping(callback2, MoreExecutors.directExecutor()); assertEquals(1, getTransportStats(clientTransport).keepAlivesSent); ArgumentCaptor<Integer> captor1 = ArgumentCaptor.forClass(int.class); ArgumentCaptor<Integer> captor2 = ArgumentCaptor.forClass(int.class); verify(frameWriter, timeout(TIME_OUT_MS)).ping(eq(false), captor1.capture(), captor2.capture()); assertEquals(0, callback1.invocationCount); assertEquals(0, callback2.invocationCount); int payload1 = captor1.getValue(); int payload2 = captor2.getValue(); frameHandler().ping(true, payload1, payload2 - 1); assertEquals(0, callback1.invocationCount); assertEquals(0, callback2.invocationCount); nanoTime += 10101; frameHandler().ping(true, payload1, payload2); assertEquals(1, callback1.invocationCount); assertEquals(10101, callback1.roundTripTime); assertNull(callback1.failureCause); assertEquals(1, callback2.invocationCount); assertEquals(10101, callback2.roundTripTime); assertNull(callback2.failureCause); callback1 = new PingCallbackImpl(); clientTransport.ping(callback1, MoreExecutors.directExecutor()); assertEquals(2, getTransportStats(clientTransport).keepAlivesSent); assertEquals(0, callback1.invocationCount); shutdownAndVerify(); }