Merge branch 'optionalize_client_config' into strong-includes

pull/6092/head
Craig Tiller 9 years ago
commit 859fb06e80
  1. 24
      Makefile
  2. 2
      README.md
  3. 15
      include/grpc/grpc.h
  4. 6
      include/grpc/impl/codegen/grpc_types.h
  5. 157
      src/compiler/csharp_generator.cc
  6. 19
      src/core/ext/client_config/subchannel.c
  7. 36
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  8. 2
      src/core/lib/iomgr/ev_poll_and_epoll_posix.c
  9. 2
      src/core/lib/iomgr/ev_posix.c
  10. 2
      src/core/lib/iomgr/ev_posix.h
  11. 259
      src/core/lib/surface/server.c
  12. 18
      src/cpp/server/server.cc
  13. 84
      src/csharp/Grpc.Core/CallInvoker.cs
  14. 161
      src/csharp/Grpc.Core/ClientBase.cs
  15. 112
      src/csharp/Grpc.Core/DefaultCallInvoker.cs
  16. 4
      src/csharp/Grpc.Core/Grpc.Core.csproj
  17. 134
      src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs
  18. 75
      src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs
  19. 4
      src/csharp/Grpc.Examples.MathClient/MathClient.cs
  20. 14
      src/csharp/Grpc.Examples/MathExamples.cs
  21. 105
      src/csharp/Grpc.Examples/MathGrpc.cs
  22. 12
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  23. 2
      src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
  24. 57
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  25. 4
      src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
  26. 8
      src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
  27. 123
      src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
  28. 106
      src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
  29. 116
      src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs
  30. 4
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  31. 148
      src/csharp/Grpc.IntegrationTesting/InterarrivalTimers.cs
  32. 26
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  33. 2
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  34. 8
      src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
  35. 188
      src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
  36. 4
      src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
  37. 287
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  38. 16
      src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
  39. 10
      src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
  40. 2
      src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec
  41. 3
      src/csharp/tests.json
  42. 8
      src/proto/grpc/testing/messages.proto
  43. 4
      src/proto/grpc/testing/test.proto
  44. 2
      src/python/grpcio/grpc/_cython/imports.generated.h
  45. 2
      src/python/grpcio/grpc/beta/implementations.py
  46. 2
      src/python/grpcio/tests/interop/_secure_interop_test.py
  47. 2
      src/python/grpcio/tests/interop/client.py
  48. 2
      src/python/grpcio/tests/unit/beta/_beta_features_test.py
  49. 2
      src/python/grpcio/tests/unit/beta/_face_interface_test.py
  50. 6
      src/ruby/ext/grpc/rb_call.c
  51. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  52. 35
      src/ruby/spec/generic/client_stub_spec.rb
  53. 3
      test/core/bad_client/bad_client.c
  54. 1
      test/core/bad_client/gen_build_yaml.py
  55. 151
      test/core/bad_client/tests/head_of_line_blocking.c
  56. 2
      test/core/end2end/fixtures/proxy.c
  57. 2
      test/core/end2end/tests/idempotent_request.c
  58. 2
      test/core/internal_api_canaries/iomgr.c
  59. 2
      test/core/internal_api_canaries/support.c
  60. 2
      test/core/internal_api_canaries/transport.c
  61. 22
      test/core/surface/server_test.c
  62. 9
      test/core/util/reconnect_server.c
  63. 3
      test/core/util/reconnect_server.h
  64. 26
      test/cpp/interop/reconnect_interop_client.cc
  65. 10
      test/cpp/interop/reconnect_interop_server.cc
  66. 15
      test/cpp/util/create_test_channel.cc
  67. 8
      test/cpp/util/create_test_channel.h
  68. 2
      tools/gce/create_interop_worker.sh
  69. 28
      tools/run_tests/performance/__init__.py
  70. 17
      tools/run_tests/performance/build_performance.sh
  71. 2
      tools/run_tests/performance/remote_host_build.sh
  72. 2
      tools/run_tests/performance/remote_host_prepare.sh
  73. 2
      tools/run_tests/performance/run_worker_csharp.sh
  74. 2
      tools/run_tests/performance/run_worker_node.sh
  75. 153
      tools/run_tests/performance/scenario_config.py
  76. 133
      tools/run_tests/run_performance_tests.py
  77. 17
      tools/run_tests/sources_and_headers.json
  78. 21
      tools/run_tests/tests.json
  79. 28
      vsprojects/buildtests_c.sln
  80. 202
      vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj
  81. 24
      vsprojects/vcxproj/test/head_of_line_blocking_bad_client_test/head_of_line_blocking_bad_client_test.vcxproj.filters

@ -1076,6 +1076,7 @@ boringssl_pqueue_test: $(BINDIR)/$(CONFIG)/boringssl_pqueue_test
boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test
badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test
connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
@ -1298,6 +1299,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \
$(BINDIR)/$(CONFIG)/badreq_bad_client_test \
$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \
$(BINDIR)/$(CONFIG)/headers_bad_client_test \
$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
@ -1620,6 +1622,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing connection_prefix_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing head_of_line_blocking_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing headers_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing initial_settings_frame_bad_client_test"
@ -12850,6 +12854,26 @@ ifneq ($(NO_DEPS),true)
endif
HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \
test/core/bad_client/tests/head_of_line_blocking.c \
HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC))))
$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/head_of_line_blocking.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
-include $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
endif
HEADERS_BAD_CLIENT_TEST_SRC = \
test/core/bad_client/tests/headers.c \

@ -5,7 +5,7 @@
[![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Copyright 2015-2016 Google Inc.
Copyright 2015 Google Inc.
#Documentation

@ -289,6 +289,14 @@ GRPCAPI grpc_call_error grpc_server_request_call(
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag_new);
/** How to handle payloads for a registered method */
typedef enum {
/** Don't try to read the payload */
GRPC_SRM_PAYLOAD_NONE,
/** Read the initial payload as a byte buffer */
GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER
} grpc_server_register_method_payload_handling;
/** Registers a method in the server.
Methods to this (host, method) pair will not be reported by
grpc_server_request_call, but instead be reported by
@ -296,9 +304,10 @@ GRPCAPI grpc_call_error grpc_server_request_call(
registered_method (as returned by this function).
Must be called before grpc_server_start.
Returns NULL on failure. */
GRPCAPI void *grpc_server_register_method(grpc_server *server,
const char *method, const char *host,
uint32_t flags);
GRPCAPI void *grpc_server_register_method(
grpc_server *server, const char *method, const char *host,
grpc_server_register_method_payload_handling payload_handling,
uint32_t flags);
/** Request notification of a new pre-registered call. 'cq_for_notification'
must have been registered to the server via

@ -142,6 +142,8 @@ typedef struct {
/** Secondary user agent: goes at the end of the user-agent metadata
sent on each request */
#define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
/** The maximum time between subsequent connection attempts, in ms */
#define GRPC_ARG_MAX_RECONNECT_BACKOFF_MS "grpc.max_reconnect_backoff_ms"
/* The caller of the secure_channel_create functions may override the target
name used for SSL host name checking using this channel argument which is of
type GRPC_ARG_STRING. This *should* be used for testing only.
@ -185,7 +187,9 @@ typedef enum grpc_call_error {
server */
GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE,
/** this batch of operations leads to more operations than allowed */
GRPC_CALL_ERROR_BATCH_TOO_BIG
GRPC_CALL_ERROR_BATCH_TOO_BIG,
/** payload type requested is not the type registered */
GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
} grpc_call_error;
/* Write Flags: */

@ -81,6 +81,10 @@ std::string GetServerInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name();
}
std::string GetServerClassName(const ServiceDescriptor* service) {
return service->name() + "Base";
}
std::string GetCSharpMethodType(MethodType method_type) {
switch (method_type) {
case METHODTYPE_NO_STREAMING:
@ -108,10 +112,14 @@ std::string GetMethodFieldName(const MethodDescriptor *method) {
return "__Method_" + method->name();
}
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method,
bool invocation_param=false) {
if (method->client_streaming()) {
return "";
}
if (invocation_param) {
return "request, ";
}
return GetClassName(method->input_type()) + " request, ";
}
@ -242,6 +250,8 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se
void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// client interface\n");
out->Print("[System.Obsolete(\"Client side interfaced will be removed "
"in the next release. Use client class directly.\")]\n");
out->Print("public interface $name$\n", "name",
GetClientInterfaceName(service));
out->Print("{\n");
@ -290,6 +300,8 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side interface\n");
out->Print("[System.Obsolete(\"Service implementations should inherit"
" from the generated abstract base class instead.\")]\n");
out->Print("public interface $name$\n", "name",
GetServerInterfaceName(service));
out->Print("{\n");
@ -309,21 +321,64 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("\n");
}
void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side abstract class\n");
out->Print("public abstract class $name$\n", "name",
GetServerClassName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print(
"public virtual $returntype$ $methodname$($request$$response_stream_maybe$, "
"ServerCallContext context)\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe",
GetMethodResponseStreamMaybe(method));
out->Print("{\n");
out->Indent();
out->Print("throw new RpcException("
"new Status(StatusCode.Unimplemented, \"\"));\n");
out->Outdent();
out->Print("}\n\n");
}
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$ : ClientBase, $interface$\n",
"name", GetClientClassName(service), "interface",
GetClientInterfaceName(service));
"public class $name$ : ClientBase<$name$>, $interface$\n",
"name", GetClientClassName(service),
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
// constructors
out->Print(
"public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print("public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("///<summary>Protected parameterless constructor to allow creation"
" of test doubles.</summary>\n");
out->Print("protected $name$() : base()\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("///<summary>Protected constructor to allow creation of configured"
" clients.</summary>\n");
out->Print("protected $name$(ClientBaseConfiguration configuration)"
" : base(configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
@ -331,30 +386,26 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method->name());
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Outdent();
out->Print("}\n");
}
@ -364,57 +415,44 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
"public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method_name,
"request_maybe", GetMethodRequestParamMaybe(method, true));
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
@ -422,17 +460,30 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Outdent();
out->Print("}\n");
}
// override NewInstance method
out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $name$(configuration);\n",
"name", GetClientClassName(service));
out->Outdent();
out->Print("}\n");
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service,
bool use_server_class) {
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));
"interface", use_server_class ? GetServerClassName(service) :
GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
@ -489,8 +540,10 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) {
GenerateServiceDescriptorProperty(out, service);
GenerateClientInterface(out, service);
GenerateServerInterface(out, service);
GenerateServerClass(out, service);
GenerateClientStub(out, service);
GenerateBindServiceMethod(out, service);
GenerateBindServiceMethod(out, service, false);
GenerateBindServiceMethod(out, service, true);
GenerateNewStubMethods(out, service);
out->Outdent();

@ -352,6 +352,25 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
c->args->args[i].value.integer,
c->args->args[i].value.integer);
}
if (0 ==
strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) {
if (c->args->args[i].type == GRPC_ARG_INTEGER) {
if (c->args->args[i].value.integer >= 0) {
gpr_backoff_init(
&c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
GRPC_SUBCHANNEL_RECONNECT_JITTER,
GPR_MIN(c->args->args[i].value.integer,
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
c->args->args[i].value.integer);
} else {
gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS
" : must be non-negative");
}
} else {
gpr_log(GPR_ERROR,
GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer");
}
}
}
}
gpr_mu_init(&c->mu);

