1 /* 2 * Copyright 2022 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.testing.integration; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotEquals; 21 22 import io.grpc.ChannelCredentials; 23 import io.grpc.ManagedChannelBuilder; 24 import io.grpc.Metadata; 25 import io.grpc.ServerBuilder; 26 import io.grpc.ServerCredentials; 27 import io.grpc.TlsChannelCredentials; 28 import io.grpc.TlsServerCredentials; 29 import io.grpc.internal.testing.TestUtils; 30 import io.grpc.netty.InternalNettyChannelBuilder; 31 import io.grpc.netty.InternalNettyServerBuilder; 32 import io.grpc.netty.NettyChannelBuilder; 33 import io.grpc.netty.NettyServerBuilder; 34 import io.grpc.okhttp.InternalOkHttpChannelBuilder; 35 import io.grpc.okhttp.InternalOkHttpServerBuilder; 36 import io.grpc.okhttp.OkHttpChannelBuilder; 37 import io.grpc.okhttp.OkHttpServerBuilder; 38 import io.grpc.stub.MetadataUtils; 39 import io.grpc.testing.TlsTesting; 40 import java.io.IOException; 41 import java.net.InetAddress; 42 import java.net.InetSocketAddress; 43 import java.util.Arrays; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 import org.junit.runners.Parameterized; 47 import org.junit.runners.Parameterized.Parameters; 48 49 /** 50 * Integration tests for GRPC over the various HTTP2 transports. 51 */ 52 @RunWith(Parameterized.class) 53 public class Http2Test extends AbstractInteropTest { 54 enum Transport { 55 NETTY, OKHTTP; 56 } 57 58 /** Parameterized test cases. */ 59 @Parameters(name = "client={0},server={1}") data()60 public static Iterable<Object[]> data() { 61 return Arrays.asList(new Object[][] { 62 {Transport.NETTY, Transport.NETTY}, 63 {Transport.OKHTTP, Transport.OKHTTP}, 64 {Transport.OKHTTP, Transport.NETTY}, 65 {Transport.NETTY, Transport.OKHTTP}, 66 }); 67 } 68 69 private final Transport clientType; 70 private final Transport serverType; 71 Http2Test(Transport clientType, Transport serverType)72 public Http2Test(Transport clientType, Transport serverType) { 73 this.clientType = clientType; 74 this.serverType = serverType; 75 } 76 77 @Override getServerBuilder()78 protected ServerBuilder<?> getServerBuilder() { 79 // Starts the server with HTTPS. 80 ServerCredentials serverCreds; 81 try { 82 serverCreds = TlsServerCredentials.create( 83 TlsTesting.loadCert("server1.pem"), TlsTesting.loadCert("server1.key")); 84 } catch (IOException ex) { 85 throw new RuntimeException(ex); 86 } 87 ServerBuilder<?> builder; 88 if (serverType == Transport.NETTY) { 89 NettyServerBuilder nettyBuilder = NettyServerBuilder.forPort(0, serverCreds) 90 .flowControlWindow(AbstractInteropTest.TEST_FLOW_CONTROL_WINDOW); 91 // Disable the default census stats tracer, use testing tracer instead. 92 InternalNettyServerBuilder.setStatsEnabled(nettyBuilder, false); 93 builder = nettyBuilder; 94 } else { 95 OkHttpServerBuilder okHttpBuilder = OkHttpServerBuilder.forPort(0, serverCreds) 96 .flowControlWindow(AbstractInteropTest.TEST_FLOW_CONTROL_WINDOW); 97 // Disable the default census stats tracer, use testing tracer instead. 98 InternalOkHttpServerBuilder.setStatsEnabled(okHttpBuilder, false); 99 builder = okHttpBuilder; 100 } 101 return builder 102 .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) 103 .addStreamTracerFactory(createCustomCensusTracerFactory()); 104 } 105 106 @Override createChannelBuilder()107 protected ManagedChannelBuilder<?> createChannelBuilder() { 108 ChannelCredentials channelCreds; 109 try { 110 channelCreds = TlsChannelCredentials.newBuilder() 111 .trustManager(TlsTesting.loadCert("ca.pem")) 112 .build(); 113 } catch (Exception ex) { 114 throw new RuntimeException(ex); 115 } 116 int port = ((InetSocketAddress) getListenAddress()).getPort(); 117 ManagedChannelBuilder<?> builder; 118 if (clientType == Transport.NETTY) { 119 NettyChannelBuilder nettyBuilder = NettyChannelBuilder 120 .forAddress("localhost", port, channelCreds) 121 .flowControlWindow(AbstractInteropTest.TEST_FLOW_CONTROL_WINDOW); 122 // Disable the default census stats interceptor, use testing interceptor instead. 123 InternalNettyChannelBuilder.setStatsEnabled(nettyBuilder, false); 124 builder = nettyBuilder; 125 } else { 126 OkHttpChannelBuilder okHttpBuilder = OkHttpChannelBuilder 127 .forAddress("localhost", port, channelCreds) 128 .flowControlWindow(AbstractInteropTest.TEST_FLOW_CONTROL_WINDOW); 129 // Disable the default census stats interceptor, use testing interceptor instead. 130 InternalOkHttpChannelBuilder.setStatsEnabled(okHttpBuilder, false); 131 builder = okHttpBuilder; 132 } 133 return builder 134 .overrideAuthority(TestUtils.TEST_SERVER_HOST) 135 .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) 136 .intercept(createCensusStatsClientInterceptor()); 137 } 138 139 @Test remoteAddr()140 public void remoteAddr() { 141 InetSocketAddress isa = (InetSocketAddress) obtainRemoteClientAddr(); 142 assertEquals(InetAddress.getLoopbackAddress(), isa.getAddress()); 143 // It should not be the same as the server 144 assertNotEquals(((InetSocketAddress) getListenAddress()).getPort(), isa.getPort()); 145 } 146 147 @Test localAddr()148 public void localAddr() throws Exception { 149 InetSocketAddress isa = (InetSocketAddress) obtainLocalServerAddr(); 150 assertEquals(InetAddress.getLoopbackAddress(), isa.getAddress()); 151 assertEquals(((InetSocketAddress) getListenAddress()).getPort(), isa.getPort()); 152 } 153 154 @Test contentLengthPermitted()155 public void contentLengthPermitted() throws Exception { 156 // Some third-party gRPC implementations (e.g., ServiceTalk) include Content-Length. The HTTP/2 157 // code starting in Netty 4.1.60.Final has special-cased handling of Content-Length, and may 158 // call uncommon methods on our custom headers implementation. 159 // https://github.com/grpc/grpc-java/issues/7953 160 Metadata contentLength = new Metadata(); 161 contentLength.put(Metadata.Key.of("content-length", Metadata.ASCII_STRING_MARSHALLER), "5"); 162 blockingStub 163 .withInterceptors(MetadataUtils.newAttachHeadersInterceptor(contentLength)) 164 .emptyCall(EMPTY); 165 } 166 } 167