• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 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.okhttp;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static io.grpc.internal.GrpcUtil.TIMER_SERVICE;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertSame;
25 import static org.mockito.Mockito.mock;
26 
27 import com.google.common.util.concurrent.SettableFuture;
28 import com.squareup.okhttp.ConnectionSpec;
29 import io.grpc.CallCredentials;
30 import io.grpc.ChannelCredentials;
31 import io.grpc.ChannelLogger;
32 import io.grpc.ChoiceChannelCredentials;
33 import io.grpc.CompositeChannelCredentials;
34 import io.grpc.InsecureChannelCredentials;
35 import io.grpc.ManagedChannel;
36 import io.grpc.TlsChannelCredentials;
37 import io.grpc.internal.ClientTransportFactory;
38 import io.grpc.internal.ClientTransportFactory.SwapChannelCredentialsResult;
39 import io.grpc.internal.FakeClock;
40 import io.grpc.internal.GrpcUtil;
41 import io.grpc.internal.SharedResourceHolder;
42 import io.grpc.internal.testing.TestUtils;
43 import io.grpc.testing.GrpcCleanupRule;
44 import io.grpc.testing.TlsTesting;
45 import io.netty.handler.ssl.util.SelfSignedCertificate;
46 import java.net.InetAddress;
47 import java.net.InetSocketAddress;
48 import java.net.Socket;
49 import java.security.KeyStore;
50 import java.security.cert.Certificate;
51 import java.util.concurrent.ScheduledExecutorService;
52 import javax.net.SocketFactory;
53 import javax.net.ssl.KeyManagerFactory;
54 import javax.net.ssl.SSLContext;
55 import javax.net.ssl.SSLServerSocket;
56 import javax.net.ssl.SSLSocket;
57 import javax.net.ssl.SSLSocketFactory;
58 import javax.net.ssl.TrustManagerFactory;
59 import javax.security.auth.x500.X500Principal;
60 import org.junit.Rule;
61 import org.junit.Test;
62 import org.junit.rules.ExpectedException;
63 import org.junit.runner.RunWith;
64 import org.junit.runners.JUnit4;
65 
66 /**
67  * Tests for {@link OkHttpChannelBuilder}.
68  */
69 @RunWith(JUnit4.class)
70 public class OkHttpChannelBuilderTest {
71 
72   @SuppressWarnings("deprecation") // https://github.com/grpc/grpc-java/issues/7467
73   @Rule public final ExpectedException thrown = ExpectedException.none();
74   @Rule public final GrpcCleanupRule grpcCleanupRule = new GrpcCleanupRule();
75 
76   @Test
authorityIsReadable()77   public void authorityIsReadable() {
78     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("original", 1234);
79     ManagedChannel channel = grpcCleanupRule.register(builder.build());
80     assertEquals("original:1234", channel.authority());
81   }
82 
83   @Test
overrideAuthorityIsReadableForAddress()84   public void overrideAuthorityIsReadableForAddress() {
85     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("original", 1234);
86     overrideAuthorityIsReadableHelper(builder, "override:5678");
87   }
88 
89   @Test
overrideAuthorityIsReadableForTarget()90   public void overrideAuthorityIsReadableForTarget() {
91     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forTarget("original:1234");
92     overrideAuthorityIsReadableHelper(builder, "override:5678");
93   }
94 
overrideAuthorityIsReadableHelper(OkHttpChannelBuilder builder, String overrideAuthority)95   private void overrideAuthorityIsReadableHelper(OkHttpChannelBuilder builder,
96       String overrideAuthority) {
97     builder.overrideAuthority(overrideAuthority);
98     ManagedChannel channel = grpcCleanupRule.register(builder.build());
99     assertEquals(overrideAuthority, channel.authority());
100   }
101 
102   @Test
failOverrideInvalidAuthority()103   public void failOverrideInvalidAuthority() {
104     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("good", 1234);
105 
106     thrown.expect(IllegalArgumentException.class);
107     thrown.expectMessage("Invalid authority:");
108     builder.overrideAuthority("[invalidauthority");
109   }
110 
111   @Test
disableCheckAuthorityAllowsInvalidAuthority()112   public void disableCheckAuthorityAllowsInvalidAuthority() {
113     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("good", 1234)
114         .disableCheckAuthority();
115     builder.overrideAuthority("[invalidauthority").usePlaintext().buildTransportFactory();
116   }
117 
118   @Test
enableCheckAuthorityFailOverrideInvalidAuthority()119   public void enableCheckAuthorityFailOverrideInvalidAuthority() {
120     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("good", 1234)
121         .disableCheckAuthority()
122         .enableCheckAuthority();
123 
124     thrown.expect(IllegalArgumentException.class);
125     thrown.expectMessage("Invalid authority:");
126     builder.overrideAuthority("[invalidauthority");
127   }
128 
129   @Test
failInvalidAuthority()130   public void failInvalidAuthority() {
131     thrown.expect(IllegalArgumentException.class);
132     thrown.expectMessage("Invalid host or port");
133 
134     OkHttpChannelBuilder.forAddress("invalid_authority", 1234);
135   }
136 
137   @Test
sslSocketFactoryFrom_unknown()138   public void sslSocketFactoryFrom_unknown() {
139     OkHttpChannelBuilder.SslSocketFactoryResult result =
140         OkHttpChannelBuilder.sslSocketFactoryFrom(new ChannelCredentials() {
141           @Override
142           public ChannelCredentials withoutBearerTokens() {
143             throw new UnsupportedOperationException();
144           }
145         });
146     assertThat(result.error).isNotNull();
147     assertThat(result.callCredentials).isNull();
148     assertThat(result.factory).isNull();
149   }
150 
151   @Test
sslSocketFactoryFrom_tls()152   public void sslSocketFactoryFrom_tls() {
153     OkHttpChannelBuilder.SslSocketFactoryResult result =
154         OkHttpChannelBuilder.sslSocketFactoryFrom(TlsChannelCredentials.create());
155     assertThat(result.error).isNull();
156     assertThat(result.callCredentials).isNull();
157     assertThat(result.factory).isNotNull();
158   }
159 
160   @Test
sslSocketFactoryFrom_unsupportedTls()161   public void sslSocketFactoryFrom_unsupportedTls() {
162     OkHttpChannelBuilder.SslSocketFactoryResult result = OkHttpChannelBuilder.sslSocketFactoryFrom(
163         TlsChannelCredentials.newBuilder().requireFakeFeature().build());
164     assertThat(result.error).contains("FAKE");
165     assertThat(result.callCredentials).isNull();
166     assertThat(result.factory).isNull();
167   }
168 
169   @Test
sslSocketFactoryFrom_tls_customRoots()170   public void sslSocketFactoryFrom_tls_customRoots() throws Exception {
171     SelfSignedCertificate cert = new SelfSignedCertificate(TestUtils.TEST_SERVER_HOST);
172     KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
173     keyStore.load(null);
174     keyStore.setKeyEntry("mykey", cert.key(), new char[0], new Certificate[] {cert.cert()});
175     KeyManagerFactory keyManagerFactory =
176         KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
177     keyManagerFactory.init(keyStore, new char[0]);
178 
179     SSLContext serverContext = SSLContext.getInstance("TLS");
180     serverContext.init(keyManagerFactory.getKeyManagers(), null, null);
181     final SSLServerSocket serverListenSocket =
182         (SSLServerSocket) serverContext.getServerSocketFactory().createServerSocket(0);
183     final SettableFuture<SSLSocket> serverSocket = SettableFuture.create();
184     new Thread(new Runnable() {
185       @Override public void run() {
186         try {
187           SSLSocket socket = (SSLSocket) serverListenSocket.accept();
188           socket.getSession(); // Force handshake
189           serverSocket.set(socket);
190           serverListenSocket.close();
191         } catch (Throwable t) {
192           serverSocket.setException(t);
193         }
194       }
195     }).start();
196 
197     ChannelCredentials creds = TlsChannelCredentials.newBuilder()
198         .trustManager(cert.certificate())
199         .build();
200     OkHttpChannelBuilder.SslSocketFactoryResult result =
201         OkHttpChannelBuilder.sslSocketFactoryFrom(creds);
202     SSLSocket socket =
203         (SSLSocket) result.factory.createSocket("localhost", serverListenSocket.getLocalPort());
204     socket.getSession(); // Force handshake
205     socket.close();
206     serverSocket.get().close();
207   }
208 
209   @Test
sslSocketFactoryFrom_tls_mtls()210   public void sslSocketFactoryFrom_tls_mtls() throws Exception {
211     SelfSignedCertificate cert = new SelfSignedCertificate(TestUtils.TEST_SERVER_HOST);
212     KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
213     keyStore.load(null);
214     keyStore.setKeyEntry("mykey", cert.key(), new char[0], new Certificate[] {cert.cert()});
215     KeyManagerFactory keyManagerFactory =
216         KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
217     keyManagerFactory.init(keyStore, new char[0]);
218 
219     KeyStore certStore = KeyStore.getInstance(KeyStore.getDefaultType());
220     certStore.load(null);
221     certStore.setCertificateEntry("mycert", cert.cert());
222     TrustManagerFactory trustManagerFactory =
223         TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
224     trustManagerFactory.init(certStore);
225 
226     SSLContext serverContext = SSLContext.getInstance("TLS");
227     serverContext.init(
228         keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
229     final SSLServerSocket serverListenSocket =
230         (SSLServerSocket) serverContext.getServerSocketFactory().createServerSocket(0);
231     serverListenSocket.setNeedClientAuth(true);
232     final SettableFuture<SSLSocket> serverSocket = SettableFuture.create();
233     new Thread(new Runnable() {
234       @Override public void run() {
235         try {
236           SSLSocket socket = (SSLSocket) serverListenSocket.accept();
237           socket.getSession(); // Force handshake
238           serverSocket.set(socket);
239           serverListenSocket.close();
240         } catch (Throwable t) {
241           serverSocket.setException(t);
242         }
243       }
244     }).start();
245 
246     ChannelCredentials creds = TlsChannelCredentials.newBuilder()
247         .keyManager(keyManagerFactory.getKeyManagers())
248         .trustManager(trustManagerFactory.getTrustManagers())
249         .build();
250     OkHttpChannelBuilder.SslSocketFactoryResult result =
251         OkHttpChannelBuilder.sslSocketFactoryFrom(creds);
252     SSLSocket socket =
253         (SSLSocket) result.factory.createSocket("localhost", serverListenSocket.getLocalPort());
254     socket.getSession(); // Force handshake
255     assertThat(((X500Principal) serverSocket.get().getSession().getPeerPrincipal()).getName())
256         .isEqualTo("CN=" + TestUtils.TEST_SERVER_HOST);
257     socket.close();
258     serverSocket.get().close();
259   }
260 
261   @Test
sslSocketFactoryFrom_tls_mtls_keyFile()262   public void sslSocketFactoryFrom_tls_mtls_keyFile() throws Exception {
263     SelfSignedCertificate cert = new SelfSignedCertificate(TestUtils.TEST_SERVER_HOST);
264     KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
265     keyStore.load(null);
266     keyStore.setKeyEntry("mykey", cert.key(), new char[0], new Certificate[] {cert.cert()});
267     KeyManagerFactory keyManagerFactory =
268         KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
269     keyManagerFactory.init(keyStore, new char[0]);
270 
271     KeyStore certStore = KeyStore.getInstance(KeyStore.getDefaultType());
272     certStore.load(null);
273     certStore.setCertificateEntry("mycert", cert.cert());
274     TrustManagerFactory trustManagerFactory =
275         TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
276     trustManagerFactory.init(certStore);
277 
278     SSLContext serverContext = SSLContext.getInstance("TLS");
279     serverContext.init(
280         keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
281     final SSLServerSocket serverListenSocket =
282         (SSLServerSocket) serverContext.getServerSocketFactory().createServerSocket(0);
283     serverListenSocket.setNeedClientAuth(true);
284     final SettableFuture<SSLSocket> serverSocket = SettableFuture.create();
285     new Thread(new Runnable() {
286       @Override public void run() {
287         try {
288           SSLSocket socket = (SSLSocket) serverListenSocket.accept();
289           socket.getSession(); // Force handshake
290           serverSocket.set(socket);
291           serverListenSocket.close();
292         } catch (Throwable t) {
293           serverSocket.setException(t);
294         }
295       }
296     }).start();
297 
298     ChannelCredentials creds = TlsChannelCredentials.newBuilder()
299         .keyManager(cert.certificate(), cert.privateKey())
300         .trustManager(cert.certificate())
301         .build();
302     OkHttpChannelBuilder.SslSocketFactoryResult result =
303         OkHttpChannelBuilder.sslSocketFactoryFrom(creds);
304     SSLSocket socket =
305         (SSLSocket) result.factory.createSocket("localhost", serverListenSocket.getLocalPort());
306     socket.getSession(); // Force handshake
307     assertThat(((X500Principal) serverSocket.get().getSession().getPeerPrincipal()).getName())
308         .isEqualTo("CN=" + TestUtils.TEST_SERVER_HOST);
309     socket.close();
310     serverSocket.get().close();
311   }
312 
313   @Test
sslSocketFactoryFrom_tls_mtls_passwordUnsupported()314   public void sslSocketFactoryFrom_tls_mtls_passwordUnsupported() throws Exception {
315     ChannelCredentials creds = TlsChannelCredentials.newBuilder()
316         .keyManager(
317             TlsTesting.loadCert("server1.pem"), TlsTesting.loadCert("server1.key"), "password")
318         .build();
319     OkHttpChannelBuilder.SslSocketFactoryResult result =
320         OkHttpChannelBuilder.sslSocketFactoryFrom(creds);
321     assertThat(result.error).contains("unsupported");
322     assertThat(result.callCredentials).isNull();
323     assertThat(result.factory).isNull();
324   }
325 
326   @Test
sslSocketFactoryFrom_insecure()327   public void sslSocketFactoryFrom_insecure() {
328     OkHttpChannelBuilder.SslSocketFactoryResult result =
329         OkHttpChannelBuilder.sslSocketFactoryFrom(InsecureChannelCredentials.create());
330     assertThat(result.error).isNull();
331     assertThat(result.callCredentials).isNull();
332     assertThat(result.factory).isNull();
333   }
334 
335   @Test
sslSocketFactoryFrom_composite()336   public void sslSocketFactoryFrom_composite() {
337     CallCredentials callCredentials = mock(CallCredentials.class);
338     OkHttpChannelBuilder.SslSocketFactoryResult result =
339         OkHttpChannelBuilder.sslSocketFactoryFrom(CompositeChannelCredentials.create(
340           TlsChannelCredentials.create(), callCredentials));
341     assertThat(result.error).isNull();
342     assertThat(result.callCredentials).isSameInstanceAs(callCredentials);
343     assertThat(result.factory).isNotNull();
344 
345     result = OkHttpChannelBuilder.sslSocketFactoryFrom(CompositeChannelCredentials.create(
346           InsecureChannelCredentials.create(), callCredentials));
347     assertThat(result.error).isNull();
348     assertThat(result.callCredentials).isSameInstanceAs(callCredentials);
349     assertThat(result.factory).isNull();
350   }
351 
352   @Test
sslSocketFactoryFrom_okHttp()353   public void sslSocketFactoryFrom_okHttp() throws Exception {
354     SSLContext sslContext = SSLContext.getInstance("TLS");
355     sslContext.init(null, null, null);
356     SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
357     OkHttpChannelBuilder.SslSocketFactoryResult result = OkHttpChannelBuilder.sslSocketFactoryFrom(
358         SslSocketFactoryChannelCredentials.create(sslSocketFactory));
359     assertThat(result.error).isNull();
360     assertThat(result.callCredentials).isNull();
361     assertThat(result.factory).isSameInstanceAs(sslSocketFactory);
362   }
363 
364   @Test
sslSocketFactoryFrom_choice()365   public void sslSocketFactoryFrom_choice() {
366     OkHttpChannelBuilder.SslSocketFactoryResult result =
367         OkHttpChannelBuilder.sslSocketFactoryFrom(ChoiceChannelCredentials.create(
368           new ChannelCredentials() {
369             @Override
370             public ChannelCredentials withoutBearerTokens() {
371               throw new UnsupportedOperationException();
372             }
373           },
374           TlsChannelCredentials.create(),
375           InsecureChannelCredentials.create()));
376     assertThat(result.error).isNull();
377     assertThat(result.callCredentials).isNull();
378     assertThat(result.factory).isNotNull();
379 
380     result = OkHttpChannelBuilder.sslSocketFactoryFrom(ChoiceChannelCredentials.create(
381           InsecureChannelCredentials.create(),
382           new ChannelCredentials() {
383             @Override
384             public ChannelCredentials withoutBearerTokens() {
385               throw new UnsupportedOperationException();
386             }
387           },
388           TlsChannelCredentials.create()));
389     assertThat(result.error).isNull();
390     assertThat(result.callCredentials).isNull();
391     assertThat(result.factory).isNull();
392   }
393 
394   @Test
sslSocketFactoryFrom_choice_unknown()395   public void sslSocketFactoryFrom_choice_unknown() {
396     OkHttpChannelBuilder.SslSocketFactoryResult result =
397         OkHttpChannelBuilder.sslSocketFactoryFrom(ChoiceChannelCredentials.create(
398           new ChannelCredentials() {
399             @Override
400             public ChannelCredentials withoutBearerTokens() {
401               throw new UnsupportedOperationException();
402             }
403           }));
404     assertThat(result.error).isNotNull();
405     assertThat(result.callCredentials).isNull();
406     assertThat(result.factory).isNull();
407   }
408 
409   @Test
failForUsingClearTextSpecDirectly()410   public void failForUsingClearTextSpecDirectly() {
411     thrown.expect(IllegalArgumentException.class);
412     thrown.expectMessage("plaintext ConnectionSpec is not accepted");
413 
414     OkHttpChannelBuilder.forAddress("host", 1234).connectionSpec(ConnectionSpec.CLEARTEXT);
415   }
416 
417   @Test
allowUsingTlsConnectionSpec()418   public void allowUsingTlsConnectionSpec() {
419     OkHttpChannelBuilder.forAddress("host", 1234).connectionSpec(ConnectionSpec.MODERN_TLS);
420   }
421 
422   @Test
usePlaintext_newClientTransportAllowed()423   public void usePlaintext_newClientTransportAllowed() {
424     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("host", 1234).usePlaintext();
425     builder.buildTransportFactory().newClientTransport(
426         new InetSocketAddress(5678),
427         new ClientTransportFactory.ClientTransportOptions(), new FakeChannelLogger());
428   }
429 
430   @Test
usePlaintextDefaultPort()431   public void usePlaintextDefaultPort() {
432     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("host", 1234).usePlaintext();
433     assertEquals(GrpcUtil.DEFAULT_PORT_PLAINTEXT, builder.getDefaultPort());
434   }
435 
436   @Test
usePlaintextCreatesNullSocketFactory()437   public void usePlaintextCreatesNullSocketFactory() {
438     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("host", 1234);
439     assertNotNull(builder.createSslSocketFactory());
440 
441     builder.usePlaintext();
442     assertNull(builder.createSslSocketFactory());
443   }
444 
445   @Test
scheduledExecutorService_default()446   public void scheduledExecutorService_default() {
447     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forTarget("foo");
448     ClientTransportFactory clientTransportFactory = builder.buildTransportFactory();
449     assertSame(
450         SharedResourceHolder.get(TIMER_SERVICE),
451         clientTransportFactory.getScheduledExecutorService());
452 
453     SharedResourceHolder.release(
454         TIMER_SERVICE, clientTransportFactory.getScheduledExecutorService());
455     clientTransportFactory.close();
456   }
457 
458   @Test
scheduledExecutorService_custom()459   public void scheduledExecutorService_custom() {
460     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forTarget("foo");
461     ScheduledExecutorService scheduledExecutorService =
462         new FakeClock().getScheduledExecutorService();
463 
464     OkHttpChannelBuilder builder1 = builder.scheduledExecutorService(scheduledExecutorService);
465     assertSame(builder, builder1);
466 
467     ClientTransportFactory clientTransportFactory = builder1.buildTransportFactory();
468 
469     assertSame(scheduledExecutorService, clientTransportFactory.getScheduledExecutorService());
470 
471     clientTransportFactory.close();
472   }
473 
474   @Test
socketFactory_default()475   public void socketFactory_default() {
476     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forTarget("foo");
477     ClientTransportFactory transportFactory = builder.buildTransportFactory();
478     OkHttpClientTransport transport =
479         (OkHttpClientTransport)
480             transportFactory.newClientTransport(
481                 new InetSocketAddress(5678),
482                 new ClientTransportFactory.ClientTransportOptions(),
483                 new FakeChannelLogger());
484 
485     assertSame(SocketFactory.getDefault(), transport.getSocketFactory());
486 
487     transportFactory.close();
488   }
489 
490   @Test
socketFactory_custom()491   public void socketFactory_custom() {
492     SocketFactory socketFactory =
493         new SocketFactory() {
494           @Override
495           public Socket createSocket(String s, int i) {
496             return null;
497           }
498 
499           @Override
500           public Socket createSocket(String s, int i, InetAddress inetAddress, int i1) {
501             return null;
502           }
503 
504           @Override
505           public Socket createSocket(InetAddress inetAddress, int i) {
506             return null;
507           }
508 
509           @Override
510           public Socket createSocket(
511               InetAddress inetAddress, int i, InetAddress inetAddress1, int i1) {
512             return null;
513           }
514         };
515     OkHttpChannelBuilder builder =
516         OkHttpChannelBuilder.forTarget("foo").socketFactory(socketFactory);
517     ClientTransportFactory transportFactory = builder.buildTransportFactory();
518     OkHttpClientTransport transport =
519         (OkHttpClientTransport)
520             transportFactory.newClientTransport(
521                 new InetSocketAddress(5678),
522                 new ClientTransportFactory.ClientTransportOptions(),
523                 new FakeChannelLogger());
524 
525     assertSame(socketFactory, transport.getSocketFactory());
526 
527     transportFactory.close();
528   }
529 
530   @Test
transportFactorySupportsOkHttpChannelCreds()531   public void transportFactorySupportsOkHttpChannelCreds() {
532     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forTarget("foo");
533     ClientTransportFactory transportFactory = builder.buildTransportFactory();
534 
535     SwapChannelCredentialsResult result = transportFactory.swapChannelCredentials(
536         mock(ChannelCredentials.class));
537     assertThat(result).isNull();
538 
539     result = transportFactory.swapChannelCredentials(
540         SslSocketFactoryChannelCredentials.create(mock(SSLSocketFactory.class)));
541     assertThat(result).isNotNull();
542   }
543 
544   private static final class FakeChannelLogger extends ChannelLogger {
545 
546     @Override
log(ChannelLogLevel level, String message)547     public void log(ChannelLogLevel level, String message) {
548 
549     }
550 
551     @Override
log(ChannelLogLevel level, String messageFormat, Object... args)552     public void log(ChannelLogLevel level, String messageFormat, Object... args) {
553 
554     }
555   }
556 }
557