@ -31,13 +31,13 @@
*
*/
#include <grpc/support/port_platform.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/client_config/lb_policy_registry.h"
@ -263,22 +263,24 @@ static grpc_resolver *sockaddr_create(
r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r));
r->lb_policy_name = NULL;
if (0 != strcmp(args->uri->query, "")) {
gpr_slice query_slice;
gpr_slice_buffer query_parts;
query_slice =
gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing);
gpr_slice_buffer_init(&query_parts);
gpr_slice_split(query_slice, "=", &query_parts);
GPR_ASSERT(query_parts.count == 2);
if (0 == gpr_slice_str_cmp(query_parts.slices[0], "lb_policy")) {
r->lb_policy_name = gpr_dump_slice(query_parts.slices[1], GPR_DUMP_ASCII);
}
gpr_slice_buffer_destroy(&query_parts);
gpr_slice_unref(query_slice);
r->lb_policy_name =
gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy"));
const char *lb_enabled_qpart =
grpc_uri_get_query_arg(args->uri, "lb_enabled");
/* anything other than "0" is interpreted as true */
const bool lb_enabled =
(lb_enabled_qpart != NULL && (strcmp("0", lb_enabled_qpart) != 0));
if (r->lb_policy_name != NULL && strcmp("grpclb", r->lb_policy_name) == 0 &&
!lb_enabled) {
/* we want grpclb but the "resolved" addresses aren't LB enabled. Bail
* out, as this is meant mostly for tests. */
gpr_log(GPR_ERROR,
"Requested 'grpclb' LB policy but resolved addresses don't "
"support load balancing.");
abort();
}
if (r->lb_policy_name == NULL) {
r->lb_policy_name = gpr_strdup(default_lb_policy_name);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -95,7 +95,6 @@ typedef struct requested_call {
grpc_byte_buffer **optional_payload;
} registered;
} data;
grpc_closure publish;
} requested_call;
typedef struct channel_registered_method {
@ -156,15 +155,21 @@ struct call_data {
bool recv_idempotent_request;
grpc_metadata_array initial_metadata;
request_matcher *request_matcher;
grpc_byte_buffer *payload;
grpc_closure got_initial_metadata;
grpc_closure server_on_recv_initial_metadata;
grpc_closure kill_zombie_closure;
grpc_closure *on_done_recv_initial_metadata;
grpc_closure publish;
call_data *pending_next;
};
struct request_matcher {
grpc_server *server;
call_data *pending_head;
call_data *pending_tail;
gpr_stack_lockfree *requests;
@ -173,6 +178,7 @@ struct request_matcher {
struct registered_method {
char *method;
char *host;
grpc_server_register_method_payload_handling payload_handling;
uint32_t flags;
request_matcher request_matcher;
registered_method *next;
@ -226,8 +232,7 @@ struct grpc_server {
#define SERVER_FROM_CALL_ELEM(elem) \
(((channel_data *)(elem)->channel_data)->server)
static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc);
static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, bool success);
static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
requested_call *rc);
/* Before calling maybe_finish_shutdown, we must hold mu_global and not
@ -303,8 +308,10 @@ static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
* request_matcher
*/
static void request_matcher_init(request_matcher *rm, size_t entries) {
static void request_matcher_init(request_matcher *rm, size_t entries,
grpc_server *server) {
memset(rm, 0, sizeof(*rm));
rm->server = server;
rm->requests = gpr_stack_lockfree_create(entries);
}
@ -417,21 +424,90 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
&op);
}
static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
grpc_call_element *elem, request_matcher *rm) {
call_data *calld = elem->call_data;
int request_id;
static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
gpr_slice slice = value->slice;
size_t len = GPR_SLICE_LENGTH(slice);
if (gpr_atm_acq_load(&server->shutdown_flag)) {
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
grpc_server *server = rc->server;
if (rc >= server->requested_calls &&
rc < server->requested_calls + server->max_requested_calls) {
GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
gpr_stack_lockfree_push(server->request_freelist,
(int)(rc - server->requested_calls));
} else {
gpr_free(req);
}
server_unref(exec_ctx, server);
}
static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc) {
grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
grpc_call *call = calld->call;
*rc->call = call;
calld->cq_new = rc->cq_for_notification;
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
GPR_ASSERT(calld->host != NULL);
GPR_ASSERT(calld->path != NULL);
cpstr(&rc->data.batch.details->host,
&rc->data.batch.details->host_capacity, calld->host);
cpstr(&rc->data.batch.details->method,
&rc->data.batch.details->method_capacity, calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
0 | (calld->recv_idempotent_request
? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
: 0);
break;
case REGISTERED_CALL:
*rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) {
*rc->data.registered.optional_payload = calld->payload;
}
break;
default:
GPR_UNREACHABLE_CODE(return );
}
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, true, done_request_event, rc,
&rc->completion);
}
static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
call_data *calld = arg;
request_matcher *rm = calld->request_matcher;
grpc_server *server = rm->server;
if (!success || gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
return;
}
request_id = gpr_stack_lockfree_pop(rm->requests);
int request_id = gpr_stack_lockfree_pop(rm->requests);
if (request_id == -1) {
gpr_mu_lock(&server->mu_call);
gpr_mu_lock(&calld->mu_state);
@ -449,7 +525,41 @@ static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
publish_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
}
}
static void finish_start_new_rpc(
grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_call_element *elem,
request_matcher *rm,
grpc_server_register_method_payload_handling payload_handling) {
call_data *calld = elem->call_data;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
return;
}
calld->request_matcher = rm;
switch (payload_handling) {
case GRPC_SRM_PAYLOAD_NONE:
publish_new_rpc(exec_ctx, calld, true);
break;
case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
grpc_op op;
memset(&op, 0, sizeof(op));
op.op = GRPC_OP_RECV_MESSAGE;
op.data.recv_message = &calld->payload;
grpc_closure_init(&calld->publish, publish_new_rpc, calld);
grpc_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1,
&calld->publish);
break;
}
}
}
@ -475,7 +585,8 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
!calld->recv_idempotent_request)
continue;
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
/* check for a wildcard method definition (no host set) */
@ -490,12 +601,14 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
!calld->recv_idempotent_request)
continue;
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
}
finish_start_new_rpc(exec_ctx, server, elem,
&server->unregistered_request_matcher);
&server->unregistered_request_matcher,
GRPC_SRM_PAYLOAD_NONE);
}
static int num_listeners(grpc_server *server) {
@ -824,7 +937,7 @@ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
gpr_stack_lockfree_push(server->request_freelist, (int)i);
}
request_matcher_init(&server->unregistered_request_matcher,
server->max_requested_calls);
server->max_requested_calls, server);
server->requested_calls = gpr_malloc(server->max_requested_calls *
sizeof(*server->requested_calls));
@ -840,8 +953,10 @@ static int streq(const char *a, const char *b) {
return 0 == strcmp(a, b);
}
void *grpc_server_register_method(grpc_server *server, const char *method,
const char *host, uint32_t flags) {
void *grpc_server_register_method(
grpc_server *server, const char *method, const char *host,
grpc_server_register_method_payload_handling payload_handling,
uint32_t flags) {
registered_method *m;
GRPC_API_TRACE(
"grpc_server_register_method(server=%p, method=%s, host=%s, "
@ -866,10 +981,12 @@ void *grpc_server_register_method(grpc_server *server, const char *method,
}
m = gpr_malloc(sizeof(registered_method));
memset(m, 0, sizeof(*m));
request_matcher_init(&m->request_matcher, server->max_requested_calls);
request_matcher_init(&m->request_matcher, server->max_requested_calls,
server);
m->method = gpr_strdup(method);
m->host = gpr_strdup(host);
m->next = server->registered_methods;
m->payload_handling = payload_handling;
m->flags = flags;
server->registered_methods = m;
return m;
@ -1143,8 +1260,8 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(exec_ctx, server, calld,
&server->requested_calls[request_id]);
publish_call(exec_ctx, server, calld,
&server->requested_calls[request_id]);
}
gpr_mu_lock(&server->mu_call);
}
@ -1209,6 +1326,12 @@ grpc_call_error grpc_server_request_registered_call(
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
if ((optional_payload == NULL) !=
(rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) {
gpr_free(rc);
error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
goto done;
}
grpc_cq_begin_op(cq_for_notification, tag);
rc->type = REGISTERED_CALL;
rc->server = server;
@ -1226,86 +1349,6 @@ done:
return error;
}
static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx,
void *user_data, bool success);
static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
gpr_slice slice = value->slice;
size_t len = GPR_SLICE_LENGTH(slice);
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc) {
grpc_op ops[1];
grpc_op *op = ops;
memset(ops, 0, sizeof(ops));
/* called once initial metadata has been read by the call, but BEFORE
the ioreq to fetch it out of the call has been executed.
This means metadata related fields can be relied on in calld, but to
fill in the metadata array passed by the client, we need to perform
an ioreq op, that should complete immediately. */
grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
grpc_closure_init(&rc->publish, publish_registered_or_batch, rc);
*rc->call = calld->call;
calld->cq_new = rc->cq_for_notification;
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
GPR_ASSERT(calld->host != NULL);
GPR_ASSERT(calld->path != NULL);
cpstr(&rc->data.batch.details->host,
&rc->data.batch.details->host_capacity, calld->host);
cpstr(&rc->data.batch.details->method,
&rc->data.batch.details->method_capacity, calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
0 | (calld->recv_idempotent_request
? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
: 0);
break;
case REGISTERED_CALL:
*rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) {
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = rc->data.registered.optional_payload;
op++;
}
break;
default:
GPR_UNREACHABLE_CODE(return );
}
GRPC_CALL_INTERNAL_REF(calld->call, "server");
grpc_call_start_batch_and_execute(exec_ctx, calld->call, ops,
(size_t)(op - ops), &rc->publish);
}
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
grpc_server *server = rc->server;
if (rc >= server->requested_calls &&
rc < server->requested_calls + server->max_requested_calls) {
GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
gpr_stack_lockfree_push(server->request_freelist,
(int)(rc - server->requested_calls));
} else {
gpr_free(req);
}
server_unref(exec_ctx, server);
}
static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
requested_call *rc) {
*rc->call = NULL;
@ -1316,20 +1359,6 @@ static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
done_request_event, rc, &rc->completion);
}
static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx, void *prc,
bool success) {
requested_call *rc = prc;
grpc_call *call = *rc->call;
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, success, done_request_event,
rc, &rc->completion);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "server");
}
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
return server->channel_args;
}

