Merge pull request #1519 from jtattermusch/csharp_protoc_plugin

C# gRPC protoc plugin
pull/1533/head^2
Michael Lumish 10 years ago
commit 7a24ecb303
  1. 15
      BUILD
  2. 34
      Makefile
  3. 15
      build.json
  4. 480
      src/compiler/csharp_generator.cc
  5. 45
      src/compiler/csharp_generator.h
  6. 50
      src/compiler/csharp_generator_helpers.h
  7. 72
      src/compiler/csharp_plugin.cc
  8. 23
      src/compiler/generator_helpers.h
  9. 2
      src/csharp/Grpc.Examples.MathClient/MathClient.cs
  10. 2
      src/csharp/Grpc.Examples.MathServer/MathServer.cs
  11. 6
      src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
  12. 14
      src/csharp/Grpc.Examples/MathExamples.cs
  13. 168
      src/csharp/Grpc.Examples/MathGrpc.cs
  14. 2
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  15. 4
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  16. 26
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  17. 6
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  18. 2
      src/csharp/Grpc.IntegrationTesting/InteropServer.cs
  19. 159
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  20. 2
      src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
  21. 43
      src/csharp/generate_proto_csharp.sh

15
BUILD

@ -737,6 +737,8 @@ cc_library(
"src/compiler/config.h",
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h",
"src/compiler/csharp_generator.h",
"src/compiler/csharp_generator_helpers.h",
"src/compiler/generator_helpers.h",
"src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h",
@ -746,6 +748,7 @@ cc_library(
"src/compiler/ruby_generator_map-inl.h",
"src/compiler/ruby_generator_string-inl.h",
"src/compiler/cpp_generator.cc",
"src/compiler/csharp_generator.cc",
"src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc",
@ -793,6 +796,18 @@ cc_binary(
)
cc_binary(
name = "grpc_csharp_plugin",
srcs = [
"src/compiler/csharp_plugin.cc",
],
deps = [
"//external:protobuf_compiler",
":grpc_plugin_support",
],
)
cc_binary(
name = "grpc_objective_c_plugin",
srcs = [

@ -490,7 +490,7 @@ endif
.SECONDARY = %.pb.h %.pb.cc
PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
ifeq ($(DEP_MISSING),)
all: static shared plugins
dep_error:
@ -675,6 +675,7 @@ end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin
grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
@ -2249,6 +2250,8 @@ else
$(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(prefix)/bin/grpc_cpp_plugin
$(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin
$(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin
$(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin
@ -3174,6 +3177,7 @@ endif
LIBGRPC_PLUGIN_SUPPORT_SRC = \
src/compiler/cpp_generator.cc \
src/compiler/csharp_generator.cc \
src/compiler/objective_c_generator.cc \
src/compiler/python_generator.cc \
src/compiler/ruby_generator.cc \
@ -7099,6 +7103,34 @@ ifneq ($(NO_DEPS),true)
endif
GRPC_CSHARP_PLUGIN_SRC = \
src/compiler/csharp_plugin.cc \
GRPC_CSHARP_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CSHARP_PLUGIN_SRC))))
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/grpc_csharp_plugin: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/grpc_csharp_plugin: $(PROTOBUF_DEP) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
$(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_CSHARP_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_csharp_plugin
endif
$(OBJDIR)/$(CONFIG)/src/compiler/csharp_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
deps_grpc_csharp_plugin: $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
-include $(GRPC_CSHARP_PLUGIN_OBJS:.o=.dep)
endif
GRPC_OBJECTIVE_C_PLUGIN_SRC = \
src/compiler/objective_c_plugin.cc \

@ -563,6 +563,8 @@
"src/compiler/config.h",
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers.h",
"src/compiler/csharp_generator.h",
"src/compiler/csharp_generator_helpers.h",
"src/compiler/generator_helpers.h",
"src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h",
@ -574,6 +576,7 @@
],
"src": [
"src/compiler/cpp_generator.cc",
"src/compiler/csharp_generator.cc",
"src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc"
@ -1931,6 +1934,18 @@
],
"secure": "no"
},
{
"name": "grpc_csharp_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/csharp_plugin.cc"
],
"deps": [
"grpc_plugin_support"
],
"secure": "no"
},
{
"name": "grpc_objective_c_plugin",
"build": "protoc",

@ -0,0 +1,480 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <cctype>
#include <map>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/csharp_generator_helpers.h"
#include "src/compiler/csharp_generator.h"
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::Descriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using grpc_generator::MethodType;
using grpc_generator::GetMethodType;
using grpc_generator::METHODTYPE_NO_STREAMING;
using grpc_generator::METHODTYPE_CLIENT_STREAMING;
using grpc_generator::METHODTYPE_SERVER_STREAMING;
using grpc_generator::METHODTYPE_BIDI_STREAMING;
using std::map;
using std::vector;
namespace grpc_csharp_generator {
namespace {
std::string GetCSharpNamespace(const FileDescriptor* file) {
// TODO(jtattermusch): this should be based on csharp_namespace option
return file->package();
}
std::string GetMessageType(const Descriptor* message) {
// TODO(jtattermusch): this has to match with C# protobuf generator
return message->name();
}
std::string GetServiceClassName(const ServiceDescriptor* service) {
return service->name();
}
std::string GetClientInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name() + "Client";
}
std::string GetClientClassName(const ServiceDescriptor* service) {
return service->name() + "Client";
}
std::string GetServerInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name();
}
std::string GetCSharpMethodType(MethodType method_type) {
switch (method_type) {
case METHODTYPE_NO_STREAMING:
return "MethodType.Unary";
case METHODTYPE_CLIENT_STREAMING:
return "MethodType.ClientStreaming";
case METHODTYPE_SERVER_STREAMING:
return "MethodType.ServerStreaming";
case METHODTYPE_BIDI_STREAMING:
return "MethodType.DuplexStreaming";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetServiceNameFieldName() {
return "__ServiceName";
}
std::string GetMarshallerFieldName(const Descriptor *message) {
return "__Marshaller_" + message->name();
}
std::string GetMethodFieldName(const MethodDescriptor *method) {
return "__Method_" + method->name();
}
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
if (method->client_streaming()) {
return "";
}
return GetMessageType(method->input_type()) + " request, ";
}
std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
return "Task<" + GetMessageType(method->output_type()) + ">";
case METHODTYPE_CLIENT_STREAMING:
return "AsyncClientStreamingCall<" + GetMessageType(method->input_type())
+ ", " + GetMessageType(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
return "AsyncServerStreamingCall<" + GetMessageType(method->output_type())
+ ">";
case METHODTYPE_BIDI_STREAMING:
return "AsyncDuplexStreamingCall<" + GetMessageType(method->input_type())
+ ", " + GetMessageType(method->output_type()) + ">";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodRequestParamServer(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_SERVER_STREAMING:
return GetMessageType(method->input_type()) + " request";
case METHODTYPE_CLIENT_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "IAsyncStreamReader<" + GetMessageType(method->input_type())
+ "> requestStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodReturnTypeServer(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_CLIENT_STREAMING:
return "Task<" + GetMessageType(method->output_type()) + ">";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return "Task";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
std::string GetMethodResponseStreamMaybe(const MethodDescriptor *method) {
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
case METHODTYPE_CLIENT_STREAMING:
return "";
case METHODTYPE_SERVER_STREAMING:
case METHODTYPE_BIDI_STREAMING:
return ", IServerStreamWriter<" + GetMessageType(method->output_type())
+ "> responseStream";
}
GOOGLE_LOG(FATAL)<< "Can't get here.";
return "";
}
// Gets vector of all messages used as input or output types.
std::vector<const Descriptor*> GetUsedMessages(
const ServiceDescriptor *service) {
std::set<const Descriptor*> descriptor_set;
std::vector<const Descriptor*> result; // vector is to maintain stable ordering
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
if (descriptor_set.find(method->input_type()) == descriptor_set.end()) {
descriptor_set.insert(method->input_type());
result.push_back(method->input_type());
}
if (descriptor_set.find(method->output_type()) == descriptor_set.end()) {
descriptor_set.insert(method->output_type());
result.push_back(method->output_type());
}
}
return result;
}
void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) {
std::vector<const Descriptor*> used_messages = GetUsedMessages(service);
for (size_t i = 0; i < used_messages.size(); i++) {
const Descriptor *message = used_messages[i];
out->Print(
"static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => arg.ToByteArray(), $type$.ParseFrom);\n",
"fieldname", GetMarshallerFieldName(message), "type",
GetMessageType(message));
}
out->Print("\n");
}
void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) {
out->Print(
"static readonly Method<$request$, $response$> $fieldname$ = new Method<$request$, $response$>(\n",
"fieldname", GetMethodFieldName(method), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
out->Indent();
out->Indent();
out->Print("$methodtype$,\n", "methodtype",
GetCSharpMethodType(GetMethodType(method)));
out->Print("\"$methodname$\",\n", "methodname", method->name());
out->Print("$requestmarshaller$,\n", "requestmarshaller",
GetMarshallerFieldName(method->input_type()));
out->Print("$responsemarshaller$);\n", "responsemarshaller",
GetMarshallerFieldName(method->output_type()));
out->Print("\n");
out->Outdent();
out->Outdent();
}
void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// client-side stub interface\n");
out->Print("public interface $name$\n", "name",
GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
MethodType method_type = GetMethodType(method);
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"$response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken));\n",
"methodname", method->name(), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
}
std::string method_name = method->name();
if (method_type == METHODTYPE_NO_STREAMING) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"$returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken));\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side interface\n");
out->Print("public interface $name$\n", "name",
GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print("$returntype$ $methodname$(ServerCallContext context, $request$$response_stream_maybe$);\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe",
GetMethodResponseStreamMaybe(method));
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("// client stub\n");
out->Print(
"public class $name$ : AbstractStub<$name$, StubConfiguration>, $interface$\n",
"name", GetClientClassName(service), "interface",
GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
// constructors
out->Print(
"public $name$(Channel channel) : this(channel, StubConfiguration.Default)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print(
"public $name$(Channel channel, StubConfiguration config) : base(channel, config)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
MethodType method_type = GetMethodType(method);
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"public $response$ $methodname$($request$ request, CancellationToken token = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetMessageType(method->input_type()), "response",
GetMessageType(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request, token);\n");
out->Outdent();
out->Print("}\n");
}
std::string method_name = method->name();
if (method_type == METHODTYPE_NO_STREAMING) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"public $returntype$ $methodname$($request_maybe$CancellationToken token = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($servicenamefield$, $methodfield$);\n",
"servicenamefield", GetServiceNameFieldName(), "methodfield",
GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request, token);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call, token);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request, token);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call, token);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Outdent();
out->Print("}\n");
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
out->Print(
"// creates service definition that can be registered with a server\n");
out->Print(
"public static ServerServiceDefinition BindService($interface$ serviceImpl)\n",
"interface", GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print(
"return ServerServiceDefinition.CreateBuilder($servicenamefield$)\n",
"servicenamefield", GetServiceNameFieldName());
out->Indent();
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print(".AddMethod($methodfield$, serviceImpl.$methodname$)",
"methodfield", GetMethodFieldName(method), "methodname",
method->name());
if (i == service->method_count() - 1) {
out->Print(".Build();");
}
out->Print("\n");
}
out->Outdent();
out->Outdent();
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
out->Print("// creates a new client stub\n");
out->Print("public static $interface$ NewStub(Channel channel)\n",
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $classname$(channel);\n", "classname",
GetClientClassName(service));
out->Outdent();
out->Print("}\n");
out->Print("\n");
out->Print("// creates a new client stub\n");
out->Print(
"public static $interface$ NewStub(Channel channel, StubConfiguration config)\n",
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $classname$(channel, config);\n", "classname",
GetClientClassName(service));
out->Outdent();
out->Print("}\n");
}
void GenerateService(Printer* out, const ServiceDescriptor *service) {
out->Print("public static class $classname$\n", "classname",
GetServiceClassName(service));
out->Print("{\n");
out->Indent();
out->Print("static readonly string $servicenamefield$ = \"$servicename$\";\n",
"servicenamefield", GetServiceNameFieldName(), "servicename",
service->full_name());
out->Print("\n");
GenerateMarshallerFields(out, service);
for (int i = 0; i < service->method_count(); i++) {
GenerateStaticMethodField(out, service->method(i));
}
GenerateClientInterface(out, service);
GenerateServerInterface(out, service);
GenerateClientStub(out, service);
GenerateBindServiceMethod(out, service);
GenerateNewStubMethods(out, service);
out->Outdent();
out->Print("}\n");
}
} // anonymous namespace
grpc::string GetServices(const FileDescriptor *file) {
grpc::string output;
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
// Don't write out any output if there no services, to avoid empty service
// files being generated for proto files that don't declare any.
if (file->service_count() == 0) {
return output;
}
// Write out a file header.
out.Print("// Generated by the protocol buffer compiler. DO NOT EDIT!\n");
out.Print("// source: $filename$\n", "filename", file->name());
out.Print("#region Designer generated code\n");
out.Print("\n");
out.Print("using System;\n");
out.Print("using System.Threading;\n");
out.Print("using System.Threading.Tasks;\n");
out.Print("using Grpc.Core;\n");
// TODO(jtattermusch): add using for protobuf message classes
out.Print("\n");
out.Print("namespace $namespace$ {\n", "namespace", GetCSharpNamespace(file));
out.Indent();
for (int i = 0; i < file->service_count(); i++) {
GenerateService(&out, file->service(i));
}
out.Outdent();
out.Print("}\n");
out.Print("#endregion\n");
return output;
}
} // namespace grpc_csharp_generator

