diff --git a/compiler/build.gradle b/compiler/build.gradle index 0fe03efbcd..6517b951b8 100644 --- a/compiler/build.gradle +++ b/compiler/build.gradle @@ -40,10 +40,17 @@ binaries.all { protobufCodeGenPlugins = ["java_plugin:$buildDir/binaries/java_pluginExecutable/java_plugin"] generateTestProto.dependsOn 'java_pluginExecutable' -test.dependsOn 'testGolden' +test.dependsOn('testGolden','testNanoGolden') task testGolden(type: Exec, dependsOn: 'generateTestProto') { executable "diff" args "$buildDir/generated-sources/test/io/grpc/testing/integration/TestServiceGrpc.java", "$projectDir/src/test/golden/TestService.java.txt" } + +task testNanoGolden(type: Exec, dependsOn: 'java_pluginExecutable') { + environment 'TEST_TMP_DIR', temporaryDir + commandLine './src/test/run_nano_test.sh' +} + + diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp index 2947b16f43..b2b3894e94 100644 --- a/compiler/src/java_plugin/cpp/java_generator.cpp +++ b/compiler/src/java_plugin/cpp/java_generator.cpp @@ -60,7 +60,8 @@ static inline string MessageFullJavaName(const Descriptor* desc) { } static void PrintMethodFields( - const ServiceDescriptor* service, map* vars, Printer* p) { + const ServiceDescriptor* service, map* vars, Printer* p, + bool generate_nano) { for (int i = 0; i < service->method_count(); ++i) { const MethodDescriptor* method = service->method(i); (*vars)["method_name"] = method->name(); @@ -82,14 +83,43 @@ static void PrintMethodFields( (*vars)["method_type"] = "UNARY"; } } - p->Print( - *vars, - "private static final $Method$<$input_type$,\n" - " $output_type$> $method_field_name$ =\n" - " $Method$.create(\n" - " $MethodType$.$method_type$, \"$method_name$\",\n" - " $ProtoUtils$.marshaller($input_type$.PARSER),\n" - " $ProtoUtils$.marshaller($output_type$.PARSER));\n"); + + if (generate_nano) { + // TODO(zsurocking): we're creating two Parsers for each method right now. + // We could instead create static Parsers and reuse them if some methods + // share the same request or response messages. + p->Print( + *vars, + "private static final $Method$<$input_type$,\n" + " $output_type$> $method_field_name$ =\n" + " $Method$.create(\n" + " $MethodType$.$method_type$, \"$method_name$\",\n" + " $NanoUtils$.<$input_type$>marshaller(\n" + " new io.grpc.nano.Parser<$input_type$>() {\n" + " @Override\n" + " public $input_type$ parse(" + "$CodedInputByteBufferNano$ input) throws IOException {\n" + " return $input_type$.parseFrom(input);\n" + " }\n" + " }),\n" + " $NanoUtils$.<$output_type$>marshaller(\n" + " new io.grpc.nano.Parser<$output_type$>() {\n" + " @Override\n" + " public $output_type$ parse(" + "$CodedInputByteBufferNano$ input) throws IOException {\n" + " return $output_type$.parseFrom(input);\n" + " }\n" + " }));\n"); + } else { + p->Print( + *vars, + "private static final $Method$<$input_type$,\n" + " $output_type$> $method_field_name$ =\n" + " $Method$.create(\n" + " $MethodType$.$method_type$, \"$method_name$\",\n" + " $ProtoUtils$.marshaller($input_type$.PARSER),\n" + " $ProtoUtils$.marshaller($output_type$.PARSER));\n"); + } } p->Print("\n"); } @@ -526,7 +556,8 @@ static void PrintBindServiceMethod(const ServiceDescriptor* service, static void PrintService(const ServiceDescriptor* service, map* vars, - Printer* p) { + Printer* p, + bool generate_nano) { (*vars)["service_name"] = service->name(); (*vars)["service_class_name"] = ServiceClassName(service); p->Print( @@ -535,7 +566,7 @@ static void PrintService(const ServiceDescriptor* service, "public class $service_class_name$ {\n\n"); p->Indent(); - PrintMethodFields(service, vars, p); + PrintMethodFields(service, vars, p, generate_nano); p->Print( *vars, @@ -583,7 +614,7 @@ static void PrintService(const ServiceDescriptor* service, p->Print("}\n"); } -void PrintImports(Printer* p) { +void PrintImports(Printer* p, bool generate_nano) { p->Print( "import static " "io.grpc.stub.Calls.createMethodDescriptor;\n" @@ -607,10 +638,14 @@ void PrintImports(Printer* p) { "io.grpc.stub.ServerCalls.asyncUnaryRequestCall;\n" "import static " "io.grpc.stub.ServerCalls.asyncStreamingRequestCall;\n\n"); + if (generate_nano) { + p->Print("import java.io.IOException;\n\n"); + } } void GenerateService(const ServiceDescriptor* service, - google::protobuf::io::ZeroCopyOutputStream* out) { + google::protobuf::io::ZeroCopyOutputStream* out, + bool generate_nano) { // All non-generated classes must be referred by fully qualified names to // avoid collision with generated classes. map vars; @@ -627,6 +662,7 @@ void GenerateService(const ServiceDescriptor* service, vars["ImmutableList"] = "com.google.common.collect.ImmutableList"; vars["MethodDescriptor"] = "io.grpc.MethodDescriptor"; vars["ProtoUtils"] = "io.grpc.proto.ProtoUtils"; + vars["NanoUtils"] = "io.grpc.nano.NanoUtils"; vars["StreamObserver"] = "io.grpc.stub.StreamObserver"; vars["Iterator"] = "java.util.Iterator"; vars["Map"] = "java.util.Map"; @@ -635,20 +671,22 @@ void GenerateService(const ServiceDescriptor* service, vars["Immutable"] = "javax.annotation.concurrent.Immutable"; vars["ListenableFuture"] = "com.google.common.util.concurrent.ListenableFuture"; + vars["CodedInputByteBufferNano"] = + "com.google.protobuf.nano.CodedInputByteBufferNano"; Printer printer(out, '$'); string package_name = ServiceJavaPackage(service->file()); printer.Print( "package $package_name$;\n\n", "package_name", package_name); - PrintImports(&printer); + PrintImports(&printer, generate_nano); // Package string is used to fully qualify method names. vars["Package"] = service->file()->package(); if (!vars["Package"].empty()) { vars["Package"].append("."); } - PrintService(service, &vars, &printer); + PrintService(service, &vars, &printer, generate_nano); } string ServiceJavaPackage(const FileDescriptor* file) { diff --git a/compiler/src/java_plugin/cpp/java_generator.h b/compiler/src/java_plugin/cpp/java_generator.h index 1af6b322f6..64941923d9 100644 --- a/compiler/src/java_plugin/cpp/java_generator.h +++ b/compiler/src/java_plugin/cpp/java_generator.h @@ -47,7 +47,8 @@ string ServiceClassName(const google::protobuf::ServiceDescriptor* service); // Writes the generated service interface into the given ZeroCopyOutputStream void GenerateService(const google::protobuf::ServiceDescriptor* service, - google::protobuf::io::ZeroCopyOutputStream* out); + google::protobuf::io::ZeroCopyOutputStream* out, + bool generate_nano); } // namespace java_grpc_generator diff --git a/compiler/src/java_plugin/cpp/java_plugin.cpp b/compiler/src/java_plugin/cpp/java_plugin.cpp index 762cc08dbc..41c8999e11 100644 --- a/compiler/src/java_plugin/cpp/java_plugin.cpp +++ b/compiler/src/java_plugin/cpp/java_plugin.cpp @@ -31,6 +31,16 @@ class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { const string& parameter, google::protobuf::compiler::GeneratorContext* context, string* error) const { + vector > options; + google::protobuf::compiler::ParseGeneratorParameter(parameter, &options); + + bool generate_nano = false; + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "nano" && options[i].second == "true") { + generate_nano = true; + } + } + string package_name = java_grpc_generator::ServiceJavaPackage(file); string package_filename = JavaPackageToDir(package_name); for (int i = 0; i < file->service_count(); ++i) { @@ -39,7 +49,7 @@ class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { + java_grpc_generator::ServiceClassName(service) + ".java"; std::unique_ptr output( context->Open(filename)); - java_grpc_generator::GenerateService(service, output.get()); + java_grpc_generator::GenerateService(service, output.get(), generate_nano); } return true; } diff --git a/compiler/src/test/golden/TestServiceNano.java.txt b/compiler/src/test/golden/TestServiceNano.java.txt new file mode 100644 index 0000000000..18f40fdd58 --- /dev/null +++ b/compiler/src/test/golden/TestServiceNano.java.txt @@ -0,0 +1,389 @@ +package io.grpc.testing.integration; + +import static io.grpc.stub.Calls.createMethodDescriptor; +import static io.grpc.stub.Calls.asyncUnaryCall; +import static io.grpc.stub.Calls.asyncServerStreamingCall; +import static io.grpc.stub.Calls.asyncClientStreamingCall; +import static io.grpc.stub.Calls.duplexStreamingCall; +import static io.grpc.stub.Calls.blockingUnaryCall; +import static io.grpc.stub.Calls.blockingServerStreamingCall; +import static io.grpc.stub.Calls.unaryFutureCall; +import static io.grpc.stub.ServerCalls.createMethodDefinition; +import static io.grpc.stub.ServerCalls.asyncUnaryRequestCall; +import static io.grpc.stub.ServerCalls.asyncStreamingRequestCall; + +import java.io.IOException; + +@javax.annotation.Generated("by gRPC proto compiler") +public class TestServiceGrpc { + + private static final io.grpc.stub.Method METHOD_UNARY_CALL = + io.grpc.stub.Method.create( + io.grpc.MethodType.UNARY, "UnaryCall", + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.SimpleRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.SimpleRequest.parseFrom(input); + } + }), + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.SimpleResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.SimpleResponse.parseFrom(input); + } + })); + private static final io.grpc.stub.Method METHOD_STREAMING_OUTPUT_CALL = + io.grpc.stub.Method.create( + io.grpc.MethodType.SERVER_STREAMING, "StreamingOutputCall", + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input); + } + }), + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input); + } + })); + private static final io.grpc.stub.Method METHOD_STREAMING_INPUT_CALL = + io.grpc.stub.Method.create( + io.grpc.MethodType.CLIENT_STREAMING, "StreamingInputCall", + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingInputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingInputCallRequest.parseFrom(input); + } + }), + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingInputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingInputCallResponse.parseFrom(input); + } + })); + private static final io.grpc.stub.Method METHOD_FULL_DUPLEX_CALL = + io.grpc.stub.Method.create( + io.grpc.MethodType.DUPLEX_STREAMING, "FullDuplexCall", + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input); + } + }), + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input); + } + })); + private static final io.grpc.stub.Method METHOD_HALF_DUPLEX_CALL = + io.grpc.stub.Method.create( + io.grpc.MethodType.DUPLEX_STREAMING, "HalfDuplexCall", + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallRequest parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallRequest.parseFrom(input); + } + }), + io.grpc.nano.NanoUtils.marshaller( + new io.grpc.nano.Parser() { + @Override + public io.grpc.testing.integration.Test.StreamingOutputCallResponse parse(com.google.protobuf.nano.CodedInputByteBufferNano input) throws IOException { + return io.grpc.testing.integration.Test.StreamingOutputCallResponse.parseFrom(input); + } + })); + + public static TestServiceStub newStub(io.grpc.Channel channel) { + return new TestServiceStub(channel, CONFIG); + } + + public static TestServiceBlockingStub newBlockingStub( + io.grpc.Channel channel) { + return new TestServiceBlockingStub(channel, CONFIG); + } + + public static TestServiceFutureStub newFutureStub( + io.grpc.Channel channel) { + return new TestServiceFutureStub(channel, CONFIG); + } + + public static final TestServiceServiceDescriptor CONFIG = + new TestServiceServiceDescriptor(); + + @javax.annotation.concurrent.Immutable + public static class TestServiceServiceDescriptor extends + io.grpc.stub.AbstractServiceDescriptor { + public final io.grpc.MethodDescriptor unaryCall; + public final io.grpc.MethodDescriptor streamingOutputCall; + public final io.grpc.MethodDescriptor streamingInputCall; + public final io.grpc.MethodDescriptor fullDuplexCall; + public final io.grpc.MethodDescriptor halfDuplexCall; + + private TestServiceServiceDescriptor() { + unaryCall = createMethodDescriptor( + "grpc.testing.TestService", METHOD_UNARY_CALL); + streamingOutputCall = createMethodDescriptor( + "grpc.testing.TestService", METHOD_STREAMING_OUTPUT_CALL); + streamingInputCall = createMethodDescriptor( + "grpc.testing.TestService", METHOD_STREAMING_INPUT_CALL); + fullDuplexCall = createMethodDescriptor( + "grpc.testing.TestService", METHOD_FULL_DUPLEX_CALL); + halfDuplexCall = createMethodDescriptor( + "grpc.testing.TestService", METHOD_HALF_DUPLEX_CALL); + } + + private TestServiceServiceDescriptor( + java.util.Map> methodMap) { + unaryCall = (io.grpc.MethodDescriptor) methodMap.get( + CONFIG.unaryCall.getName()); + streamingOutputCall = (io.grpc.MethodDescriptor) methodMap.get( + CONFIG.streamingOutputCall.getName()); + streamingInputCall = (io.grpc.MethodDescriptor) methodMap.get( + CONFIG.streamingInputCall.getName()); + fullDuplexCall = (io.grpc.MethodDescriptor) methodMap.get( + CONFIG.fullDuplexCall.getName()); + halfDuplexCall = (io.grpc.MethodDescriptor) methodMap.get( + CONFIG.halfDuplexCall.getName()); + } + + @java.lang.Override + protected TestServiceServiceDescriptor build( + java.util.Map> methodMap) { + return new TestServiceServiceDescriptor(methodMap); + } + + @java.lang.Override + public com.google.common.collect.ImmutableList> methods() { + return com.google.common.collect.ImmutableList.>of( + unaryCall, + streamingOutputCall, + streamingInputCall, + fullDuplexCall, + halfDuplexCall); + } + } + + public static interface TestService { + + public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request, + io.grpc.stub.StreamObserver responseObserver); + + public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request, + io.grpc.stub.StreamObserver responseObserver); + + public io.grpc.stub.StreamObserver streamingInputCall( + io.grpc.stub.StreamObserver responseObserver); + + public io.grpc.stub.StreamObserver fullDuplexCall( + io.grpc.stub.StreamObserver responseObserver); + + public io.grpc.stub.StreamObserver halfDuplexCall( + io.grpc.stub.StreamObserver responseObserver); + } + + public static interface TestServiceBlockingClient { + + public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request); + + public java.util.Iterator streamingOutputCall( + io.grpc.testing.integration.Test.StreamingOutputCallRequest request); + } + + public static interface TestServiceFutureClient { + + public com.google.common.util.concurrent.ListenableFuture unaryCall( + io.grpc.testing.integration.Test.SimpleRequest request); + } + + public static class TestServiceStub extends + io.grpc.stub.AbstractStub + implements TestService { + private TestServiceStub(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + super(channel, config); + } + + @java.lang.Override + protected TestServiceStub build(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + return new TestServiceStub(channel, config); + } + + @java.lang.Override + public void unaryCall(io.grpc.testing.integration.Test.SimpleRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncUnaryCall( + channel.newCall(config.unaryCall), request, responseObserver); + } + + @java.lang.Override + public void streamingOutputCall(io.grpc.testing.integration.Test.StreamingOutputCallRequest request, + io.grpc.stub.StreamObserver responseObserver) { + asyncServerStreamingCall( + channel.newCall(config.streamingOutputCall), request, responseObserver); + } + + @java.lang.Override + public io.grpc.stub.StreamObserver streamingInputCall( + io.grpc.stub.StreamObserver responseObserver) { + return asyncClientStreamingCall( + channel.newCall(config.streamingInputCall), responseObserver); + } + + @java.lang.Override + public io.grpc.stub.StreamObserver fullDuplexCall( + io.grpc.stub.StreamObserver responseObserver) { + return duplexStreamingCall( + channel.newCall(config.fullDuplexCall), responseObserver); + } + + @java.lang.Override + public io.grpc.stub.StreamObserver halfDuplexCall( + io.grpc.stub.StreamObserver responseObserver) { + return duplexStreamingCall( + channel.newCall(config.halfDuplexCall), responseObserver); + } + } + + public static class TestServiceBlockingStub extends + io.grpc.stub.AbstractStub + implements TestServiceBlockingClient { + private TestServiceBlockingStub(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + super(channel, config); + } + + @java.lang.Override + protected TestServiceBlockingStub build(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + return new TestServiceBlockingStub(channel, config); + } + + @java.lang.Override + public io.grpc.testing.integration.Test.SimpleResponse unaryCall(io.grpc.testing.integration.Test.SimpleRequest request) { + return blockingUnaryCall( + channel.newCall(config.unaryCall), request); + } + + @java.lang.Override + public java.util.Iterator streamingOutputCall( + io.grpc.testing.integration.Test.StreamingOutputCallRequest request) { + return blockingServerStreamingCall( + channel.newCall(config.streamingOutputCall), request); + } + } + + public static class TestServiceFutureStub extends + io.grpc.stub.AbstractStub + implements TestServiceFutureClient { + private TestServiceFutureStub(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + super(channel, config); + } + + @java.lang.Override + protected TestServiceFutureStub build(io.grpc.Channel channel, + TestServiceServiceDescriptor config) { + return new TestServiceFutureStub(channel, config); + } + + @java.lang.Override + public com.google.common.util.concurrent.ListenableFuture unaryCall( + io.grpc.testing.integration.Test.SimpleRequest request) { + return unaryFutureCall( + channel.newCall(config.unaryCall), request); + } + } + + public static io.grpc.ServerServiceDefinition bindService( + final TestService serviceImpl) { + return io.grpc.ServerServiceDefinition.builder("grpc.testing.TestService") + .addMethod(createMethodDefinition( + METHOD_UNARY_CALL, + asyncUnaryRequestCall( + new io.grpc.stub.ServerCalls.UnaryRequestMethod< + io.grpc.testing.integration.Test.SimpleRequest, + io.grpc.testing.integration.Test.SimpleResponse>() { + @java.lang.Override + public void invoke( + io.grpc.testing.integration.Test.SimpleRequest request, + io.grpc.stub.StreamObserver responseObserver) { + serviceImpl.unaryCall(request, responseObserver); + } + }))) + .addMethod(createMethodDefinition( + METHOD_STREAMING_OUTPUT_CALL, + asyncUnaryRequestCall( + new io.grpc.stub.ServerCalls.UnaryRequestMethod< + io.grpc.testing.integration.Test.StreamingOutputCallRequest, + io.grpc.testing.integration.Test.StreamingOutputCallResponse>() { + @java.lang.Override + public void invoke( + io.grpc.testing.integration.Test.StreamingOutputCallRequest request, + io.grpc.stub.StreamObserver responseObserver) { + serviceImpl.streamingOutputCall(request, responseObserver); + } + }))) + .addMethod(createMethodDefinition( + METHOD_STREAMING_INPUT_CALL, + asyncStreamingRequestCall( + new io.grpc.stub.ServerCalls.StreamingRequestMethod< + io.grpc.testing.integration.Test.StreamingInputCallRequest, + io.grpc.testing.integration.Test.StreamingInputCallResponse>() { + @java.lang.Override + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + return serviceImpl.streamingInputCall(responseObserver); + } + }))) + .addMethod(createMethodDefinition( + METHOD_FULL_DUPLEX_CALL, + asyncStreamingRequestCall( + new io.grpc.stub.ServerCalls.StreamingRequestMethod< + io.grpc.testing.integration.Test.StreamingOutputCallRequest, + io.grpc.testing.integration.Test.StreamingOutputCallResponse>() { + @java.lang.Override + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + return serviceImpl.fullDuplexCall(responseObserver); + } + }))) + .addMethod(createMethodDefinition( + METHOD_HALF_DUPLEX_CALL, + asyncStreamingRequestCall( + new io.grpc.stub.ServerCalls.StreamingRequestMethod< + io.grpc.testing.integration.Test.StreamingOutputCallRequest, + io.grpc.testing.integration.Test.StreamingOutputCallResponse>() { + @java.lang.Override + public io.grpc.stub.StreamObserver invoke( + io.grpc.stub.StreamObserver responseObserver) { + return serviceImpl.halfDuplexCall(responseObserver); + } + }))).build(); + } +} diff --git a/compiler/src/test/run_nano_test.sh b/compiler/src/test/run_nano_test.sh new file mode 100755 index 0000000000..c86243a6d3 --- /dev/null +++ b/compiler/src/test/run_nano_test.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [ -z "$TEST_TMP_DIR" ]; then + echo '$TEST_TMP_DIR not set' + exit 1; +fi + +cd $(dirname $0) + +INPUT_FILE="proto/test.proto" +OUTPUT_FILE="$TEST_TMP_DIR/TestServiceGrpc.src.jar" +GRPC_FILE="$TEST_TMP_DIR/io/grpc/testing/integration/TestServiceGrpc.java" +GOLDEN_FILE="golden/TestServiceNano.java.txt" + +protoc --plugin=protoc-gen-java_rpc=../../build/binaries/java_pluginExecutable/java_plugin \ + --java_rpc_out=nano=true:"$OUTPUT_FILE" "$INPUT_FILE" && \ + unzip -o -d "$TEST_TMP_DIR" "$OUTPUT_FILE" && \ + diff "$GRPC_FILE" "$GOLDEN_FILE" && \ + echo "PASS"