@ -321,6 +321,19 @@ void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
g_callbacks.reset(callbacks);
}
static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
RpcServiceMethod* method) {
switch (method->method_type()) {
case RpcMethod::NORMAL_RPC:
case RpcMethod::SERVER_STREAMING:
return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
case RpcMethod::CLIENT_STREAMING:
case RpcMethod::BIDI_STREAMING:
return GRPC_SRM_PAYLOAD_NONE;
}
GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
}
bool Server::RegisterService(const grpc::string* host, Service* service) {
bool has_async_methods = service->has_async_methods();
if (has_async_methods) {
@ -334,8 +347,9 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
continue;
}
RpcServiceMethod* method = it->get();
void* tag = grpc_server_register_method(server_, method->name(),
host ? host->c_str() : nullptr, 0);
void* tag = grpc_server_register_method(
server_, method->name(), host ? host->c_str() : nullptr,
PayloadHandlingForMethod(method), 0);
if (tag == nullptr) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());

@ -0,0 +1,84 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core
{
/// <summary>
/// Abstraction of client-side RPC invocation.
/// </summary>
/// <seealso cref="Calls"/>
public abstract class CallInvoker
{
/// <summary>
/// Invokes a simple remote call in a blocking fashion.
/// </summary>
public abstract TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public abstract AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public abstract AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public abstract AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public abstract AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class;
}
}

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -31,93 +31,156 @@
#endregion
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Interceptor for call headers.
/// Generic base class for client-side stubs.
/// </summary>
/// <remarks>Header interceptor is no longer to recommented way to perform authentication.
/// For header (initial metadata) based auth such as OAuth2 or JWT access token, use <see cref="MetadataCredentials"/>.
/// </remarks>
public delegate void HeaderInterceptor(IMethod method, Metadata metadata);
public abstract class ClientBase<T> : ClientBase
where T : ClientBase<T>
{
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class that
/// throws <c>NotImplementedException</c> upon invocation of any RPC.
/// This constructor is only provided to allow creation of test doubles
/// for client classes (e.g. mocking requires a parameterless constructor).
/// </summary>
protected ClientBase() : base()
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
protected ClientBase(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="channel">The channel to use for remote call invocation.</param>
public ClientBase(Channel channel) : base(channel)
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
public ClientBase(CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>
/// Creates a new client that sets host field for calls explicitly.
/// gRPC supports multiple "hosts" being served by a single server.
/// By default (if a client was not created by calling this method),
/// host <c>null</c> with the meaning "use default host" is used.
/// </summary>
public T WithHost(string host)
{
var newConfiguration = this.Configuration.WithHost(host);
return NewInstance(newConfiguration);
}
/// <summary>
/// Creates a new instance of client from given <c>ClientBaseConfiguration</c>.
/// </summary>
protected abstract T NewInstance(ClientBaseConfiguration configuration);
}
/// <summary>
/// Base class for client-side stubs.
/// </summary>
public abstract class ClientBase
{
readonly Channel channel;
readonly ClientBaseConfiguration configuration;
readonly CallInvoker callInvoker;
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class that
/// throws <c>NotImplementedException</c> upon invocation of any RPC.
/// This constructor is only provided to allow creation of test doubles
/// for client classes (e.g. mocking requires a parameterless constructor).
/// </summary>
protected ClientBase() : this(new UnimplementedCallInvoker())
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
protected ClientBase(ClientBaseConfiguration configuration)
{
this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration");
this.callInvoker = configuration.CreateDecoratedCallInvoker();
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="channel">The channel to use for remote call invocation.</param>
public ClientBase(Channel channel)
public ClientBase(Channel channel) : this(new DefaultCallInvoker(channel))
{
this.channel = channel;
}
/// <summary>
/// Can be used to register a custom header interceptor.
/// The interceptor is invoked each time a new call on this client is started.
/// It is not recommented to use header interceptor to add auth headers to RPC calls.
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <seealso cref="HeaderInterceptor"/>
public HeaderInterceptor HeaderInterceptor
/// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null))
{
get;
set;
}
/// <summary>
/// gRPC supports multiple "hosts" being served by a single server.
/// This property can be used to set the target host explicitly.
/// By default, this will be set to <c>null</c> with the meaning
/// "use default host".
/// Gets the call invoker.
/// </summary>
public string Host
protected CallInvoker CallInvoker
{
get;
set;
get { return this.callInvoker; }
}
/// <summary>
/// Channel associated with this client.
/// Gets the configuration.
/// </summary>
public Channel Channel
internal ClientBaseConfiguration Configuration
{
get
{
return this.channel;
}
get { return this.configuration; }
}
/// <summary>
/// Creates a new call to given method.
/// Represents configuration of ClientBase. The class itself is visible to
/// subclasses, but contents are marked as internal to make the instances opaque.
/// The verbose name of this class was chosen to make name clash in generated code
/// less likely.
/// </summary>
/// <param name="method">The method to invoke.</param>
/// <param name="options">The call options.</param>
/// <typeparam name="TRequest">Request message type.</typeparam>
/// <typeparam name="TResponse">Response message type.</typeparam>
/// <returns>The call invocation details.</returns>
protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
where TRequest : class
where TResponse : class
protected internal class ClientBaseConfiguration
{
var interceptor = HeaderInterceptor;
if (interceptor != null)
readonly CallInvoker undecoratedCallInvoker;
readonly string host;
internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host)
{
this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker);
this.host = host;
}
internal CallInvoker CreateDecoratedCallInvoker()
{
return new InterceptingCallInvoker(undecoratedCallInvoker, hostInterceptor: (h) => host);
}
internal ClientBaseConfiguration WithHost(string host)
{
if (options.Headers == null)
{
options = options.WithHeaders(new Metadata());
}
interceptor(method, options.Headers);
GrpcPreconditions.CheckNotNull(host, "host");
return new ClientBaseConfiguration(this.undecoratedCallInvoker, host);
}
return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
}
}
}

@ -0,0 +1,112 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Invokes client RPCs using <see cref="Calls"/>.
/// </summary>
public class DefaultCallInvoker : CallInvoker
{
readonly Channel channel;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.DefaultCallInvoker"/> class.
/// </summary>
/// <param name="channel">Channel to use.</param>
public DefaultCallInvoker(Channel channel)
{
this.channel = GrpcPreconditions.CheckNotNull(channel);
}
/// <summary>
/// Invokes a simple remote call in a blocking fashion.
/// </summary>
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.BlockingUnaryCall(call, request);
}
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.AsyncUnaryCall(call, request);
}
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.AsyncServerStreamingCall(call, request);
}
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
var call = CreateCall(method, host, options);
return Calls.AsyncClientStreamingCall(call);
}
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
var call = CreateCall(method, host, options);
return Calls.AsyncDuplexStreamingCall(call);
}
protected virtual CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class
{
return new CallInvocationDetails<TRequest, TResponse>(channel, method, host, options);
}
}
}

@ -129,6 +129,10 @@
<Compile Include="Profiling\Profilers.cs" />
<Compile Include="Internal\DefaultSslRootsOverride.cs" />
<Compile Include="Utils\GrpcPreconditions.cs" />
<Compile Include="CallInvoker.cs" />
<Compile Include="DefaultCallInvoker.cs" />
<Compile Include="Internal\UnimplementedCallInvoker.cs" />
<Compile Include="Internal\InterceptingCallInvoker.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.nuspec" />

@ -0,0 +1,134 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Decorates an underlying <c>CallInvoker</c> to intercept call invocations.
/// </summary>
internal class InterceptingCallInvoker : CallInvoker
{
readonly CallInvoker callInvoker;
readonly Func<string, string> hostInterceptor;
readonly Func<CallOptions, CallOptions> callOptionsInterceptor;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class.
/// </summary>
public InterceptingCallInvoker(CallInvoker callInvoker,
Func<string, string> hostInterceptor = null,
Func<CallOptions, CallOptions> callOptionsInterceptor = null)
{
this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker);
this.hostInterceptor = hostInterceptor;
this.callOptionsInterceptor = callOptionsInterceptor;
}
/// <summary>
/// Intercepts a unary call.
/// </summary>
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.BlockingUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncServerStreamingCall(method, host, options, request);
}
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncClientStreamingCall(method, host, options);
}
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncDuplexStreamingCall(method, host, options);
}
private string InterceptHost(string host)
{
if (hostInterceptor == null)
{
return host;
}
return hostInterceptor(host);
}
private CallOptions InterceptCallOptions(CallOptions options)
{
if (callOptionsInterceptor == null)
{
return options;
}
return callOptionsInterceptor(options);
}
}
}

@ -0,0 +1,75 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Call invoker that throws <c>NotImplementedException</c> for all requests.
/// </summary>
internal class UnimplementedCallInvoker : CallInvoker
{
public UnimplementedCallInvoker()
{
}
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
throw new NotImplementedException();
}
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
throw new NotImplementedException();
}
}
}

@ -1,5 +1,5 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@ namespace Math
public static void Main(string[] args)
{
var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure);
Math.IMathClient client = new Math.MathClient(channel);
Math.MathClient client = new Math.MathClient(channel);
MathExamples.DivExample(client);
MathExamples.DivAsyncExample(client).Wait();