@ -0,0 +1,45 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H
#include "src/compiler/config.h"
namespace grpc_csharp_generator {
grpc::string GetServices(const grpc::protobuf::FileDescriptor *file);
} // namespace grpc_csharp_generator
#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_H

@ -0,0 +1,50 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H
#define GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
namespace grpc_csharp_generator {
inline bool ServicesFilename(const grpc::protobuf::FileDescriptor *file,
grpc::string *file_name_or_error) {
*file_name_or_error = grpc_generator::FileNameInUpperCamel(file) + "Grpc.cs";
return true;
}
} // namespace grpc_csharp_generator
#endif // GRPC_INTERNAL_COMPILER_CSHARP_GENERATOR_HELPERS_H

@ -0,0 +1,72 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Generates C# gRPC service interface out of Protobuf IDL.
#include <memory>
#include "src/compiler/config.h"
#include "src/compiler/csharp_generator.h"
#include "src/compiler/csharp_generator_helpers.h"
class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
CSharpGrpcGenerator() {}
~CSharpGrpcGenerator() {}
bool Generate(const grpc::protobuf::FileDescriptor *file,
const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const {
grpc::string code = grpc_csharp_generator::GetServices(file);
if (code.size() == 0) {
return true; // don't generate a file if there are no services
}
// Get output file name.
grpc::string file_name;
if (!grpc_csharp_generator::ServicesFilename(file, &file_name)) {
return false;
}
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(file_name));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
return true;
}
};
int main(int argc, char *argv[]) {
CSharpGrpcGenerator generator;
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}

