From 274cbc3409bf31c4587643a904bb577986467bea Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Fri, 2 Dec 2016 14:46:31 -0800 Subject: [PATCH] Shade Netty transport, with tcnative The entire transport is shaded because we wouldn't want to collide with the unshaded form of grpc-netty. --- netty/shaded/build.gradle | 66 +++++++++++ .../io/grpc/netty/shaded/ShadingTest.java | 112 ++++++++++++++++++ settings.gradle | 2 + 3 files changed, 180 insertions(+) create mode 100644 netty/shaded/build.gradle create mode 100644 netty/shaded/src/testShadow/java/io/grpc/netty/shaded/ShadingTest.java diff --git a/netty/shaded/build.gradle b/netty/shaded/build.gradle new file mode 100644 index 00000000000..cf67cead2af --- /dev/null +++ b/netty/shaded/build.gradle @@ -0,0 +1,66 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1' + } +} + +apply plugin: 'com.github.johnrengelman.shadow' + +description = "gRPC: Netty Shaded" + +sourceSets { + testShadow {} +} + +dependencies { + compile project(':grpc-netty') + runtime libraries.netty_tcnative + testShadowCompile files(shadowJar), + configurations.shadow, + project(':grpc-testing-proto'), + project(':grpc-testing'), + libraries.truth + shadow project(':grpc-core') +} + +artifacts { + // We want uploadArchives to handle the shadowJar; we don't care about + // uploadShadow + archives shadowJar +} + +shadowJar { + classifier = null + dependencies { + include(project(':grpc-netty')) + include(dependency('io.netty:')) + } + relocate 'io.grpc.netty', 'io.grpc.netty.shaded.io.grpc.netty' + relocate 'io.netty', 'io.grpc.netty.shaded.io.netty' + // We have to be careful with these replacements as they must not match any + // string in NativeLibraryLoader, else they cause corruption. Note that + // this includes concatenation of string literals and constants. + relocate 'META-INF/native/libnetty', 'META-INF/native/libio_grpc_netty_shaded_netty' + relocate 'META-INF/native/netty', 'META-INF/native/io_grpc_netty_shaded_netty' + mergeServiceFiles() +} + +// This is a hack to have shadow plugin modify the uploadArchives POM's +// dependencies. If we delete the uploadShadow task, then the plugin will no +// longer modify the POM. This probably can break horribly with parallel build, +// but that's broken anyway with install/uploadArchives +uploadShadow.repositories.addAll(uploadArchives.repositories) +// And then we use a further hack to share that POM with install +install.repositories.mavenInstaller.pom = uploadArchives.repositories.mavenDeployer.pom + +task testShadow(type: Test) { + testClassesDirs = sourceSets.testShadow.output.classesDirs + classpath = sourceSets.testShadow.runtimeClasspath +} +compileTestShadowJava.options.compilerArgs = compileTestJava.options.compilerArgs +compileTestShadowJava.options.encoding = compileTestJava.options.encoding + +test.dependsOn testShadow diff --git a/netty/shaded/src/testShadow/java/io/grpc/netty/shaded/ShadingTest.java b/netty/shaded/src/testShadow/java/io/grpc/netty/shaded/ShadingTest.java new file mode 100644 index 00000000000..10b84fd35e6 --- /dev/null +++ b/netty/shaded/src/testShadow/java/io/grpc/netty/shaded/ShadingTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2017, gRPC Authors All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.netty.shaded; + +import static com.google.common.truth.Truth.assertThat; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.internal.testing.TestUtils; +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder; +import io.grpc.netty.shaded.io.netty.handler.ssl.SslProvider; +import io.grpc.stub.StreamObserver; +import io.grpc.testing.protobuf.SimpleRequest; +import io.grpc.testing.protobuf.SimpleResponse; +import io.grpc.testing.protobuf.SimpleServiceGrpc; +import io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceBlockingStub; +import io.grpc.testing.protobuf.SimpleServiceGrpc.SimpleServiceImplBase; +import java.util.concurrent.TimeUnit; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link Shading}. */ +@RunWith(JUnit4.class) +public final class ShadingTest { + private ManagedChannel channel; + private Server server; + + @After + public void tearDown() throws Exception { + if (channel != null) { + channel.shutdownNow(); + channel.awaitTermination(1, TimeUnit.SECONDS); + } + if (server != null) { + server.shutdownNow(); + server.awaitTermination(1, TimeUnit.SECONDS); + } + } + + /** Verify that normal Netty didn't leak into the test runtime. */ + @Test(expected = ClassNotFoundException.class) + public void noNormalNetty() throws Exception { + Class.forName("io.grpc.netty.NettyServerBuilder"); + } + + @Test + public void serviceLoaderFindsNetty() throws Exception { + assertThat(ServerBuilder.forPort(0)).isInstanceOf(NettyServerBuilder.class); + assertThat(ManagedChannelBuilder.forAddress("localhost", 1234)) + .isInstanceOf(NettyChannelBuilder.class); + } + + @Test + public void basic() throws Exception { + server = ServerBuilder.forPort(0) + .addService(new SimpleServiceImpl()) + .build().start(); + channel = ManagedChannelBuilder + .forAddress("localhost", server.getPort()) + .usePlaintext(true) + .build(); + SimpleServiceBlockingStub stub = SimpleServiceGrpc.newBlockingStub(channel); + assertThat(SimpleResponse.getDefaultInstance()) + .isEqualTo(stub.unaryRpc(SimpleRequest.getDefaultInstance())); + } + + @Test + public void tcnative() throws Exception { + server = NettyServerBuilder.forPort(0) + .useTransportSecurity(TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key")) + .addService(new SimpleServiceImpl()) + .build().start(); + channel = NettyChannelBuilder + .forAddress("localhost", server.getPort()) + .sslContext( + GrpcSslContexts.configure(SslContextBuilder.forClient(), SslProvider.OPENSSL) + .trustManager(TestUtils.loadCert("ca.pem")).build()) + .overrideAuthority("foo.test.google.fr") + .build(); + SimpleServiceBlockingStub stub = SimpleServiceGrpc.newBlockingStub(channel); + assertThat(SimpleResponse.getDefaultInstance()) + .isEqualTo(stub.unaryRpc(SimpleRequest.getDefaultInstance())); + } + + private static class SimpleServiceImpl extends SimpleServiceImplBase { + @Override public void unaryRpc(SimpleRequest req, StreamObserver obs) { + obs.onNext(SimpleResponse.getDefaultInstance()); + obs.onCompleted(); + } + } +} diff --git a/settings.gradle b/settings.gradle index 780e8c69d1d..cacec138a0d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ include ":grpc-protobuf" include ":grpc-protobuf-lite" include ":grpc-protobuf-nano" include ":grpc-netty" +include ":grpc-netty-shaded" include ":grpc-grpclb" include ":grpc-testing" include ":grpc-testing-proto" @@ -27,6 +28,7 @@ project(':grpc-protobuf').projectDir = "$rootDir/protobuf" as File project(':grpc-protobuf-lite').projectDir = "$rootDir/protobuf-lite" as File project(':grpc-protobuf-nano').projectDir = "$rootDir/protobuf-nano" as File project(':grpc-netty').projectDir = "$rootDir/netty" as File +project(':grpc-netty-shaded').projectDir = "$rootDir/netty/shaded" as File project(':grpc-grpclb').projectDir = "$rootDir/grpclb" as File project(':grpc-testing').projectDir = "$rootDir/testing" as File project(':grpc-testing-proto').projectDir = "$rootDir/testing-proto" as File