@ -1,5 +1,5 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -38,19 +38,19 @@ namespace Math
{
public static class MathExamples
{
public static void DivExample(Math.IMathClient client)
public static void DivExample(Math.MathClient client)
{
DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 });
Console.WriteLine("Div Result: " + result);
}
public static async Task DivAsyncExample(Math.IMathClient client)
public static async Task DivAsyncExample(Math.MathClient client)
{
DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 });
Console.WriteLine("DivAsync Result: " + result);
}
public static async Task FibExample(Math.IMathClient client)
public static async Task FibExample(Math.MathClient client)
{
using (var call = client.Fib(new FibArgs { Limit = 5 }))
{
@ -59,7 +59,7 @@ namespace Math
}
}
public static async Task SumExample(Math.IMathClient client)
public static async Task SumExample(Math.MathClient client)
{
var numbers = new List<Num>
{
@ -75,7 +75,7 @@ namespace Math
}
}
public static async Task DivManyExample(Math.IMathClient client)
public static async Task DivManyExample(Math.MathClient client)
{
var divArgsList = new List<DivArgs>
{
@ -90,7 +90,7 @@ namespace Math
}
}
public static async Task DependendRequestsExample(Math.IMathClient client)
public static async Task DependendRequestsExample(Math.MathClient client)
{
var numbers = new List<Num>
{

@ -52,6 +52,7 @@ namespace Math {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IMathClient
{
global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -67,6 +68,7 @@ namespace Math {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IMath
{
Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context);
@ -75,61 +77,92 @@ namespace Math {
Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context);
}
// server-side abstract class
public abstract class MathBase
{
public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class MathClient : ClientBase, IMathClient
public class MathClient : ClientBase<MathClient>, IMathClient
{
public MathClient(Channel channel) : base(channel)
{
}
public global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public MathClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected MathClient() : base()
{
var call = CreateCall(__Method_Div, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected MathClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Div, options);
return Calls.AsyncUnaryCall(call, request);
return Div(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request);
}
public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_DivMany, options);
return Calls.AsyncDuplexStreamingCall(call);
return DivAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request);
}
public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Fib, options);
return Calls.AsyncServerStreamingCall(call, request);
return DivMany(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
{
var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options);
}
public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Sum, options);
return Calls.AsyncClientStreamingCall(call);
return Fib(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request);
}
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return Sum(new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options);
}
protected override MathClient NewInstance(ClientBaseConfiguration configuration)
{
return new MathClient(configuration);
}
}
@ -143,6 +176,16 @@ namespace Math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(MathBase serviceImpl)
{
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();
}
// creates a new client
public static MathClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -43,14 +43,14 @@ namespace Math
/// <summary>
/// Implementation of MathService server
/// </summary>
public class MathServiceImpl : Math.IMath
public class MathServiceImpl : Math.MathBase
{
public Task<DivReply> Div(DivArgs request, ServerCallContext context)
public override Task<DivReply> Div(DivArgs request, ServerCallContext context)
{
return Task.FromResult(DivInternal(request));
}
public async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
{
if (request.Limit <= 0)
{
@ -72,7 +72,7 @@ namespace Math
}
}
public async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
public override async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
{
long sum = 0;
await requestStream.ForEachAsync(async num =>
@ -82,7 +82,7 @@ namespace Math
return new Num { Num_ = sum };
}
public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
public override async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
{
await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs)));
}

@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests
const string Host = "localhost";
Server server;
Channel channel;
Grpc.Health.V1.Health.IHealthClient client;
Grpc.Health.V1.Health.HealthClient client;
Grpc.HealthCheck.HealthServiceImpl serviceImpl;
[TestFixtureSetUp]

@ -29,6 +29,7 @@ namespace Grpc.Health.V1 {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IHealthClient
{
global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -38,36 +39,59 @@ namespace Grpc.Health.V1 {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IHealth
{
Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context);
}
// server-side abstract class
public abstract class HealthBase
{
public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class HealthClient : ClientBase, IHealthClient
public class HealthClient : ClientBase<HealthClient>, IHealthClient
{
public HealthClient(Channel channel) : base(channel)
{
}
public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public HealthClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected HealthClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected HealthClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Check, options);
return Calls.BlockingUnaryCall(call, request);
return Check(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
{
var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Check, options);
return Calls.AsyncUnaryCall(call, request);
return CheckAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request);
}
protected override HealthClient NewInstance(ClientBaseConfiguration configuration)
{
return new HealthClient(configuration);
}
}
@ -78,6 +102,13 @@ namespace Grpc.Health.V1 {
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(HealthBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
// creates a new client
public static HealthClient NewClient(Channel channel)
{

@ -51,7 +51,7 @@ namespace Grpc.HealthCheck
/// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl));
/// </code>
/// </summary>
public class HealthServiceImpl : Grpc.Health.V1.Health.IHealth
public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase
{
private readonly object myLock = new object();
private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap =
@ -99,7 +99,7 @@ namespace Grpc.HealthCheck
/// <param name="request">The check request.</param>
/// <param name="context">The call context.</param>
/// <returns>The asynchronous response.</returns>
public Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
{
lock (myLock)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -44,19 +44,19 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of BenchmarkService server
/// </summary>
public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase
{
public BenchmarkServiceImpl()
{
}
public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
return Task.FromResult(response);
}
public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
public override async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
{
await requestStream.ForEachAsync(async request =>
{

@ -61,15 +61,7 @@ namespace Grpc.IntegrationTesting
public static IClientRunner CreateStarted(ClientConfig config)
{
Logger.Debug("ClientConfig: {0}", config);
string target = config.ServerTargets.Single();
GrpcPreconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop,
"Only closed loop scenario supported for C#");
GrpcPreconditions.CheckArgument(config.ClientChannels == 1, "ClientConfig.ClientChannels needs to be 1");
if (config.OutstandingRpcsPerChannel != 0)
{
Logger.Warning("ClientConfig.OutstandingRpcsPerChannel is not supported for C#. Ignoring the value");
}
if (config.AsyncClientThreads != 0)
{
Logger.Warning("ClientConfig.AsyncClientThreads is not supported for C#. Ignoring the value");
@ -83,22 +75,40 @@ namespace Grpc.IntegrationTesting
Logger.Warning("ClientConfig.CoreList is not supported for C#. Ignoring the value");
}
var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
var channels = CreateChannels(config.ClientChannels, config.ServerTargets, config.SecurityParams);
return new ClientRunnerImpl(channels,
config.ClientType,
config.RpcType,
config.OutstandingRpcsPerChannel,
config.LoadParams,
config.PayloadConfig,
config.HistogramParams);
}
private static List<Channel> CreateChannels(int clientChannels, IEnumerable<string> serverTargets, SecurityParams securityParams)
{
GrpcPreconditions.CheckArgument(clientChannels > 0, "clientChannels needs to be at least 1.");
GrpcPreconditions.CheckArgument(serverTargets.Count() > 0, "at least one serverTarget needs to be specified.");
var credentials = securityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
List<ChannelOption> channelOptions = null;
if (config.SecurityParams != null && config.SecurityParams.ServerHostOverride != "")
if (securityParams != null && securityParams.ServerHostOverride != "")
{
channelOptions = new List<ChannelOption>
{
new ChannelOption(ChannelOptions.SslTargetNameOverride, config.SecurityParams.ServerHostOverride)
new ChannelOption(ChannelOptions.SslTargetNameOverride, securityParams.ServerHostOverride)
};
}
var channel = new Channel(target, credentials, channelOptions);
return new ClientRunnerImpl(channel,
config.ClientType,
config.RpcType,
config.PayloadConfig,
config.HistogramParams);
var result = new List<Channel>();
for (int i = 0; i < clientChannels; i++)
{
var target = serverTargets.ElementAt(i % serverTargets.Count());
var channel = new Channel(target, credentials, channelOptions);
result.Add(channel);
}
return result;
}
}
@ -106,30 +116,35 @@ namespace Grpc.IntegrationTesting
{
const double SecondsToNanos = 1e9;
readonly Channel channel;
readonly List<Channel> channels;
readonly ClientType clientType;
readonly RpcType rpcType;
readonly PayloadConfig payloadConfig;
readonly Histogram histogram;
readonly BenchmarkService.IBenchmarkServiceClient client;
readonly Task runnerTask;
readonly CancellationTokenSource stoppedCts;
readonly List<Task> runnerTasks;
readonly CancellationTokenSource stoppedCts = new CancellationTokenSource();
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
public ClientRunnerImpl(Channel channel, ClientType clientType, RpcType rpcType, PayloadConfig payloadConfig, HistogramParams histogramParams)
public ClientRunnerImpl(List<Channel> channels, ClientType clientType, RpcType rpcType, int outstandingRpcsPerChannel, LoadParams loadParams, PayloadConfig payloadConfig, HistogramParams histogramParams)
{
this.channel = GrpcPreconditions.CheckNotNull(channel);
GrpcPreconditions.CheckArgument(outstandingRpcsPerChannel > 0, "outstandingRpcsPerChannel");
this.channels = new List<Channel>(channels);
this.clientType = clientType;
this.rpcType = rpcType;
this.payloadConfig = payloadConfig;
this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
this.stoppedCts = new CancellationTokenSource();
this.client = BenchmarkService.NewClient(channel);
var threadBody = GetThreadBody();
this.runnerTask = Task.Factory.StartNew(threadBody, TaskCreationOptions.LongRunning);
this.runnerTasks = new List<Task>();
foreach (var channel in this.channels)
{
for (int i = 0; i < outstandingRpcsPerChannel; i++)
{
var timer = CreateTimer(loadParams, 1.0 / this.channels.Count / outstandingRpcsPerChannel);
var threadBody = GetThreadBody(channel, timer);
this.runnerTasks.Add(Task.Factory.StartNew(threadBody, TaskCreationOptions.LongRunning));
}
}
}
public ClientStats GetStats(bool reset)
@ -150,12 +165,19 @@ namespace Grpc.IntegrationTesting
public async Task StopAsync()
{
stoppedCts.Cancel();
await runnerTask;
await channel.ShutdownAsync();
foreach (var runnerTask in runnerTasks)
{
await runnerTask;
}
foreach (var channel in channels)
{
await channel.ShutdownAsync();
}
}
private void RunClosedLoopUnary()
private void RunUnary(Channel channel, IInterarrivalTimer timer)
{
var client = BenchmarkService.NewClient(channel);
var request = CreateSimpleRequest();
var stopwatch = new Stopwatch();
@ -167,11 +189,14 @@ namespace Grpc.IntegrationTesting
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
timer.WaitForNext();
}
}
private async Task RunClosedLoopUnaryAsync()
private async Task RunUnaryAsync(Channel channel, IInterarrivalTimer timer)
{
var client = BenchmarkService.NewClient(channel);
var request = CreateSimpleRequest();
var stopwatch = new Stopwatch();
@ -183,11 +208,14 @@ namespace Grpc.IntegrationTesting
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
}
private async Task RunClosedLoopStreamingAsync()
private async Task RunStreamingPingPongAsync(Channel channel, IInterarrivalTimer timer)
{
var client = BenchmarkService.NewClient(channel);
var request = CreateSimpleRequest();
var stopwatch = new Stopwatch();
@ -202,6 +230,8 @@ namespace Grpc.IntegrationTesting
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
// finish the streaming call
@ -210,7 +240,7 @@ namespace Grpc.IntegrationTesting
}
}
private async Task RunGenericClosedLoopStreamingAsync()
private async Task RunGenericStreamingAsync(Channel channel, IInterarrivalTimer timer)
{
var request = CreateByteBufferRequest();
var stopwatch = new Stopwatch();
@ -228,6 +258,8 @@ namespace Grpc.IntegrationTesting
// spec requires data point in nanoseconds.
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
await timer.WaitForNextAsync();
}
// finish the streaming call
@ -236,7 +268,7 @@ namespace Grpc.IntegrationTesting
}
}
private Action GetThreadBody()
private Action GetThreadBody(Channel channel, IInterarrivalTimer timer)
{
if (payloadConfig.PayloadCase == PayloadConfig.PayloadOneofCase.BytebufParams)
{
@ -244,7 +276,7 @@ namespace Grpc.IntegrationTesting
GrpcPreconditions.CheckArgument(rpcType == RpcType.STREAMING, "Generic client only supports streaming calls");
return () =>
{
RunGenericClosedLoopStreamingAsync().Wait();
RunGenericStreamingAsync(channel, timer).Wait();
};
}
@ -252,7 +284,7 @@ namespace Grpc.IntegrationTesting
if (clientType == ClientType.SYNC_CLIENT)
{
GrpcPreconditions.CheckArgument(rpcType == RpcType.UNARY, "Sync client can only be used for Unary calls in C#");
return RunClosedLoopUnary;
return () => RunUnary(channel, timer);
}
else if (clientType == ClientType.ASYNC_CLIENT)
{
@ -261,12 +293,12 @@ namespace Grpc.IntegrationTesting
case RpcType.UNARY:
return () =>
{
RunClosedLoopUnaryAsync().Wait();
RunUnaryAsync(channel, timer).Wait();
};
case RpcType.STREAMING:
return () =>
{
RunClosedLoopStreamingAsync().Wait();
RunStreamingPingPongAsync(channel, timer).Wait();
};
}
}
@ -292,5 +324,18 @@ namespace Grpc.IntegrationTesting
{
return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
}
private static IInterarrivalTimer CreateTimer(LoadParams loadParams, double loadMultiplier)
{
switch (loadParams.LoadCase)
{
case LoadParams.LoadOneofCase.ClosedLoop:
return new ClosedLoopInterarrivalTimer();
case LoadParams.LoadOneofCase.Poisson:
return new PoissonInterarrivalTimer(loadParams.Poisson.OfferedLoad * loadMultiplier);
default:
throw new ArgumentException("Unknown load type");
}
}
}
}

@ -0,0 +1,106 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class GeneratedClientTest
{
TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient();
[Test]
public void ExpandedParamOverloadCanBeMocked()
{
var expected = new SimpleResponse();
var mockClient = new Mock<TestService.TestServiceClient>();
// mocking is relatively clumsy because one needs to specify value for all the optional params.
mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), null, null, CancellationToken.None)).Returns(expected);
Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest()));
}
[Test]
public void CallOptionsOverloadCanBeMocked()
{
var expected = new SimpleResponse();
var mockClient = new Mock<TestService.TestServiceClient>();
mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<CallOptions>())).Returns(expected);
Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest(), new CallOptions()));
}
[Test]
public void DefaultMethodStubThrows_UnaryCall()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest()));
}
[Test]
public void DefaultMethodStubThrows_ClientStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall());
}
[Test]
public void DefaultMethodStubThrows_ServerStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest()));
}
[Test]
public void DefaultMethodStubThrows_DuplexStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall());
}
/// <summary>
/// Subclass of the generated client that doesn't override any method stubs.
/// </summary>
private class UnimplementedTestServiceClient : TestService.TestServiceClient
{
}
}
}