@ -116,6 +116,29 @@ inline grpc::string FileNameInUpperCamel(const grpc::protobuf::FileDescriptor *f
return LowerUnderscoreToUpperCamel(StripProto(file->name()));
}
enum MethodType {
METHODTYPE_NO_STREAMING,
METHODTYPE_CLIENT_STREAMING,
METHODTYPE_SERVER_STREAMING,
METHODTYPE_BIDI_STREAMING
};
inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method) {
if (method->client_streaming()) {
if (method->server_streaming()) {
return METHODTYPE_BIDI_STREAMING;
} else {
return METHODTYPE_CLIENT_STREAMING;
}
} else {
if (method->server_streaming()) {
return METHODTYPE_SERVER_STREAMING;
} else {
return METHODTYPE_NO_STREAMING;
}
}
}
} // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H

@ -43,7 +43,7 @@ namespace math
using (Channel channel = new Channel("127.0.0.1:23456"))
{
MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);
Math.IMathClient stub = new Math.MathClient(channel);
MathExamples.DivExample(stub);
MathExamples.DivAsyncExample(stub).Wait();

@ -45,7 +45,7 @@ namespace math
GrpcEnvironment.Initialize();
Server server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, 23456);
server.Start();

@ -50,7 +50,7 @@ namespace math.Tests
string host = "localhost";
Server server;
Channel channel;
MathGrpc.IMathServiceClient client;
Math.IMathClient client;
[TestFixtureSetUp]
public void Init()
@ -58,7 +58,7 @@ namespace math.Tests
GrpcEnvironment.Initialize();
server = new Server();
server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
server.AddServiceDefinition(Math.BindService(new MathServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort);
server.Start();
channel = new Channel(host + ":" + port);
@ -69,7 +69,7 @@ namespace math.Tests
{
headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef"));
});
client = MathGrpc.NewStub(channel, stubConfig);
client = Math.NewStub(channel, stubConfig);
}
[TestFixtureTearDown]