@ -0,0 +1,116 @@
#region Copyright notice and license
// Copyright 2015-2016, 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
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class GeneratedServiceBaseTest
{
const string Host = "localhost";
Server server;
Channel channel;
TestService.TestServiceClient client;
[SetUp]
public void Init()
{
server = new Server
{
Services = { TestService.BindService(new UnimplementedTestServiceImpl()) },
Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = TestService.NewClient(channel);
}
[TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public void UnimplementedByDefault_Unary()
{
var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { }));
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_ClientStreaming()
{
var call = client.StreamingInputCall();
var ex = Assert.Throws<RpcException>(async () => await call);
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_ServerStreamingCall()
{
var call = client.StreamingOutputCall(new StreamingOutputCallRequest());
var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_DuplexStreamingCall()
{
var call = client.FullDuplexCall();
var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
/// <summary>
/// Implementation of TestService that doesn't override any methods.
/// </summary>
private class UnimplementedTestServiceImpl : TestService.TestServiceBase
{
}
}
}

@ -84,7 +84,6 @@
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="HeaderInterceptorTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Empty.cs" />
<Compile Include="Messages.cs" />
@ -114,6 +113,9 @@
<Compile Include="QpsWorker.cs" />
<Compile Include="WallClockStopwatch.cs" />
<Compile Include="GenericService.cs" />
<Compile Include="GeneratedServiceBaseTest.cs" />
<Compile Include="GeneratedClientTest.cs" />
<Compile Include="InterarrivalTimers.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -0,0 +1,148 @@
#region Copyright notice and license
// Copyright 2016, 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
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
public interface IInterarrivalTimer
{
void WaitForNext();
Task WaitForNextAsync();
}
/// <summary>
/// Interarrival timer that doesn't wait at all.
/// </summary>
public class ClosedLoopInterarrivalTimer : IInterarrivalTimer
{
public ClosedLoopInterarrivalTimer()
{
}
public void WaitForNext()
{
// NOP
}
public Task WaitForNextAsync()
{
return Task.FromResult<object>(null);
}
}
/// <summary>
/// Interarrival timer that generates Poisson process load.
/// </summary>
public class PoissonInterarrivalTimer : IInterarrivalTimer
{
readonly ExponentialDistribution exponentialDistribution;
DateTime? lastEventTime;
public PoissonInterarrivalTimer(double offeredLoad)
{
this.exponentialDistribution = new ExponentialDistribution(new Random(), offeredLoad);
this.lastEventTime = DateTime.UtcNow;
}
public void WaitForNext()
{
var waitDuration = GetNextWaitDuration();
int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds);
if (millisTimeout > 0)
{
// TODO(jtattermusch): probably only works well for a relatively low interarrival rate
Thread.Sleep(millisTimeout);
}
}
public async Task WaitForNextAsync()
{
var waitDuration = GetNextWaitDuration();
int millisTimeout = (int) Math.Round(waitDuration.TotalMilliseconds);
if (millisTimeout > 0)
{
// TODO(jtattermusch): probably only works well for a relatively low interarrival rate
await Task.Delay(millisTimeout);
}
}
private TimeSpan GetNextWaitDuration()
{
if (!lastEventTime.HasValue)
{
this.lastEventTime = DateTime.Now;
}
var origLastEventTime = this.lastEventTime.Value;
this.lastEventTime = origLastEventTime + TimeSpan.FromSeconds(exponentialDistribution.Next());
return this.lastEventTime.Value - origLastEventTime;
}
/// <summary>
/// Exp generator.
/// </summary>
private class ExponentialDistribution
{
readonly Random random;
readonly double lambda;
readonly double lambdaReciprocal;
public ExponentialDistribution(Random random, double lambda)
{
this.random = random;
this.lambda = lambda;
this.lambdaReciprocal = 1.0 / lambda;
}
public double Next()
{
double uniform = random.NextDouble();
// Use 1.0-uni above to avoid NaN if uni is 0
return lambdaReciprocal * (-Math.Log(1.0 - uniform));
}
}
}
}

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -217,7 +217,7 @@ namespace Grpc.IntegrationTesting
}
}
public static void RunEmptyUnary(TestService.ITestServiceClient client)
public static void RunEmptyUnary(TestService.TestServiceClient client)
{
Console.WriteLine("running empty_unary");
var response = client.EmptyCall(new Empty());
@ -225,7 +225,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunLargeUnary(TestService.ITestServiceClient client)
public static void RunLargeUnary(TestService.TestServiceClient client)
{
Console.WriteLine("running large_unary");
var request = new SimpleRequest
@ -241,7 +241,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunClientStreamingAsync(TestService.ITestServiceClient client)
public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running client_streaming");
@ -257,7 +257,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunServerStreamingAsync(TestService.ITestServiceClient client)
public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running server_streaming");
@ -281,7 +281,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunPingPongAsync(TestService.ITestServiceClient client)
public static async Task RunPingPongAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running ping_pong");
@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunEmptyStreamAsync(TestService.ITestServiceClient client)
public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running empty_stream");
using (var call = client.FullDuplexCall())
@ -434,7 +434,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCancelAfterBeginAsync(TestService.ITestServiceClient client)
public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running cancel_after_begin");
@ -451,7 +451,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCancelAfterFirstResponseAsync(TestService.ITestServiceClient client)
public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running cancel_after_first_response");
@ -477,7 +477,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunTimeoutOnSleepingServerAsync(TestService.ITestServiceClient client)
public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running timeout_on_sleeping_server");
@ -499,7 +499,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client)
public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running custom_metadata");
{
@ -546,7 +546,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client)
public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running status_code_and_message");
var echoStatus = new EchoStatus
@ -580,7 +580,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client)
public static void RunUnimplementedMethod(UnimplementedService.UnimplementedServiceClient client)
{
Console.WriteLine("running unimplemented_method");
var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));

@ -51,7 +51,7 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -50,15 +50,15 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
List<ChannelOption> options;
Mock<TestService.ITestService> serviceMock;
Mock<TestService.TestServiceBase> serviceMock;
AsyncAuthInterceptor asyncAuthInterceptor;
[SetUp]
public void Init()
{
serviceMock = new Mock<TestService.ITestService>();
serviceMock = new Mock<TestService.TestServiceBase>();
serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>()))
.Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler));