@ -39,34 +39,34 @@ namespace math
{
public static class MathExamples
{
public static void DivExample(MathGrpc.IMathServiceClient stub)
public static void DivExample(Math.IMathClient stub)
{
DivReply result = stub.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build());
Console.WriteLine("Div Result: " + result);
}
public static async Task DivAsyncExample(MathGrpc.IMathServiceClient stub)
public static async Task DivAsyncExample(Math.IMathClient stub)
{
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = await resultTask;
Console.WriteLine("DivAsync Result: " + result);
}
public static async Task DivAsyncWithCancellationExample(MathGrpc.IMathServiceClient stub)
public static async Task DivAsyncWithCancellationExample(Math.IMathClient stub)
{
Task<DivReply> resultTask = stub.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build());
DivReply result = await resultTask;
Console.WriteLine(result);
}
public static async Task FibExample(MathGrpc.IMathServiceClient stub)
public static async Task FibExample(Math.IMathClient stub)
{
var call = stub.Fib(new FibArgs.Builder { Limit = 5 }.Build());
List<Num> result = await call.ResponseStream.ToList();
Console.WriteLine("Fib Result: " + string.Join("|", result));
}
public static async Task SumExample(MathGrpc.IMathServiceClient stub)
public static async Task SumExample(Math.IMathClient stub)
{
var numbers = new List<Num>
{
@ -80,7 +80,7 @@ namespace math
Console.WriteLine("Sum Result: " + await call.Result);
}
public static async Task DivManyExample(MathGrpc.IMathServiceClient stub)
public static async Task DivManyExample(Math.IMathClient stub)
{
var divArgsList = new List<DivArgs>
{
@ -93,7 +93,7 @@ namespace math
Console.WriteLine("DivMany Result: " + string.Join("|", await call.ResponseStream.ToList()));
}
public static async Task DependendRequestsExample(MathGrpc.IMathServiceClient stub)
public static async Task DependendRequestsExample(Math.IMathClient stub)
{
var numbers = new List<Num>
{

@ -1,164 +1,122 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto
#region Designer generated code
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace math
namespace math {
public static class Math
{
/// <summary>
/// Math service definitions (this is handwritten version of code that will normally be generated).
/// </summary>
public class MathGrpc
{
static readonly string ServiceName = "/math.Math";
static readonly string __ServiceName = "math.Math";
static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
static readonly Marshaller<FibArgs> FibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
static readonly Marshaller<DivArgs> __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
static readonly Marshaller<DivReply> __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
static readonly Marshaller<FibArgs> __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
static readonly Marshaller<Num> __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>(
static readonly Method<DivArgs, DivReply> __Method_Div = new Method<DivArgs, DivReply>(
MethodType.Unary,
"Div",
DivArgsMarshaller,
DivReplyMarshaller);
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<DivArgs, DivReply> __Method_DivMany = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
"DivMany",
__Marshaller_DivArgs,
__Marshaller_DivReply);
static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>(
static readonly Method<FibArgs, Num> __Method_Fib = new Method<FibArgs, Num>(
MethodType.ServerStreaming,
"Fib",
FibArgsMarshaller,
NumMarshaller);
__Marshaller_FibArgs,
__Marshaller_Num);
static readonly Method<Num, Num> SumMethod = new Method<Num, Num>(
static readonly Method<Num, Num> __Method_Sum = new Method<Num, Num>(
MethodType.ClientStreaming,
"Sum",
NumMarshaller,
NumMarshaller);
static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>(
MethodType.DuplexStreaming,
"DivMany",
DivArgsMarshaller,
DivReplyMarshaller);
__Marshaller_Num,
__Marshaller_Num);
public interface IMathServiceClient
// client-side stub interface
public interface IMathClient
{
DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken));
Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken));
AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken));
AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken));
}
AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken));
// server-side interface
public interface IMath
{
Task<DivReply> Div(ServerCallContext context, DivArgs request);
Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream);
Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream);
Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream);
}
public class MathServiceClientStub : AbstractStub<MathServiceClientStub, StubConfiguration>, IMathServiceClient
// client stub
public class MathClient : AbstractStub<MathClient, StubConfiguration>, IMathClient
{
public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default)
public MathClient(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config)
public MathClient(Channel channel, StubConfiguration config) : base(channel, config)
{
}
public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivMethod);
var call = CreateCall(__ServiceName, __Method_Div);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivMethod);
var call = CreateCall(__ServiceName, __Method_Div);
return Calls.AsyncUnaryCall(call, request, token);
}
public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_DivMany);
return Calls.AsyncDuplexStreamingCall(call, token);
}
public AsyncServerStreamingCall<Num> Fib(FibArgs request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, FibMethod);
var call = CreateCall(__ServiceName, __Method_Fib);
return Calls.AsyncServerStreamingCall(call, request, token);
}
public AsyncClientStreamingCall<Num, Num> Sum(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, SumMethod);
var call = CreateCall(__ServiceName, __Method_Sum);
return Calls.AsyncClientStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<DivArgs, DivReply> DivMany(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(ServiceName, DivManyMethod);
return Calls.AsyncDuplexStreamingCall(call, token);
}
}
// server-side interface
public interface IMathService
{
Task<DivReply> Div(ServerCallContext context, DivArgs request);
Task Fib(ServerCallContext context, FibArgs request, IServerStreamWriter<Num> responseStream);
Task<Num> Sum(ServerCallContext context, IAsyncStreamReader<Num> requestStream);
Task DivMany(ServerCallContext context, IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream);
}
public static ServerServiceDefinition BindService(IMathService serviceImpl)
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(IMath serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(ServiceName)
.AddMethod(DivMethod, serviceImpl.Div)
.AddMethod(FibMethod, serviceImpl.Fib)
.AddMethod(SumMethod, serviceImpl.Sum)
.AddMethod(DivManyMethod, serviceImpl.DivMany).Build();
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div)
.AddMethod(__Method_DivMany, serviceImpl.DivMany)
.AddMethod(__Method_Fib, serviceImpl.Fib)
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
public static IMathServiceClient NewStub(Channel channel)
// creates a new client stub
public static IMathClient NewStub(Channel channel)
{
return new MathServiceClientStub(channel);
return new MathClient(channel);
}
public static IMathServiceClient NewStub(Channel channel, StubConfiguration config)
// creates a new client stub
public static IMathClient NewStub(Channel channel, StubConfiguration config)
{
return new MathServiceClientStub(channel, config);
return new MathClient(channel, config);
}
}
}
#endregion

@ -44,7 +44,7 @@ namespace math
/// <summary>
/// Implementation of MathService server
/// </summary>
public class MathServiceImpl : MathGrpc.IMathService
public class MathServiceImpl : Math.IMath
{
public Task<DivReply> Div(ServerCallContext context, DivArgs request)
{

@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C61154BA-DD4A-4838-8420-0162A28925E0}</ProjectGuid>
<OutputType>Library</OutputType>
@ -72,7 +72,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestServiceGrpc.cs" />
<Compile Include="Empty.cs" />
<Compile Include="Messages.cs" />
<Compile Include="InteropClientServerTest.cs" />
@ -80,6 +79,7 @@
<Compile Include="InteropServer.cs" />
<Compile Include="InteropClient.cs" />
<Compile Include="TestCredentials.cs" />
<Compile Include="TestGrpc.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -132,14 +132,14 @@ namespace Grpc.IntegrationTesting
stubConfig = new StubConfiguration(OAuth2InterceptorFactory.Create(credential));
}
TestServiceGrpc.ITestServiceClient client = new TestServiceGrpc.TestServiceClientStub(channel, stubConfig);
TestService.ITestServiceClient client = new TestService.TestServiceClient(channel, stubConfig);
RunTestCase(options.testCase, client);
}
GrpcEnvironment.Shutdown();
}
private void RunTestCase(string testCase, TestServiceGrpc.ITestServiceClient client)
private void RunTestCase(string testCase, TestService.ITestServiceClient client)
{
switch (testCase)
{
@ -181,7 +181,7 @@ namespace Grpc.IntegrationTesting
}
}
public static void RunEmptyUnary(TestServiceGrpc.ITestServiceClient client)
public static void RunEmptyUnary(TestService.ITestServiceClient client)
{
Console.WriteLine("running empty_unary");
var response = client.EmptyCall(Empty.DefaultInstance);
@ -189,7 +189,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunLargeUnary(TestServiceGrpc.ITestServiceClient client)
public static void RunLargeUnary(TestService.ITestServiceClient client)
{
Console.WriteLine("running large_unary");
var request = SimpleRequest.CreateBuilder()
@ -205,7 +205,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunClientStreaming(TestServiceGrpc.ITestServiceClient client)
public static void RunClientStreaming(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -222,7 +222,7 @@ namespace Grpc.IntegrationTesting
}).Wait();
}
public static void RunServerStreaming(TestServiceGrpc.ITestServiceClient client)
public static void RunServerStreaming(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -248,7 +248,7 @@ namespace Grpc.IntegrationTesting
}).Wait();
}
public static void RunPingPong(TestServiceGrpc.ITestServiceClient client)
public static void RunPingPong(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -303,7 +303,7 @@ namespace Grpc.IntegrationTesting
}).Wait();
}
public static void RunEmptyStream(TestServiceGrpc.ITestServiceClient client)
public static void RunEmptyStream(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -318,7 +318,7 @@ namespace Grpc.IntegrationTesting
}).Wait();
}
public static void RunServiceAccountCreds(TestServiceGrpc.ITestServiceClient client)
public static void RunServiceAccountCreds(TestService.ITestServiceClient client)
{
Console.WriteLine("running service_account_creds");
var request = SimpleRequest.CreateBuilder()
@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunComputeEngineCreds(TestServiceGrpc.ITestServiceClient client)
public static void RunComputeEngineCreds(TestService.ITestServiceClient client)
{
Console.WriteLine("running compute_engine_creds");
var request = SimpleRequest.CreateBuilder()
@ -358,7 +358,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunCancelAfterBegin(TestServiceGrpc.ITestServiceClient client)
public static void RunCancelAfterBegin(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -383,7 +383,7 @@ namespace Grpc.IntegrationTesting
}).Wait();
}
public static void RunCancelAfterFirstResponse(TestServiceGrpc.ITestServiceClient client)
public static void RunCancelAfterFirstResponse(TestService.ITestServiceClient client)
{
Task.Run(async () =>
{
@ -419,7 +419,7 @@ namespace Grpc.IntegrationTesting
}
// This is not an official interop test, but it's useful.
public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client)
public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client)
{
BenchmarkUtil.RunBenchmark(10000, 10000,
() => { client.EmptyCall(Empty.DefaultInstance); });

@ -50,7 +50,7 @@ namespace Grpc.IntegrationTesting
string host = "localhost";
Server server;
Channel channel;
TestServiceGrpc.ITestServiceClient client;
TestService.ITestServiceClient client;
[TestFixtureSetUp]
public void Init()
@ -58,7 +58,7 @@ namespace Grpc.IntegrationTesting
GrpcEnvironment.Initialize();
server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
int port = server.AddListeningPort(host, Server.PickUnusedPort, TestCredentials.CreateTestServerCredentials());
server.Start();
@ -66,7 +66,7 @@ namespace Grpc.IntegrationTesting
.AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
client = TestServiceGrpc.NewStub(channel);
client = TestService.NewStub(channel);
}
[TestFixtureTearDown]