@ -36,6 +36,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IBenchmarkServiceClient
{
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -47,47 +48,73 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IBenchmarkService
{
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
}
// server-side abstract class
public abstract class BenchmarkServiceBase
{
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient
{
public BenchmarkServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public BenchmarkServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected BenchmarkServiceClient() : base()
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_StreamingCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingCall(new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
}
protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new BenchmarkServiceClient(configuration);
}
}
@ -99,6 +126,14 @@ namespace Grpc.Testing {
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
// creates a new client
public static BenchmarkServiceClient NewClient(Channel channel)
{
@ -153,6 +188,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IWorkerServiceClient
{
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -170,6 +206,7 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IWorkerService
{
Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
@ -178,71 +215,100 @@ namespace Grpc.Testing {
Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context);
}
// server-side abstract class
public abstract class WorkerServiceBase
{
public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class WorkerServiceClient : ClientBase, IWorkerServiceClient
public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient
{
public WorkerServiceClient(Channel channel) : base(channel)
{
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public WorkerServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected WorkerServiceClient() : base()
{
var call = CreateCall(__Method_RunServer, options);
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RunClient, options);
return Calls.AsyncDuplexStreamingCall(call);
return RunServer(new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
{
var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
}
public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_CoreCount, options);
return Calls.BlockingUnaryCall(call, request);
return RunClient(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
{
var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
}
public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_CoreCount, options);
return Calls.AsyncUnaryCall(call, request);
return CoreCount(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
}
public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_QuitWorker, options);
return Calls.BlockingUnaryCall(call, request);
return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_QuitWorker, options);
return Calls.AsyncUnaryCall(call, request);
return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
}
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
}
protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new WorkerServiceClient(configuration);
}
}
@ -256,6 +322,16 @@ namespace Grpc.Testing {
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer)
.AddMethod(__Method_RunClient, serviceImpl.RunClient)
.AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
// creates a new client
public static WorkerServiceClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -53,7 +53,7 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()

@ -69,6 +69,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface ITestServiceClient
{
global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -90,6 +91,7 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface ITestService
{
Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context);
@ -100,91 +102,126 @@ namespace Grpc.Testing {
Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
}
// server-side abstract class
public abstract class TestServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class TestServiceClient : ClientBase, ITestServiceClient
public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient
{
public TestServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public TestServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected TestServiceClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request);
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request);
return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
{
var call = CreateCall(__Method_StreamingOutputCall, options);
return Calls.AsyncServerStreamingCall(call, request);
return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request);
}
public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call);
return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
{
var call = CreateCall(__Method_StreamingInputCall, options);
return Calls.AsyncClientStreamingCall(call);
return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_FullDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_HalfDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
}
protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new TestServiceClient(configuration);
}
}
@ -200,6 +237,18 @@ namespace Grpc.Testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(TestServiceBase 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
public static TestServiceClient NewClient(Channel channel)
{
@ -227,6 +276,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IUnimplementedServiceClient
{
global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -236,36 +286,59 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IUnimplementedService
{
Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context);
}
// server-side abstract class
public abstract class UnimplementedServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class UnimplementedServiceClient : ClientBase, IUnimplementedServiceClient
public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient
{
public UnimplementedServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public UnimplementedServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected UnimplementedServiceClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
}
public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnimplementedCall, options);
return Calls.BlockingUnaryCall(call, request);
return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration)
{
var call = CreateCall(__Method_UnimplementedCall, options);
return Calls.AsyncUnaryCall(call, request);
return new UnimplementedServiceClient(configuration);
}
}
@ -276,6 +349,13 @@ namespace Grpc.Testing {
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
// creates a new client
public static UnimplementedServiceClient NewClient(Channel channel)
{
@ -311,6 +391,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IReconnectServiceClient
{
global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -324,57 +405,81 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IReconnectService
{
Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context);
Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context);
}
// server-side abstract class
public abstract class ReconnectServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class ReconnectServiceClient : ClientBase, IReconnectServiceClient
public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient
{
public ReconnectServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public ReconnectServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected ReconnectServiceClient() : base()
{
var call = CreateCall(__Method_Start, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Start, options);
return Calls.AsyncUnaryCall(call, request);
return Start(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request);
}
public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Stop, options);
return Calls.BlockingUnaryCall(call, request);
return StartAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Stop, options);
return Calls.AsyncUnaryCall(call, request);
return Stop(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request);
}
public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StopAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request);
}
protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new ReconnectServiceClient(configuration);
}
}
@ -386,6 +491,14 @@ namespace Grpc.Testing {
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start)
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
// creates a new client
public static ReconnectServiceClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -45,14 +45,14 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of TestService server
/// </summary>
public class TestServiceImpl : TestService.ITestService
public class TestServiceImpl : TestService.TestServiceBase
{
public Task<Empty> EmptyCall(Empty request, ServerCallContext context)
public override Task<Empty> EmptyCall(Empty request, ServerCallContext context)
{
return Task.FromResult(new Empty());
}
public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
EnsureEchoStatus(request.ResponseStatus, context);
@ -61,7 +61,7 @@ namespace Grpc.Testing
return response;
}
public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
EnsureEchoStatus(request.ResponseStatus, context);
@ -73,7 +73,7 @@ namespace Grpc.Testing
}
}
public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
@ -85,7 +85,7 @@ namespace Grpc.Testing
return new StreamingInputCallResponse { AggregatedPayloadSize = sum };
}
public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
@ -100,7 +100,7 @@ namespace Grpc.Testing
});
}
public async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new NotImplementedException();
}

@ -45,7 +45,7 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of WorkerService server
/// </summary>
public class WorkerServiceImpl : WorkerService.IWorkerService
public class WorkerServiceImpl : WorkerService.WorkerServiceBase
{
readonly Action stopRequestHandler;
@ -54,7 +54,7 @@ namespace Grpc.Testing
this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler);
}
public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
public override async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
{
GrpcPreconditions.CheckState(await requestStream.MoveNext());
var serverConfig = requestStream.Current.Setup;
@ -78,7 +78,7 @@ namespace Grpc.Testing
await runner.StopAsync();
}
public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
public override async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
{
GrpcPreconditions.CheckState(await requestStream.MoveNext());
var clientConfig = requestStream.Current.Setup;
@ -100,12 +100,12 @@ namespace Grpc.Testing
await runner.StopAsync();
}
public Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
public override Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
{
return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount });
}
public Task<Void> QuitWorker(Void request, ServerCallContext context)
public override Task<Void> QuitWorker(Void request, ServerCallContext context)
{
stopRequestHandler();
return Task.FromResult(new Void());

@ -10,7 +10,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency.</description>
<releaseNotes>Release of gRPC C core $version$ libraries.</releaseNotes>
<copyright>Copyright 2015-2016</copyright>
<copyright>Copyright 2015</copyright>
<title>gRPC C# Native Extension</title>
<summary>Native library required by gRPC C#</summary>
<tags>gRPC native</tags>

@ -36,8 +36,9 @@
"Math.Tests.MathClientServerTest",
"Grpc.HealthCheck.Tests.HealthClientServerTest",
"Grpc.HealthCheck.Tests.HealthServiceImplTest",
"Grpc.IntegrationTesting.HeaderInterceptorTest",
"Grpc.IntegrationTesting.HistogramTest",
"Grpc.IntegrationTesting.GeneratedClientTest",
"Grpc.IntegrationTesting.GeneratedServiceBaseTest",
"Grpc.IntegrationTesting.InteropClientServerTest",
"Grpc.IntegrationTesting.MetadataCredentialsTest",
"Grpc.IntegrationTesting.RunnerClientServerTest",

@ -1,5 +1,5 @@
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -158,6 +158,12 @@ message StreamingOutputCallResponse {
Payload payload = 1;
}
// For reconnect interop test only.
// Client tells server what reconnection parameters it used.
message ReconnectParams {
int32 max_reconnect_backoff_ms = 1;
}
// For reconnect interop test only.
// Server tells client whether its reconnects are following the spec and the
// reconnect backoffs it saw.

@ -1,5 +1,5 @@
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -80,6 +80,6 @@ service UnimplementedService {
// A service used to control reconnect server.
service ReconnectService {
rpc Start(grpc.testing.Empty) returns (grpc.testing.Empty);
rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty);
rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo);
}

@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import;
typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
extern grpc_server_request_call_type grpc_server_request_call_import;
#define grpc_server_request_call grpc_server_request_call_import
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags);
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
extern grpc_server_register_method_type grpc_server_register_method_import;
#define grpc_server_register_method grpc_server_register_method_import
typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -359,7 +359,7 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
md_ary->metadata[md_ary->count].value_length = value_len;
md_ary->count += 1;
}
} else {
} else if (TYPE(val) == T_STRING) {
value_str = RSTRING_PTR(val);
value_len = RSTRING_LEN(val);
if (!grpc_is_binary_header(key_str, key_len) &&
@ -373,6 +373,10 @@ static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
md_ary->metadata[md_ary->count].value = value_str;
md_ary->metadata[md_ary->count].value_length = value_len;
md_ary->count += 1;
} else {
rb_raise(rb_eArgError,
"Header values must be of type string or array");
return ST_STOP;
}
return ST_CONTINUE;

@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import;
typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
extern grpc_server_request_call_type grpc_server_request_call_import;
#define grpc_server_request_call grpc_server_request_call_import
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags);
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
extern grpc_server_register_method_type grpc_server_register_method_import;
#define grpc_server_register_method grpc_server_register_method_import
typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);

@ -193,44 +193,45 @@ describe 'ClientStub' do
describe '#client_streamer' do
shared_examples 'client streaming' do
before(:each) do
server_port = create_test_server
host = "localhost:#{server_port}"
@stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
@options = { k1: 'v1', k2: 'v2' }
@sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
@resp = 'a_reply'
end
it 'should send requests to/receive a reply from a server' do
server_port = create_test_server
host = "localhost:#{server_port}"
th = run_client_streamer(@sent_msgs, @resp, @pass)
stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
expect(get_response(stub)).to eq(@resp)
expect(get_response(@stub)).to eq(@resp)
th.join
end
it 'should send metadata to the server ok' do
server_port = create_test_server
host = "localhost:#{server_port}"
th = run_client_streamer(@sent_msgs, @resp, @pass,
k1: 'v1', k2: 'v2')
stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
expect(get_response(stub)).to eq(@resp)
th = run_client_streamer(@sent_msgs, @resp, @pass, @options)
expect(get_response(@stub)).to eq(@resp)
th.join
end
it 'should raise an error if the status is not ok' do
server_port = create_test_server
host = "localhost:#{server_port}"
th = run_client_streamer(@sent_msgs, @resp, @fail)
stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
blk = proc { get_response(stub) }
blk = proc { get_response(@stub) }
expect(&blk).to raise_error(GRPC::BadStatus)
th.join
end
it 'should raise ArgumentError if metadata contains invalid values' do
@options.merge!(k3: 3)
expect do
get_response(@stub)
end.to raise_error(ArgumentError,
/Header values must be of type string or array/)
end
end
describe 'without a call operation' do
def get_response(stub)
stub.client_streamer(@method, @sent_msgs, noop, noop,
k1: 'v1', k2: 'v2')
stub.client_streamer(@method, @sent_msgs, noop, noop, @options)
end
it_behaves_like 'client streaming'
@ -239,7 +240,7 @@ describe 'ClientStub' do
describe 'via a call operation' do
def get_response(stub)
op = stub.client_streamer(@method, @sent_msgs, noop, noop,
return_op: true, k1: 'v1', k2: 'v2')
@options.merge(return_op: true))
expect(op).to be_a(GRPC::ActiveCall::Operation)
op.execute
end

@ -109,7 +109,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
grpc_server_register_completion_queue(a.server, a.cq, NULL);
a.registered_method =
grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
GRPC_BAD_CLIENT_REGISTERED_HOST, 0);
GRPC_BAD_CLIENT_REGISTERED_HOST,
GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
grpc_server_start(a.server);
transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0);
server_setup_transport(&a, transport);