@ -91,7 +91,7 @@ namespace Grpc.IntegrationTesting
GrpcEnvironment.Initialize();
var server = new Server();
server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
server.AddServiceDefinition(TestService.BindService(new TestServiceImpl()));
string host = "0.0.0.0";
int port = options.port.Value;

@ -0,0 +1,159 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: test.proto
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace grpc.testing {
public static class TestService
{
static readonly string __ServiceName = "grpc.testing.TestService";
static readonly Marshaller<Empty> __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
static readonly Marshaller<SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
static readonly Marshaller<SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
static readonly Marshaller<StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
static readonly Marshaller<StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
static readonly Marshaller<StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
static readonly Marshaller<StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
static readonly Method<Empty, Empty> __Method_EmptyCall = new Method<Empty, Empty>(
MethodType.Unary,
"EmptyCall",
__Marshaller_Empty,
__Marshaller_Empty);
static readonly Method<SimpleRequest, SimpleResponse> __Method_UnaryCall = new Method<SimpleRequest, SimpleResponse>(
MethodType.Unary,
"UnaryCall",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.ServerStreaming,
"StreamingOutputCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> __Method_StreamingInputCall = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
MethodType.ClientStreaming,
"StreamingInputCall",
__Marshaller_StreamingInputCallRequest,
__Marshaller_StreamingInputCallResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"FullDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
MethodType.DuplexStreaming,
"HalfDuplexCall",
__Marshaller_StreamingOutputCallRequest,
__Marshaller_StreamingOutputCallResponse);
// client-side stub interface
public interface ITestServiceClient
{
Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken));
Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken));
SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken));
Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken));
AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken));
AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken));
AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken));
}
// server-side interface
public interface ITestService
{
Task<Empty> EmptyCall(ServerCallContext context, Empty request);
Task<SimpleResponse> UnaryCall(ServerCallContext context, SimpleRequest request);
Task StreamingOutputCall(ServerCallContext context, StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
Task<StreamingInputCallResponse> StreamingInputCall(ServerCallContext context, IAsyncStreamReader<StreamingInputCallRequest> requestStream);
Task FullDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
Task HalfDuplexCall(ServerCallContext context, IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream);
}
// client stub
public class TestServiceClient : AbstractStub<TestServiceClient, StubConfiguration>, ITestServiceClient
{
public TestServiceClient(Channel channel) : this(channel, StubConfiguration.Default)
{
}
public TestServiceClient(Channel channel, StubConfiguration config) : base(channel, config)
{
}
public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_EmptyCall);
return Calls.AsyncUnaryCall(call, request, token);
}
public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall);
return Calls.BlockingUnaryCall(call, request, token);
}
public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_UnaryCall);
return Calls.AsyncUnaryCall(call, request, token);
}
public AsyncServerStreamingCall<StreamingOutputCallResponse> StreamingOutputCall(StreamingOutputCallRequest request, CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingOutputCall);
return Calls.AsyncServerStreamingCall(call, request, token);
}
public AsyncClientStreamingCall<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_StreamingInputCall);
return Calls.AsyncClientStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_FullDuplexCall);
return Calls.AsyncDuplexStreamingCall(call, token);
}
public AsyncDuplexStreamingCall<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCall(CancellationToken token = default(CancellationToken))
{
var call = CreateCall(__ServiceName, __Method_HalfDuplexCall);
return Calls.AsyncDuplexStreamingCall(call, token);
}
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(ITestService serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall)
.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall)
.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall)
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
// creates a new client stub
public static ITestServiceClient NewStub(Channel channel)
{
return new TestServiceClient(channel);
}
// creates a new client stub
public static ITestServiceClient NewStub(Channel channel, StubConfiguration config)
{
return new TestServiceClient(channel, config);
}
}
}
#endregion

@ -44,7 +44,7 @@ namespace grpc.testing
/// <summary>
/// Implementation of TestService server
/// </summary>
public class TestServiceImpl : TestServiceGrpc.ITestService
public class TestServiceImpl : TestService.ITestService
{
public Task<Empty> EmptyCall(ServerCallContext context, Empty request)
{

@ -0,0 +1,43 @@
#!/bin/sh
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Regenerates gRPC service stubs from proto files.
set +e
cd $(dirname $0)
PLUGIN=protoc-gen-grpc=../../bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=Grpc.Examples
INTEROP_DIR=Grpc.IntegrationTesting
protoc --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \
-I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto
protoc --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \
-I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto
Loading…
Cancel
Save