@ -44,6 +44,7 @@ BAD_CLIENT_TESTS = {
'connection_prefix': default_test_options._replace(cpu_cost=0.2),
'headers': default_test_options._replace(cpu_cost=0.2),
'initial_settings_frame': default_test_options._replace(cpu_cost=0.2),
'head_of_line_blocking': default_test_options,
'server_registered_method': default_test_options,
'simple_request': default_test_options,
'window_overflow': default_test_options,

@ -0,0 +1,151 @@
/*
*
* 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 "test/core/bad_client/bad_client.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include "src/core/lib/surface/server.h"
#include "test/core/end2end/cq_verifier.h"
static const char prefix[] =
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
// settings frame
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
// stream 1 headers: generated from server_registered_method.headers in this
// directory
"\x00\x00\xd0\x01\x04\x00\x00\x00\x01"
"\x10\x05:path\x0f/registered/bar"
"\x10\x07:scheme\x04http"
"\x10\x07:method\x04POST"
"\x10\x0a:authority\x09localhost"
"\x10\x0c"
"content-type\x10"
"application/grpc"
"\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
"\x10\x02te\x08trailers"
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
// data frame for stream 1: advertise a 10000 byte payload (that we won't
// fulfill)
"\x00\x00\x05\x00\x00\x00\x00\x00\x01"
"\x01\x00\x00\x27\x10"
// stream 3 headers: generated from server_registered_method.headers in this
// directory
"\x00\x00\xd0\x01\x04\x00\x00\x00\x03"
"\x10\x05:path\x0f/registered/bar"
"\x10\x07:scheme\x04http"
"\x10\x07:method\x04POST"
"\x10\x0a:authority\x09localhost"
"\x10\x0c"
"content-type\x10"
"application/grpc"
"\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
"\x10\x02te\x08trailers"
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
// data frame for stream 3: advertise a 10000 byte payload (that we will
// fulfill)
"\x00\x00\x05\x00\x00\x00\x00\x00\x03"
"\x01\x00\x00\x27\x10"
"";
static void *tag(intptr_t t) { return (void *)t; }
static void verifier(grpc_server *server, grpc_completion_queue *cq,
void *registered_method) {
grpc_call_error error;
grpc_call *s;
cq_verifier *cqv = cq_verifier_create(cq);
grpc_metadata_array request_metadata_recv;
gpr_timespec deadline;
grpc_byte_buffer *payload = NULL;
grpc_metadata_array_init(&request_metadata_recv);
error = grpc_server_request_registered_call(server, registered_method, &s,
&deadline, &request_metadata_recv,
&payload, cq, cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(101), 1);
cq_verify(cqv);
GPR_ASSERT(payload != NULL);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_destroy(s);
grpc_byte_buffer_destroy(payload);
cq_verifier_destroy(cqv);
}
char *g_buffer;
size_t g_cap = 0;
size_t g_count = 0;
static void addbuf(const void *data, size_t len) {
if (g_count + len > g_cap) {
g_cap = GPR_MAX(g_count + len, g_cap * 2);
g_buffer = gpr_realloc(g_buffer, g_cap);
}
memcpy(g_buffer + g_count, data, len);
g_count += len;
}
int main(int argc, char **argv) {
int i;
grpc_test_init(argc, argv);
#define NUM_FRAMES 10
#define FRAME_SIZE 1000
addbuf(prefix, sizeof(prefix) - 1);
for (i = 0; i < NUM_FRAMES; i++) {
uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16),
(uint8_t)(FRAME_SIZE >> 8),
(uint8_t)FRAME_SIZE,
0,
0,
0,
0,
0,
3};
uint8_t msg[FRAME_SIZE];
memset(msg, 'a', sizeof(msg));
addbuf(hdr, sizeof(hdr));
addbuf(msg, FRAME_SIZE);
}
grpc_run_bad_client_test(verifier, g_buffer, g_count, 0);
gpr_free(g_buffer);
return 0;
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -42,19 +42,25 @@ void test_register_method_fail(void) {
grpc_server *server = grpc_server_create(NULL, NULL);
void *method;
void *method_old;
method = grpc_server_register_method(server, NULL, NULL, 0);
method =
grpc_server_register_method(server, NULL, NULL, GRPC_SRM_PAYLOAD_NONE, 0);
GPR_ASSERT(method == NULL);
method_old = grpc_server_register_method(server, "m", "h", 0);
method_old =
grpc_server_register_method(server, "m", "h", GRPC_SRM_PAYLOAD_NONE, 0);
GPR_ASSERT(method_old != NULL);
method = grpc_server_register_method(server, "m", "h", 0);
method = grpc_server_register_method(
server, "m", "h", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
GPR_ASSERT(method == NULL);
method_old = grpc_server_register_method(
server, "m2", "h2", GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
method_old =
grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE,
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
GPR_ASSERT(method_old != NULL);
method = grpc_server_register_method(server, "m2", "h2", 0);
method =
grpc_server_register_method(server, "m2", "h2", GRPC_SRM_PAYLOAD_NONE, 0);
GPR_ASSERT(method == NULL);
method = grpc_server_register_method(
server, "m2", "h2", GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
server, "m2", "h2", GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST);
GPR_ASSERT(method == NULL);
grpc_server_destroy(server);
}

@ -60,8 +60,12 @@ static void pretty_print_backoffs(reconnect_server *server) {
i, backoff / 1000.0, expected_backoff / 1000.0,
(backoff - expected_backoff) * 100.0 / expected_backoff);
expected_backoff *= 1.6;
if (expected_backoff > 120 * 1000) {
expected_backoff = 120 * 1000;
int max_reconnect_backoff_ms = 120 * 1000;
if (server->max_reconnect_backoff_ms > 0) {
max_reconnect_backoff_ms = server->max_reconnect_backoff_ms;
}
if (expected_backoff > max_reconnect_backoff_ms) {
expected_backoff = max_reconnect_backoff_ms;
}
}
}
@ -108,6 +112,7 @@ void reconnect_server_init(reconnect_server *server) {
server->head = NULL;
server->tail = NULL;
server->peer = NULL;
server->max_reconnect_backoff_ms = 0;
}
void reconnect_server_start(reconnect_server *server, int port) {

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -52,6 +52,7 @@ typedef struct reconnect_server {
timestamp_list *head;
timestamp_list *tail;
char *peer;
int max_reconnect_backoff_ms;
} reconnect_server;
void reconnect_server_init(reconnect_server *server);

@ -37,6 +37,7 @@
#include <gflags/gflags.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/support/channel_arguments.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/proto/grpc/testing/empty.grpc.pb.h"
@ -48,13 +49,18 @@
DEFINE_int32(server_control_port, 0, "Server port for control rpcs.");
DEFINE_int32(server_retry_port, 0, "Server port for testing reconnection.");
DEFINE_string(server_host, "127.0.0.1", "Server host to connect to");
DEFINE_int32(max_reconnect_backoff_ms, 0,
"Maximum backoff time, or 0 for default.");
using grpc::CallCredentials;
using grpc::Channel;
using grpc::ChannelArguments;
using grpc::ClientContext;
using grpc::CreateTestChannel;
using grpc::Status;
using grpc::testing::Empty;
using grpc::testing::ReconnectInfo;
using grpc::testing::ReconnectParams;
using grpc::testing::ReconnectService;
int main(int argc, char** argv) {
@ -68,17 +74,25 @@ int main(int argc, char** argv) {
ReconnectService::NewStub(
CreateTestChannel(server_address.str(), false)));
ClientContext start_context;
Empty empty_request;
ReconnectParams reconnect_params;
reconnect_params.set_max_reconnect_backoff_ms(FLAGS_max_reconnect_backoff_ms);
Empty empty_response;
Status start_status =
control_stub->Start(&start_context, empty_request, &empty_response);
control_stub->Start(&start_context, reconnect_params, &empty_response);
GPR_ASSERT(start_status.ok());
gpr_log(GPR_INFO, "Starting connections with retries.");
server_address.str("");
server_address << FLAGS_server_host << ':' << FLAGS_server_retry_port;
ChannelArguments channel_args;
if (FLAGS_max_reconnect_backoff_ms > 0) {
channel_args.SetInt(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS,
FLAGS_max_reconnect_backoff_ms);
}
std::shared_ptr<Channel> retry_channel =
CreateTestChannel(server_address.str(), true);
CreateTestChannel(server_address.str(), "foo.test.google.fr", true, false,
std::shared_ptr<CallCredentials>(), channel_args);
// About 13 retries.
const int kDeadlineSeconds = 540;
// Use any rpc to test retry.
@ -88,15 +102,15 @@ int main(int argc, char** argv) {
retry_context.set_deadline(std::chrono::system_clock::now() +
std::chrono::seconds(kDeadlineSeconds));
Status retry_status =
retry_stub->Start(&retry_context, empty_request, &empty_response);
retry_stub->Start(&retry_context, reconnect_params, &empty_response);
GPR_ASSERT(retry_status.error_code() == grpc::StatusCode::DEADLINE_EXCEEDED);
gpr_log(GPR_INFO, "Done retrying, getting final data from server");
ClientContext stop_context;
ReconnectInfo response;
Status stop_status =
control_stub->Stop(&stop_context, empty_request, &response);
Status stop_status = control_stub->Stop(&stop_context, Empty(), &response);
GPR_ASSERT(stop_status.ok());
GPR_ASSERT(response.passed() == true);
gpr_log(GPR_INFO, "Passed");
return 0;
}

@ -71,6 +71,7 @@ using grpc::Status;
using grpc::testing::Empty;
using grpc::testing::ReconnectService;
using grpc::testing::ReconnectInfo;
using grpc::testing::ReconnectParams;
static bool got_sigint = false;
@ -92,7 +93,8 @@ class ReconnectServiceImpl : public ReconnectService::Service {
void Poll(int seconds) { reconnect_server_poll(&tcp_server_, seconds); }
Status Start(ServerContext* context, const Empty* request, Empty* response) {
Status Start(ServerContext* context, const ReconnectParams* request,
Empty* response) {
bool start_server = true;
std::unique_lock<std::mutex> lock(mu_);
while (serving_ && !shutdown_) {
@ -105,6 +107,8 @@ class ReconnectServiceImpl : public ReconnectService::Service {
if (server_started_) {
start_server = false;
} else {
tcp_server_.max_reconnect_backoff_ms =
request->max_reconnect_backoff_ms();
server_started_ = true;
}
lock.unlock();
@ -133,7 +137,9 @@ class ReconnectServiceImpl : public ReconnectService::Service {
const double kTransmissionDelay = 100.0;
const double kBackoffMultiplier = 1.6;
const double kJitterFactor = 0.2;
const int kMaxBackoffMs = 120 * 1000;
const int kMaxBackoffMs = tcp_server_.max_reconnect_backoff_ms
? tcp_server_.max_reconnect_backoff_ms
: 120 * 1000;
bool passed = true;
for (timestamp_list* cur = tcp_server_.head; cur && cur->next;
cur = cur->next) {

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -58,8 +58,9 @@ namespace grpc {
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
bool enable_ssl, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds) {
ChannelArguments channel_args;
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args) {
ChannelArguments channel_args(args);
if (enable_ssl) {
const char* roots_certs = use_prod_roots ? "" : test_root_cert;
SslCredentialsOptions ssl_opts = {roots_certs, "", ""};
@ -81,6 +82,14 @@ std::shared_ptr<Channel> CreateTestChannel(
}
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
bool enable_ssl, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds) {
return CreateTestChannel(server, override_hostname, enable_ssl,
use_prod_roots, creds, ChannelArguments());
}
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
bool enable_ssl, bool use_prod_roots) {

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -53,6 +53,12 @@ std::shared_ptr<Channel> CreateTestChannel(
bool enable_ssl, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds);
std::shared_ptr<Channel> CreateTestChannel(
const grpc::string& server, const grpc::string& override_hostname,
bool enable_ssl, bool use_prod_roots,
const std::shared_ptr<CallCredentials>& creds,
const ChannelArguments& args);
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_CREATE_TEST_CHANNEL_H

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -0,0 +1,28 @@
# Copyright 2016, 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.

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -36,16 +36,17 @@ cd $(dirname $0)/../../..
CONFIG=${CONFIG:-opt}
# build C++ qps worker & driver always - we need at least the driver to
# run any of the scenarios.
# TODO(jtattermusch): not embedding OpenSSL breaks the C# build because
# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
# this build will be reused.
make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_driver -j8
for language in $@
do
if [ "$language" == "c++" ]
if [ "$language" != "c++" ]
then
# build C++ qps worker & driver
# TODO(jtattermusch): not embedding OpenSSL breaks the C# build because
# grpc_csharp_ext needs OpenSSL embedded and some intermediate files from
# this build will be reused.
make CONFIG=${CONFIG} EMBED_OPENSSL=true EMBED_ZLIB=true qps_worker qps_driver -j8
else
tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8
fi
done

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -0,0 +1,153 @@
# Copyright 2016, 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.
# performance scenario configuration for various languages
class CXXLanguage:
def __init__(self):
self.safename = 'cxx'
def worker_cmdline(self):
return ['bins/opt/qps_worker']
def worker_port_offset(self):
return 0
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
# Scenario 1: generic async streaming ping-pong (contentionless latency)
'cpp_async_generic_streaming_ping_pong': [
'--rpc_type=STREAMING',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_GENERIC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--bbuf_req_size=0',
'--bbuf_resp_size=0',
'--async_client_threads=1',
'--async_server_threads=1',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0'],
# Scenario 5: Sync unary ping-pong with protobufs
'cpp_sync_unary_ping_pong_protobuf': [
'--rpc_type=UNARY',
'--client_type=SYNC_CLIENT',
'--server_type=SYNC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--simple_req_size=0',
'--simple_resp_size=0',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'c++'
class CSharpLanguage:
def __init__(self):
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_csharp.sh']
def worker_port_offset(self):
return 100
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
# Scenario 1: generic async streaming ping-pong (contentionless latency)
'csharp_async_generic_streaming_ping_pong': [
'--rpc_type=STREAMING',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_GENERIC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--bbuf_req_size=0',
'--bbuf_resp_size=0',
'--async_client_threads=1',
'--async_server_threads=1',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'csharp'
class NodeLanguage:
def __init__(self):
pass
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_node.sh']
def worker_port_offset(self):
return 200
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
'node_sync_unary_ping_pong_protobuf': [
'--rpc_type=UNARY',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--simple_req_size=0',
'--simple_resp_size=0',
'--secure_test=false',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'node'
LANGUAGES = {
'c++' : CXXLanguage(),
'csharp' : CSharpLanguage(),
'node' : NodeLanguage(),
}

@ -40,6 +40,7 @@ import sys
import tempfile
import time
import uuid
import performance.scenario_config as scenario_config
_ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..'))
@ -49,130 +50,6 @@ os.chdir(_ROOT)
_REMOTE_HOST_USERNAME = 'jenkins'
class CXXLanguage:
def __init__(self):
self.safename = 'cxx'
def worker_cmdline(self):
return ['bins/opt/qps_worker']
def worker_port_offset(self):
return 0
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
# Scenario 1: generic async streaming ping-pong (contentionless latency)
'cpp_async_generic_streaming_ping_pong': [
'--rpc_type=STREAMING',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_GENERIC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--bbuf_req_size=0',
'--bbuf_resp_size=0',
'--async_client_threads=1',
'--async_server_threads=1',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0'],
# Scenario 5: Sync unary ping-pong with protobufs
'cpp_sync_unary_ping_pong_protobuf': [
'--rpc_type=UNARY',
'--client_type=SYNC_CLIENT',
'--server_type=SYNC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--simple_req_size=0',
'--simple_resp_size=0',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'c++'
class CSharpLanguage:
def __init__(self):
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_csharp.sh']
def worker_port_offset(self):
return 100
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
# Scenario 1: generic async streaming ping-pong (contentionless latency)
'csharp_async_generic_streaming_ping_pong': [
'--rpc_type=STREAMING',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_GENERIC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--bbuf_req_size=0',
'--bbuf_resp_size=0',
'--async_client_threads=1',
'--async_server_threads=1',
'--secure_test=true',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'csharp'
class NodeLanguage:
def __init__(self):
pass
self.safename = str(self)
def worker_cmdline(self):
return ['tools/run_tests/performance/run_worker_node.sh']
def worker_port_offset(self):
return 200
def scenarios(self):
# TODO(jtattermusch): add more scenarios
return {
'node_sync_unary_ping_pong_protobuf': [
'--rpc_type=UNARY',
'--client_type=ASYNC_CLIENT',
'--server_type=ASYNC_SERVER',
'--outstanding_rpcs_per_channel=1',
'--client_channels=1',
'--simple_req_size=0',
'--simple_resp_size=0',
'--secure_test=false',
'--num_servers=1',
'--num_clients=1',
'--server_core_limit=0',
'--client_core_limit=0']}
def __str__(self):
return 'node'
_LANGUAGES = {
'c++' : CXXLanguage(),
'csharp' : CSharpLanguage(),
'node' : NodeLanguage(),
}
class QpsWorkerJob:
"""Encapsulates a qps worker server job."""
@ -272,7 +149,7 @@ def prepare_remote_hosts(hosts):
sys.exit(1)
def build_on_remote_hosts(hosts, languages=_LANGUAGES.keys(), build_local=False):
def build_on_remote_hosts(hosts, languages=scenario_config.LANGUAGES.keys(), build_local=False):
"""Builds performance worker on remote hosts (and maybe also locally)."""
build_timeout = 15*60
build_jobs = []
@ -366,7 +243,7 @@ def finish_qps_workers(jobs):
argp = argparse.ArgumentParser(description='Run performance tests.')
argp.add_argument('-l', '--language',
choices=['all'] + sorted(_LANGUAGES.keys()),
choices=['all'] + sorted(scenario_config.LANGUAGES.keys()),
nargs='+',
default=['all'],
help='Languages to benchmark.')
@ -380,9 +257,9 @@ argp.add_argument('--remote_worker_host',
args = argp.parse_args()
languages = set(_LANGUAGES[l]
languages = set(scenario_config.LANGUAGES[l]
for l in itertools.chain.from_iterable(
_LANGUAGES.iterkeys() if x == 'all' else [x]
scenario_config.LANGUAGES.iterkeys() if x == 'all' else [x]
for x in args.language))
# Put together set of remote hosts where to run and build

@ -3160,6 +3160,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"bad_client_test",
"gpr",
"gpr_test_util",
"grpc_test_util_unsecure",
"grpc_unsecure"
],
"headers": [],
"language": "c",
"name": "head_of_line_blocking_bad_client_test",
"src": [
"test/core/bad_client/tests/head_of_line_blocking.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"bad_client_test",

@ -2608,6 +2608,27 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "head_of_line_blocking_bad_client_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"args": [],
"ci_platforms": [

@ -1066,6 +1066,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "connection_prefix_bad_clien
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "head_of_line_blocking_bad_client_test", "vcxproj\test\head_of_line_blocking_bad_client_test\head_of_line_blocking_bad_client_test.vcxproj", "{23DF0572-DBF1-08DA-8EAD-8508354C90A4}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{BA67B418-B699-E41A-9CC4-0279C49481A5} = {BA67B418-B699-E41A-9CC4-0279C49481A5}
{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF} = {0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}
{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5} = {46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "headers_bad_client_test", "vcxproj\test\headers_bad_client_test\headers_bad_client_test.vcxproj", "{7819A11E-607E-F0C0-FC47-C704CF7D818C}"
ProjectSection(myProperties) = preProject
lib = "False"
@ -3038,6 +3050,22 @@ Global
{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|Win32.Build.0 = Release|Win32
{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|x64.ActiveCfg = Release|x64
{AF9D0EB2-2A53-B815-3A63-E82C7F91DB29}.Release-DLL|x64.Build.0 = Release|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|Win32.ActiveCfg = Debug|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|x64.ActiveCfg = Debug|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|Win32.ActiveCfg = Release|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|x64.ActiveCfg = Release|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|Win32.Build.0 = Debug|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug|x64.Build.0 = Debug|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|Win32.Build.0 = Release|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release|x64.Build.0 = Release|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|Win32.Build.0 = Debug|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|x64.ActiveCfg = Debug|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Debug-DLL|x64.Build.0 = Debug|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|Win32.ActiveCfg = Release|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|Win32.Build.0 = Release|Win32
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|x64.ActiveCfg = Release|x64
{23DF0572-DBF1-08DA-8EAD-8508354C90A4}.Release-DLL|x64.Build.0 = Release|x64
{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Debug|Win32.ActiveCfg = Debug|Win32
{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Debug|x64.ActiveCfg = Debug|x64
{7819A11E-607E-F0C0-FC47-C704CF7D818C}.Release|Win32.ActiveCfg = Release|Win32

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{23DF0572-DBF1-08DA-8EAD-8508354C90A4}</ProjectGuid>
<IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
<IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\..\vsprojects\global.props" />
<Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
<Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
<Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetName>head_of_line_blocking_bad_client_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetName>head_of_line_blocking_bad_client_test</TargetName>
<Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
<Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
<Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
<Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
<MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
<GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\bad_client\tests\head_of_line_blocking.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\test/bad_client\bad_client_test\bad_client_test.vcxproj">
<Project>{BA67B418-B699-E41A-9CC4-0279C49481A5}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util_unsecure\grpc_test_util_unsecure.vcxproj">
<Project>{0A7E7F92-FDEA-40F1-A9EC-3BA484F98BBF}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_unsecure\grpc_unsecure.vcxproj">
<Project>{46CEDFFF-9692-456A-AA24-38B5D6BCF4C5}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
<Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
<Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
<Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
<Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
</Target>
</Project>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\core\bad_client\tests\head_of_line_blocking.c">
<Filter>test\core\bad_client\tests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="test">
<UniqueIdentifier>{c7d7f2b5-9afd-5668-b11f-ceb3a3503569}</UniqueIdentifier>
</Filter>
<Filter Include="test\core">
<UniqueIdentifier>{3175d310-96bd-0c78-72e3-b5985873fa82}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\bad_client">
<UniqueIdentifier>{d7e592e2-acda-4572-59b7-20845fb05bd5}</UniqueIdentifier>
</Filter>
<Filter Include="test\core\bad_client\tests">
<UniqueIdentifier>{1fa3207b-dc88-d316-7c13-9ac70ddc850e}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
Loading…
Cancel
Save