Merge branch 'master' into fix_alarm

pull/11579/head
Sree Kuchibhotla 8 years ago
commit b633a86e1a
  1. 71
      .pylintrc
  2. 355
      CMakeLists.txt
  3. 2
      Makefile
  4. 16
      doc/PROTOCOL-HTTP2.md
  5. 21
      include/grpc++/alarm.h
  6. 90
      include/grpc++/impl/codegen/async_unary_call.h
  7. 22
      include/grpc++/impl/codegen/call.h
  8. 40
      src/compiler/php_generator.cc
  9. 14
      src/compiler/php_generator_helpers.h
  10. 45
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c
  11. 38
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c
  12. 2
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
  13. 2
      src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
  14. 15
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c
  15. 35
      src/core/ext/filters/http/message_compress/message_compress_filter.c
  16. 4
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  17. 2
      src/core/ext/transport/chttp2/transport/frame_rst_stream.c
  18. 14
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  19. 2
      src/core/ext/transport/chttp2/transport/hpack_encoder.h
  20. 1
      src/core/ext/transport/chttp2/transport/internal.h
  21. 12
      src/core/ext/transport/chttp2/transport/parsing.c
  22. 87
      src/core/ext/transport/chttp2/transport/writing.c
  23. 52
      src/core/ext/transport/cronet/transport/cronet_transport.c
  24. 10
      src/core/lib/http/httpcli_security_connector.c
  25. 12
      src/core/lib/iomgr/closure.h
  26. 5
      src/core/lib/iomgr/ev_epollsig_linux.c
  27. 5
      src/core/lib/iomgr/ev_poll_posix.c
  28. 2
      src/core/lib/support/time_precise.c
  29. 53
      src/core/lib/surface/call.c
  30. 2
      src/core/lib/surface/server.c
  31. 5
      src/core/lib/transport/transport.c
  32. 14
      src/core/lib/transport/transport.h
  33. 54
      src/cpp/common/channel_filter.h
  34. 260
      src/csharp/Grpc.IntegrationTesting/Control.cs
  35. 112
      src/csharp/Grpc.IntegrationTesting/CustomErrorDetailsTest.cs
  36. 1354
      src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
  37. 34
      src/csharp/Grpc.IntegrationTesting/Services.cs
  38. 266
      src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
  39. 93
      src/csharp/Grpc.IntegrationTesting/Stats.cs
  40. 2
      src/csharp/generate_proto_csharp.sh
  41. 1
      src/csharp/tests.json
  42. 6
      src/objective-c/GRPCClient/GRPCCall.h
  43. 2
      src/objective-c/GRPCClient/GRPCCall.m
  44. 1
      src/objective-c/GRPCClient/private/GRPCChannel.h
  45. 10
      src/objective-c/GRPCClient/private/GRPCChannel.m
  46. 1
      src/objective-c/GRPCClient/private/GRPCHost.h
  47. 3
      src/objective-c/GRPCClient/private/GRPCHost.m
  48. 1
      src/objective-c/GRPCClient/private/GRPCWrappedCall.h
  49. 9
      src/objective-c/GRPCClient/private/GRPCWrappedCall.m
  50. 4
      src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
  51. 5
      src/python/grpcio/grpc/_channel.py
  52. 3
      src/python/grpcio/grpc/_server.py
  53. 55
      templates/CMakeLists.txt.template
  54. 78
      templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
  55. 9
      templates/tools/dockerfile/node_deps.include
  56. 8
      test/core/end2end/end2end_nosec_tests.c
  57. 8
      test/core/end2end/end2end_tests.c
  58. 1
      test/core/end2end/gen_build_yaml.py
  59. 1
      test/core/end2end/generate_tests.bzl
  60. 5
      test/core/end2end/tests/bad_ping.c
  61. 298
      test/core/end2end/tests/cancel_after_round_trip.c
  62. 91
      test/core/end2end/tests/compressed_payload.c
  63. 6
      test/core/transport/chttp2/hpack_encoder_test.c
  64. 31
      test/cpp/common/alarm_cpp_test.cc
  65. 4
      test/cpp/common/channel_filter_test.cc
  66. 60
      test/cpp/end2end/client_lb_end2end_test.cc
  67. 3
      test/cpp/end2end/filter_end2end_test.cc
  68. 2
      test/cpp/microbenchmarks/bm_chttp2_hpack.cc
  69. 1
      third_party/cares/cares.BUILD
  70. 7
      tools/distrib/pylint_code.sh
  71. 76
      tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
  72. 9
      tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
  73. 9
      tools/dockerfile/test/multilang_jessie_x64/Dockerfile
  74. 9
      tools/dockerfile/test/node_jessie_x64/Dockerfile
  75. 27
      tools/gcp/utils/big_query_utils.py
  76. 52
      tools/grift/Dockerfile
  77. 24
      tools/grift/README.md
  78. 2505
      tools/grift/grpc_plugins_generator.patch
  79. 54
      tools/internal_ci/helper_scripts/prepare_build_macos_rc
  80. 27
      tools/internal_ci/macos/grpc_build_artifacts.sh
  81. 2
      tools/internal_ci/macos/grpc_master.sh
  82. 2
      tools/run_tests/artifacts/build_artifact_node.sh
  83. 2
      tools/run_tests/artifacts/build_package_node.sh
  84. 2
      tools/run_tests/generated/sources_and_headers.json
  85. 950
      tools/run_tests/generated/tests.json
  86. 3
      tools/run_tests/helper_scripts/build_node_electron.sh
  87. 3
      tools/run_tests/helper_scripts/pre_build_node.sh
  88. 2
      tools/run_tests/helper_scripts/pre_build_node_electron.sh
  89. 2
      tools/run_tests/helper_scripts/run_node_electron.sh
  90. 36
      tools/run_tests/interop/android/android_interop_helper.sh
  91. 30
      tools/run_tests/interop/android/run_android_tests_on_firebase.sh
  92. 55
      tools/run_tests/performance/patch_scenario_results_schema.py
  93. 2
      tools/run_tests/performance/run_worker_node.sh
  94. 20
      tools/run_tests/performance/scenario_result_schema.json
  95. 2
      tools/run_tests/python_utils/upload_test_results.py
  96. 2
      tools/run_tests/run_tests.py
  97. 2
      vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj
  98. 3
      vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters
  99. 2
      vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj
  100. 3
      vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters

@ -1,15 +1,18 @@
[VARIABLES]
# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
# not include "unused_" and "ignored_" by default?
dummy-variables-rgx=^ignored_|^unused_
[DESIGN]
# NOTE(nathaniel): Not particularly attached to this value; it just seems to
# be what works for us at the moment (excepting the dead-code-walking Beta
# API).
max-args=6
[MISCELLANEOUS]
# NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and
# "NOTE(<username or issue link>): ". We do not allow "TODO:",
# "TODO(<username>):", "FIXME:", or anything else.
@ -17,24 +20,50 @@ notes=FIXME,XXX
[MESSAGES CONTROL]
#TODO: Enable missing-docstring
#TODO: Enable too-few-public-methods
#TODO: Enable no-init
#TODO: Enable duplicate-code
#TODO: Enable invalid-name
#TODO: Enable locally-disabled
#TODO: Enable protected-access
#TODO: Enable no-name-in-module
#TODO: Enable wrong-import-order
# TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
# enable cyclic-import after a 1.7-or-later pylint release that recognizes our
# disable=cyclic-import suppressions.
#TODO: Enable too-many-instance-attributes
#TODO: Enable too-many-lines
#TODO: Enable redefined-variable-type
#TODO: Enable next-method-called
#TODO: Enable import-error
#TODO: Enable useless-else-on-loop
#TODO: Enable too-many-nested-blocks
disable=missing-docstring,too-few-public-methods,no-init,duplicate-code,invalid-name,locally-disabled,protected-access,no-name-in-module,wrong-import-order,cyclic-import,too-many-instance-attributes,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-nested-blocks
disable=
# TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
# Enable cyclic-import after a 1.7-or-later pylint release that
# recognizes our disable=cyclic-import suppressions.
cyclic-import,
# TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the
# Beta API is removed.
duplicate-code,
# TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to
# understand enum and concurrent.futures; look into this later with the
# latest pylint version.
import-error,
# TODO(https://github.com/grpc/grpc/issues/261): Enable this one.
# Should take a little configuration but not much.
invalid-name,
# TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to
# work for now? Try with a later pylint?
locally-disabled,
# NOTE(nathaniel): We don't write doc strings for most private code
# elements.
missing-docstring,
# NOTE(nathaniel): Our completely abstract interface classes don't have
# constructors.
no-init,
# TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play
# nicely with some of our code being implemented in Cython. Maybe in a
# later version?
no-name-in-module,
# TODO(https://github.com/grpc/grpc/issues/261): Suppress these where
# the odd shape of the authentication portion of the API forces them on
# us and enable everywhere else.
protected-access,
# NOTE(nathaniel): Pylint and I will probably never agree on this.
too-few-public-methods,
# NOTE(nathaniel): Pylint and I wil probably never agree on this for
# private classes. For public classes maybe?
too-many-instance-attributes,
# NOTE(nathaniel): Some of our modules have a lot of lines... of
# specification and documentation. Maybe if this were
# lines-of-code-based we would use it.
too-many-lines,
# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
# this one if we extracted just a few more helper functions...
too-many-nested-blocks,
# NOTE(nathaniel): I have disputed the premise of this inspection from
# the beginning and will continue to do so until it goes away for good.
useless-else-on-loop,

File diff suppressed because it is too large Load Diff

@ -7892,6 +7892,7 @@ LIBEND2END_TESTS_SRC = \
test/core/end2end/tests/cancel_after_accept.c \
test/core/end2end/tests/cancel_after_client_done.c \
test/core/end2end/tests/cancel_after_invoke.c \
test/core/end2end/tests/cancel_after_round_trip.c \
test/core/end2end/tests/cancel_before_invoke.c \
test/core/end2end/tests/cancel_in_a_vacuum.c \
test/core/end2end/tests/cancel_with_status.c \
@ -7985,6 +7986,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \
test/core/end2end/tests/cancel_after_accept.c \
test/core/end2end/tests/cancel_after_client_done.c \
test/core/end2end/tests/cancel_after_invoke.c \
test/core/end2end/tests/cancel_after_round_trip.c \
test/core/end2end/tests/cancel_before_invoke.c \
test/core/end2end/tests/cancel_in_a_vacuum.c \
test/core/end2end/tests/cancel_with_status.c \

@ -24,7 +24,8 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
* **Call-Definition** → Method Scheme Path TE [Authority] [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent]
* **Method** → ":method POST"
* **Scheme** → ":scheme " ("http" / "https")
* **Path** → ":path" {_path identifying method within exposed API_}
* **Path** → ":path" "/" Service-Name "/" {_method name_}
* **Service-Name** → {_IDL-specific service name_}
* **Authority** → ":authority" {_virtual host name of authority_}
* **TE** → "te" "trailers" # Used to detect incompatible proxies
* **Timeout** → "grpc-timeout" TimeoutValue TimeoutUnit
@ -51,6 +52,13 @@ Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.
HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.
Some gRPC implementations may allow the **Path** format shown above
to be overridden, but this functionality is strongly discouraged.
gRPC does not go out of its way to break users that are using this kind
of override, but we do not actively support it, and some functionality
(e.g., service config support) will not work when the path is not of
the form shown above.
If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.
**Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**.
@ -238,10 +246,10 @@ If a detectable connection failure occurs on the client all calls will be closed
### Appendix A - GRPC for Protobuf
The service interfaces declared by protobuf are easily mapped onto GRPC by code generation extensions to protoc. The following defines the mapping to be used
The service interfaces declared by protobuf are easily mapped onto GRPC by
code generation extensions to protoc. The following defines the mapping
to be used.
* **Path** → / Service-Name / {_method name_}
* **Service-Name** → ?( {_proto package name_} "." ) {_service name_}
* **Message-Type** → {_fully qualified proto message name_}
* **Content-Type** → "application/grpc+proto"

@ -52,8 +52,25 @@ class Alarm : private GrpcLibraryCodegen {
alarm_(grpc_alarm_create(cq->cq(), TimePoint<T>(deadline).raw_time(),
static_cast<void*>(&tag_))) {}
/// Alarms aren't copyable.
Alarm(const Alarm&) = delete;
Alarm& operator=(const Alarm&) = delete;
/// Alarms are movable.
Alarm(Alarm&& rhs) : tag_(rhs.tag_), alarm_(rhs.alarm_) {
rhs.alarm_ = nullptr;
}
Alarm& operator=(Alarm&& rhs) {
tag_ = rhs.tag_;
alarm_ = rhs.alarm_;
rhs.alarm_ = nullptr;
return *this;
}
/// Destroy the given completion queue alarm, cancelling it in the process.
~Alarm() { grpc_alarm_destroy(alarm_); }
~Alarm() {
if (alarm_ != nullptr) grpc_alarm_destroy(alarm_);
}
/// Cancel a completion queue alarm. Calling this function over an alarm that
/// has already fired has no effect.
@ -73,7 +90,7 @@ class Alarm : private GrpcLibraryCodegen {
};
AlarmEntry tag_;
grpc_alarm* const alarm_; // owned
grpc_alarm* alarm_; // owned
};
} // namespace grpc

@ -87,6 +87,28 @@ class ClientAsyncResponseReader final
ClientAsyncResponseReader(call, context, request);
}
/// TODO(vjpai): Delete the below constructor
/// PLEASE DO NOT USE THIS CONSTRUCTOR IN NEW CODE
/// This code is only present as a short-term workaround
/// for users that bypassed the code-generator and directly
/// created this struct rather than properly using a stub.
/// This code will not remain a valid public constructor for long.
template <class W>
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const W& request)
: context_(context),
call_(channel->CreateCall(method, context, cq)),
collection_(std::make_shared<Ops>()) {
collection_->init_buf.SetCollection(collection_);
collection_->init_buf.SendInitialMetadata(
context->send_initial_metadata_, context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(collection_->init_buf.SendMessage(request).ok());
collection_->init_buf.ClientSendClose();
call_.PerformOps(&collection_->init_buf);
}
// always allocated against a call arena, no memory free required
static void operator delete(void* ptr, std::size_t size) {
assert(size == sizeof(ClientAsyncResponseReader));
@ -101,9 +123,18 @@ class ClientAsyncResponseReader final
void ReadInitialMetadata(void* tag) {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_buf_.set_output_tag(tag);
meta_buf_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_);
Ops& o = ops_;
// TODO(vjpai): Remove the collection_ specialization as soon
// as the public constructor is deleted
if (collection_) {
o = *collection_;
collection_->meta_buf.SetCollection(collection_);
}
o.meta_buf.set_output_tag(tag);
o.meta_buf.RecvInitialMetadata(context_);
call_.PerformOps(&o.meta_buf);
}
/// See \a ClientAysncResponseReaderInterface::Finish for semantics.
@ -112,14 +143,23 @@ class ClientAsyncResponseReader final
/// - the \a ClientContext associated with this call is updated with
/// possible initial and trailing metadata sent from the server.
void Finish(R* msg, Status* status, void* tag) {
finish_buf_.set_output_tag(tag);
Ops& o = ops_;
// TODO(vjpai): Remove the collection_ specialization as soon
// as the public constructor is deleted
if (collection_) {
o = *collection_;
collection_->finish_buf.SetCollection(collection_);
}
o.finish_buf.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_buf_.RecvInitialMetadata(context_);
o.finish_buf.RecvInitialMetadata(context_);
}
finish_buf_.RecvMessage(msg);
finish_buf_.AllowNoMessage();
finish_buf_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_);
o.finish_buf.RecvMessage(msg);
o.finish_buf.AllowNoMessage();
o.finish_buf.ClientRecvStatus(context_, status);
call_.PerformOps(&o.finish_buf);
}
private:
@ -129,25 +169,33 @@ class ClientAsyncResponseReader final
template <class W>
ClientAsyncResponseReader(Call call, ClientContext* context, const W& request)
: context_(context), call_(call) {
init_buf_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
ops_.init_buf.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_buf_.SendMessage(request).ok());
init_buf_.ClientSendClose();
call_.PerformOps(&init_buf_);
GPR_CODEGEN_ASSERT(ops_.init_buf.SendMessage(request).ok());
ops_.init_buf.ClientSendClose();
call_.PerformOps(&ops_.init_buf);
}
// disable operator new
static void* operator new(std::size_t size);
static void* operator new(std::size_t size, void* p) { return p; }
SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
init_buf_;
CallOpSet<CallOpRecvInitialMetadata> meta_buf_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
CallOpClientRecvStatus>
finish_buf_;
// TODO(vjpai): Remove the reference to CallOpSetCollectionInterface
// as soon as the related workaround (public constructor) is deleted
struct Ops : public CallOpSetCollectionInterface {
SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
init_buf;
CallOpSet<CallOpRecvInitialMetadata> meta_buf;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>,
CallOpClientRecvStatus>
finish_buf;
} ops_;
// TODO(vjpai): Remove the collection_ as soon as the related workaround
// (public constructor) is deleted
std::shared_ptr<Ops> collection_;
};
/// Async server-side API for handling unary calls, where the single

@ -544,6 +544,11 @@ class CallOpClientRecvStatus {
grpc_slice error_message_;
};
/// TODO(vjpai): Remove the existence of CallOpSetCollectionInterface
/// and references to it. This code is deprecated-on-arrival and is
/// only added for users that bypassed the code-generator.
class CallOpSetCollectionInterface {};
/// An abstract collection of call ops, used to generate the
/// grpc_call_op structure to pass down to the lower layers,
/// and as it is-a CompletionQueueTag, also massages the final
@ -554,6 +559,18 @@ class CallOpSetInterface : public CompletionQueueTag {
/// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards.
virtual void FillOps(grpc_call* call, grpc_op* ops, size_t* nops) = 0;
/// TODO(vjpai): Remove the SetCollection method and comment. This is only
/// a short-term workaround for users that bypassed the code generator
/// Mark this as belonging to a collection if needed
void SetCollection(std::shared_ptr<CallOpSetCollectionInterface> collection) {
collection_ = collection;
}
protected:
/// TODO(vjpai): Remove the collection_ field once the idea of bypassing the
/// code generator is forbidden. This is already deprecated
std::shared_ptr<CallOpSetCollectionInterface> collection_;
};
/// Primary implementaiton of CallOpSetInterface.
@ -593,6 +610,11 @@ class CallOpSet : public CallOpSetInterface,
this->Op5::FinishOp(status);
this->Op6::FinishOp(status);
*tag = return_tag_;
// TODO(vjpai): Remove the reference to collection_ once the idea of
// bypassing the code generator is forbidden. It is already deprecated
collection_.reset();
g_core_codegen_interface->grpc_call_unref(call_);
return true;
}

@ -52,14 +52,16 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
vars["input_type_id"] = MessageIdentifierName(input_type->full_name());
vars["output_type_id"] = MessageIdentifierName(output_type->full_name());
out->Print(GetPHPComments(method, " //").c_str());
out->Print("/**\n");
out->Print(GetPHPComments(method, " *").c_str());
if (method->client_streaming()) {
out->Print(vars,
" // @param array $$metadata metadata\n"
" // @param array $$options call options\n"
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
"public function $name$($$metadata = [], "
"$$options = []) {\n");
out->Indent();
out->Indent();
if (method->server_streaming()) {
out->Print("return $$this->_bidiRequest(");
} else {
@ -71,12 +73,13 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
"$$metadata, $$options);\n");
} else {
out->Print(vars,
" // @param \\$input_type_id$ $$argument input argument\n"
" // @param array $$metadata metadata\n"
" // @param array $$options call options\n"
" * @param \\$input_type_id$ $$argument input argument\n"
" * @param array $$metadata metadata\n"
" * @param array $$options call options\n */\n"
"public function $name$(\\$input_type_id$ $$argument,\n"
" $$metadata = [], $$options = []) {\n");
out->Indent();
out->Indent();
if (method->server_streaming()) {
out->Print("return $$this->_serverStreamRequest(");
} else {
@ -89,26 +92,32 @@ void PrintMethod(const MethodDescriptor *method, Printer *out) {
"$$metadata, $$options);\n");
}
out->Outdent();
out->Outdent();
out->Print("}\n\n");
}
// Prints out the service descriptor object
void PrintService(const ServiceDescriptor *service, Printer *out) {
map<grpc::string, grpc::string> vars;
out->Print(GetPHPComments(service, "//").c_str());
out->Print("/**\n");
out->Print(GetPHPComments(service, " *").c_str());
out->Print(" */\n");
vars["name"] = service->name();
out->Print(vars, "class $name$Client extends \\Grpc\\BaseStub {\n\n");
out->Indent();
out->Indent();
out->Print(
" // @param string $$hostname hostname\n"
" // @param array $$opts channel options\n"
" // @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n"
"/**\n * @param string $$hostname hostname\n"
" * @param array $$opts channel options\n"
" * @param \\Grpc\\Channel $$channel (optional) re-use channel "
"object\n */\n"
"public function __construct($$hostname, $$opts, "
"$$channel = null) {\n");
out->Indent();
out->Indent();
out->Print("parent::__construct($$hostname, $$opts, $$channel);\n");
out->Outdent();
out->Outdent();
out->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
grpc::string method_name =
@ -116,7 +125,8 @@ void PrintService(const ServiceDescriptor *service, Printer *out) {
PrintMethod(service->method(i), out);
}
out->Outdent();
out->Print("}\n\n");
out->Outdent();
out->Print("}\n");
}
}
@ -138,13 +148,9 @@ grpc::string GenerateFile(const FileDescriptor *file,
map<grpc::string, grpc::string> vars;
vars["package"] = MessageIdentifierName(file->package());
out.Print(vars, "namespace $package$ {\n\n");
out.Indent();
out.Print(vars, "namespace $package$;\n\n");
PrintService(service, &out);
out.Outdent();
out.Print("}\n");
}
return output;
}

@ -39,12 +39,24 @@ inline grpc::string GetPHPServiceFilename(
return oss.str() + "/" + service->name() + "Client.php";
}
// ReplaceAll replaces all instances of search with replace in s.
inline grpc::string ReplaceAll(grpc::string s, const grpc::string &search,
const grpc::string &replace) {
size_t pos = 0;
while ((pos = s.find(search, pos)) != grpc::string::npos) {
s.replace(pos, search.length(), replace);
pos += replace.length();
}
return s;
}
// Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments.
template <typename DescriptorType>
inline grpc::string GetPHPComments(const DescriptorType *desc,
grpc::string prefix) {
return grpc_generator::GetPrefixedComments(desc, true, prefix);
return ReplaceAll(grpc_generator::GetPrefixedComments(desc, true, prefix),
"*/", "&#42;/");
}
} // namespace grpc_php_generator

@ -95,6 +95,9 @@ static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
gpr_free(p->subchannels);
gpr_free(p->new_subchannels);
gpr_free(p);
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p destroyed.", (void *)p);
}
}
static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
@ -268,11 +271,20 @@ static void stop_connectivity_watchers(grpc_exec_ctx *exec_ctx,
pick_first_lb_policy *p) {
if (p->num_subchannels > 0) {
GPR_ASSERT(p->selected == NULL);
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unsubscribing from subchannel %p",
(void *)p, (void *)p->subchannels[p->checking_subchannel]);
}
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
&p->connectivity_changed);
p->updating_subchannels = true;
} else if (p->selected != NULL) {
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG,
"Pick First %p unsubscribing from selected subchannel %p",
(void *)p, (void *)p->selected);
}
grpc_connected_subchannel_notify_on_state_change(
exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
p->updating_selected = true;
@ -451,12 +463,25 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_subchannel *selected_subchannel;
pending_pick *pp;
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(
GPR_DEBUG,
"Pick First %p connectivity changed. Updating selected: %d; Updating "
"subchannels: %d; Checking %lu index (%lu total); State: %d; ",
(void *)p, p->updating_selected, p->updating_subchannels,
(unsigned long)p->checking_subchannel,
(unsigned long)p->num_subchannels, p->checking_connectivity);
}
bool restart = false;
if (p->updating_selected && error == GRPC_ERROR_CANCELLED) {
if (p->updating_selected && error != GRPC_ERROR_NONE) {
/* Captured the unsubscription for p->selected */
GPR_ASSERT(p->selected != NULL);
GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected,
"pf_update_connectivity");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unreffing selected subchannel %p",
(void *)p, (void *)p->selected);
}
p->updating_selected = false;
if (p->num_new_subchannels == 0) {
p->selected = NULL;
@ -464,12 +489,16 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
}
restart = true;
}
if (p->updating_subchannels && error == GRPC_ERROR_CANCELLED) {
if (p->updating_subchannels && error != GRPC_ERROR_NONE) {
/* Captured the unsubscription for the checking subchannel */
GPR_ASSERT(p->selected == NULL);
for (size_t i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i],
"pf_update_connectivity");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p unreffing subchannel %p", (void *)p,
(void *)p->subchannels[i]);
}
}
gpr_free(p->subchannels);
p->subchannels = NULL;
@ -481,14 +510,12 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
if (restart) {
p->selected = NULL;
p->selected_key = NULL;
GPR_ASSERT(p->new_subchannels != NULL);
GPR_ASSERT(p->num_new_subchannels > 0);
p->num_subchannels = p->num_new_subchannels;
p->subchannels = p->new_subchannels;
p->num_new_subchannels = 0;
p->new_subchannels = NULL;
if (p->started_picking) {
/* If we were picking, continue to do so over the new subchannels,
* starting from the 0th index. */
@ -542,7 +569,9 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
"picked_first");
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_INFO, "Selected subchannel %p", (void *)p->selected);
gpr_log(GPR_INFO,
"Pick First %p selected subchannel %p (connected %p)",
(void *)p, (void *)selected_subchannel, (void *)p->selected);
}
p->selected_key = grpc_subchannel_get_key(selected_subchannel);
/* drop the pick list: we are connected now */
@ -568,7 +597,8 @@ static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
p->checking_subchannel =
(p->checking_subchannel + 1) % p->num_subchannels;
if (p->checking_subchannel == 0) {
/* only trigger transient failure when we've tried all alternatives */
/* only trigger transient failure when we've tried all alternatives
*/
grpc_connectivity_state_set(
exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "connecting_transient_failure");
@ -652,6 +682,9 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->client_channel_factory != NULL);
pick_first_lb_policy *p = gpr_zalloc(sizeof(*p));
if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
gpr_log(GPR_DEBUG, "Pick First %p created.", (void *)p);
}
pf_update_locked(exec_ctx, &p->base, args);
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p,

@ -126,6 +126,8 @@ struct rr_subchannel_list {
size_t num_ready;
/** how many subchannels are in state TRANSIENT_FAILURE */
size_t num_transient_failures;
/** how many subchannels are in state SHUTDOWN */
size_t num_shutdown;
/** how many subchannels are in state IDLE */
size_t num_idle;
@ -425,6 +427,9 @@ static void update_state_counters_locked(subchannel_data *sd) {
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
GPR_ASSERT(subchannel_list->num_transient_failures > 0);
--subchannel_list->num_transient_failures;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
GPR_ASSERT(subchannel_list->num_shutdown > 0);
--subchannel_list->num_shutdown;
} else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
GPR_ASSERT(subchannel_list->num_idle > 0);
--subchannel_list->num_idle;
@ -433,6 +438,8 @@ static void update_state_counters_locked(subchannel_data *sd) {
++subchannel_list->num_ready;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
++subchannel_list->num_transient_failures;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
++subchannel_list->num_shutdown;
} else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
++subchannel_list->num_idle;
}
@ -455,7 +462,8 @@ static grpc_connectivity_state update_lb_connectivity_status_locked(
* CHECK: sd->curr_connectivity_state == CONNECTING.
*
* 3) RULE: ALL subchannels are SHUTDOWN => policy is SHUTDOWN.
* CHECK: p->subchannel_list->num_subchannels = 0.
* CHECK: p->subchannel_list->num_shutdown ==
* p->subchannel_list->num_subchannels.
*
* 4) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is
* TRANSIENT_FAILURE.
@ -464,37 +472,39 @@ static grpc_connectivity_state update_lb_connectivity_status_locked(
* 5) RULE: ALL subchannels are IDLE => policy is IDLE.
* CHECK: p->num_idle == p->subchannel_list->num_subchannels.
*/
grpc_connectivity_state new_state = sd->curr_connectivity_state;
rr_subchannel_list *subchannel_list = sd->subchannel_list;
round_robin_lb_policy *p = subchannel_list->policy;
if (subchannel_list->num_ready > 0) { /* 1) READY */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_READY,
GRPC_ERROR_NONE, "rr_ready");
return GRPC_CHANNEL_READY;
new_state = GRPC_CHANNEL_READY;
} else if (sd->curr_connectivity_state ==
GRPC_CHANNEL_CONNECTING) { /* 2) CONNECTING */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
"rr_connecting");
return GRPC_CHANNEL_CONNECTING;
} else if (p->subchannel_list->num_subchannels == 0) { /* 3) SHUTDOWN */
new_state = GRPC_CHANNEL_CONNECTING;
} else if (p->subchannel_list->num_shutdown ==
p->subchannel_list->num_subchannels) { /* 3) SHUTDOWN */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error),
"rr_shutdown");
return GRPC_CHANNEL_SHUTDOWN;
new_state = GRPC_CHANNEL_SHUTDOWN;
} else if (subchannel_list->num_transient_failures ==
p->subchannel_list->num_subchannels) { /* 4) TRANSIENT_FAILURE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
GRPC_ERROR_REF(error), "rr_transient_failure");
return GRPC_CHANNEL_TRANSIENT_FAILURE;
new_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
} else if (subchannel_list->num_idle ==
p->subchannel_list->num_subchannels) { /* 5) IDLE */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker, GRPC_CHANNEL_IDLE,
GRPC_ERROR_NONE, "rr_idle");
return GRPC_CHANNEL_IDLE;
new_state = GRPC_CHANNEL_IDLE;
}
/* no change */
return sd->curr_connectivity_state;
GRPC_ERROR_UNREF(error);
return new_state;
}
static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
@ -571,13 +581,15 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
GPR_ASSERT(sd->subchannel_list == p->latest_pending_subchannel_list);
GPR_ASSERT(!sd->subchannel_list->shutting_down);
if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) {
const unsigned long num_subchannels =
p->subchannel_list != NULL
? (unsigned long)p->subchannel_list->num_subchannels
: 0;
gpr_log(GPR_DEBUG,
"[RR %p] phasing out subchannel list %p (size %lu) in favor "
"of %p (size %lu)",
(void *)p, (void *)p->subchannel_list,
(unsigned long)p->subchannel_list->num_subchannels,
(void *)sd->subchannel_list,
(unsigned long)sd->subchannel_list->num_subchannels);
(void *)p, (void *)p->subchannel_list, num_subchannels,
(void *)sd->subchannel_list, num_subchannels);
}
if (p->subchannel_list != NULL) {
// dispose of the current subchannel_list

@ -19,8 +19,6 @@
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H
#include <ares.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset_set.h"

@ -19,6 +19,8 @@
#include "src/core/lib/iomgr/port.h"
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET)
#include <ares.h>
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
#include <grpc/support/alloc.h>

@ -56,6 +56,10 @@ typedef struct {
// grpc_resolver_next_locked()'s closure.
grpc_channel_args* next_results;
// Results to use for the pretended re-resolution in
// fake_resolver_channel_saw_error_locked().
grpc_channel_args* results_upon_error;
// pending next completion, or NULL
grpc_closure* next_completion;
// target result address for next completion
@ -65,6 +69,7 @@ typedef struct {
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr;
grpc_channel_args_destroy(exec_ctx, r->next_results);
grpc_channel_args_destroy(exec_ctx, r->results_upon_error);
grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r);
}
@ -87,15 +92,19 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
*r->target_result =
grpc_channel_args_union(r->next_results, r->channel_args);
grpc_channel_args_destroy(exec_ctx, r->next_results);
r->next_results = NULL;
GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL;
r->next_results = NULL;
}
}
static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx,
grpc_resolver* resolver) {
fake_resolver* r = (fake_resolver*)resolver;
if (r->next_results == NULL && r->results_upon_error != NULL) {
// Pretend we re-resolved.
r->next_results = grpc_channel_args_copy(r->results_upon_error);
}
fake_resolver_maybe_finish_next_locked(exec_ctx, r);
}
@ -151,6 +160,10 @@ static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg,
grpc_channel_args_destroy(exec_ctx, r->next_results);
}
r->next_results = generator->next_response;
if (r->results_upon_error != NULL) {
grpc_channel_args_destroy(exec_ctx, r->results_upon_error);
}
r->results_upon_error = grpc_channel_args_copy(generator->next_response);
fake_resolver_maybe_finish_next_locked(exec_ctx, r);
}

@ -255,6 +255,23 @@ static void continue_send_message(grpc_exec_ctx *exec_ctx,
}
}
static void handle_send_message_batch(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op_batch *op,
bool has_compression_algorithm) {
call_data *calld = elem->call_data;
if (!skip_compression(elem, op->payload->send_message.send_message->flags,
has_compression_algorithm)) {
calld->send_op = op;
calld->send_length = op->payload->send_message.send_message->length;
calld->send_flags = op->payload->send_message.send_message->flags;
continue_send_message(exec_ctx, elem);
} else {
/* pass control down the stack */
grpc_call_next_op(exec_ctx, elem, op);
}
}
static void compress_start_transport_stream_op_batch(
grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op_batch *op) {
@ -307,8 +324,9 @@ static void compress_start_transport_stream_op_batch(
goto retry_send_im;
}
if (cur != INITIAL_METADATA_UNSEEN) {
grpc_call_next_op(exec_ctx, elem,
(grpc_transport_stream_op_batch *)cur);
handle_send_message_batch(exec_ctx, elem,
(grpc_transport_stream_op_batch *)cur,
has_compression_algorithm);
}
}
}
@ -325,17 +343,8 @@ static void compress_start_transport_stream_op_batch(
break;
case HAS_COMPRESSION_ALGORITHM:
case NO_COMPRESSION_ALGORITHM:
if (!skip_compression(elem,
op->payload->send_message.send_message->flags,
cur == HAS_COMPRESSION_ALGORITHM)) {
calld->send_op = op;
calld->send_length = op->payload->send_message.send_message->length;
calld->send_flags = op->payload->send_message.send_message->flags;
continue_send_message(exec_ctx, elem);
} else {
/* pass control down the stack */
grpc_call_next_op(exec_ctx, elem, op);
}
handle_send_message_batch(exec_ctx, elem, op,
cur == HAS_COMPRESSION_ALGORITHM);
break;
default:
if (cur & CANCELLED_BIT) {

@ -52,7 +52,7 @@
#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
#define MAX_WINDOW 0x7fffffffu
#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
#define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
#define DEFAULT_MAX_HEADER_LIST_SIZE (8 * 1024)
#define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX
#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */
@ -1417,6 +1417,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
op_payload->recv_initial_metadata.recv_initial_metadata_ready;
s->recv_initial_metadata =
op_payload->recv_initial_metadata.recv_initial_metadata;
s->trailing_metadata_available =
op_payload->recv_initial_metadata.trailing_metadata_available;
grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
}

@ -93,7 +93,7 @@ grpc_error *grpc_chttp2_rst_stream_parser_parse(grpc_exec_ctx *exec_ctx,
(((uint32_t)p->reason_bytes[2]) << 8) |
(((uint32_t)p->reason_bytes[3]));
grpc_error *error = GRPC_ERROR_NONE;
if (reason != GRPC_HTTP2_NO_ERROR || s->header_frames_received < 2) {
if (reason != GRPC_HTTP2_NO_ERROR || s->metadata_buffer[1].size == 0) {
char *message;
gpr_asprintf(&message, "Received RST_STREAM with error code %d", reason);
error = grpc_error_set_int(

@ -608,15 +608,14 @@ void grpc_chttp2_hpack_compressor_set_max_table_size(
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
grpc_mdelem **extra_headers,
size_t extra_headers_size,
grpc_metadata_batch *metadata,
const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf) {
framer_state st;
grpc_linked_mdelem *l;
gpr_timespec deadline;
GPR_ASSERT(options->stream_id != 0);
framer_state st;
st.seen_regular_header = 0;
st.stream_id = options->stream_id;
st.output = outbuf;
@ -633,11 +632,14 @@ void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
if (c->advertise_table_size_change != 0) {
emit_advertise_table_size_change(c, &st);
}
for (size_t i = 0; i < extra_headers_size; ++i) {
hpack_enc(exec_ctx, c, *extra_headers[i], &st);
}
grpc_metadata_batch_assert_ok(metadata);
for (l = metadata->list.head; l; l = l->next) {
for (grpc_linked_mdelem *l = metadata->list.head; l; l = l->next) {
hpack_enc(exec_ctx, c, l->md, &st);
}
deadline = metadata->deadline;
gpr_timespec deadline = metadata->deadline;
if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) != 0) {
deadline_enc(exec_ctx, c, deadline, &st);
}

@ -85,6 +85,8 @@ typedef struct {
void grpc_chttp2_encode_header(grpc_exec_ctx *exec_ctx,
grpc_chttp2_hpack_compressor *c,
grpc_mdelem **extra_headers,
size_t extra_headers_size,
grpc_metadata_batch *metadata,
const grpc_encode_header_options *options,
grpc_slice_buffer *outbuf);

@ -447,6 +447,7 @@ struct grpc_chttp2_stream {
grpc_metadata_batch *recv_initial_metadata;
grpc_closure *recv_initial_metadata_ready;
bool *trailing_metadata_available;
grpc_byte_stream **recv_message;
grpc_closure *recv_message_ready;
grpc_metadata_batch *recv_trailing_metadata;

@ -681,9 +681,19 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
t->parser_data = &t->hpack_parser;
switch (s->header_frames_received) {
case 0:
t->hpack_parser.on_header = on_initial_header;
if (t->is_client && t->header_eof) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing Trailers-Only"));
if (s->trailing_metadata_available != NULL) {
*s->trailing_metadata_available = true;
}
t->hpack_parser.on_header = on_trailing_header;
} else {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
t->hpack_parser.on_header = on_initial_header;
}
break;
case 1:
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
t->hpack_parser.on_header = on_trailing_header;
break;
case 2:

@ -162,6 +162,20 @@ static uint32_t target_write_size(grpc_chttp2_transport *t) {
return 1024 * 1024;
}
// Returns true if initial_metadata contains only default headers.
//
// TODO(roth): The fact that we hard-code these particular headers here
// is fairly ugly. Need some better way to know which headers are
// default, maybe via a bit in the static metadata table?
static bool is_default_initial_metadata(grpc_metadata_batch *initial_metadata) {
int num_default_fields =
(initial_metadata->idx.named.status != NULL) +
(initial_metadata->idx.named.content_type != NULL) +
(initial_metadata->idx.named.grpc_encoding != NULL) +
(initial_metadata->idx.named.grpc_accept_encoding != NULL);
return (size_t)num_default_fields == initial_metadata->list.count;
}
grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
grpc_chttp2_stream *s;
@ -218,31 +232,59 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
t->is_client ? "CLIENT" : "SERVER", s->id, sent_initial_metadata,
s->send_initial_metadata != NULL, s->announce_window));
grpc_mdelem *extra_headers_for_trailing_metadata[2];
size_t num_extra_headers_for_trailing_metadata = 0;
/* send initial metadata if it's available */
if (!sent_initial_metadata && s->send_initial_metadata) {
grpc_encode_header_options hopt = {
.stream_id = s->id,
.is_eof = false,
.use_true_binary_metadata =
t->settings
[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0,
.max_frame_size = t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
.stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
s->send_initial_metadata, &hopt, &t->outbuf);
if (!sent_initial_metadata && s->send_initial_metadata != NULL) {
// We skip this on the server side if there is no custom initial
// metadata, there are no messages to send, and we are also sending
// trailing metadata. This results in a Trailers-Only response,
// which is required for retries, as per:
// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid
if (t->is_client || s->fetching_send_message != NULL ||
s->flow_controlled_buffer.length != 0 ||
s->send_trailing_metadata == NULL ||
!is_default_initial_metadata(s->send_initial_metadata)) {
grpc_encode_header_options hopt = {
.stream_id = s->id,
.is_eof = false,
.use_true_binary_metadata =
t->settings
[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA] != 0,
.max_frame_size = t->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
.stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0,
s->send_initial_metadata, &hopt, &t->outbuf);
now_writing = true;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC);
t->ping_recv_state.ping_strikes = 0;
}
} else {
GRPC_CHTTP2_IF_TRACING(
gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
// When sending Trailers-Only, we need to move the :status and
// content-type headers to the trailers.
if (s->send_initial_metadata->idx.named.status != NULL) {
extra_headers_for_trailing_metadata
[num_extra_headers_for_trailing_metadata++] =
&s->send_initial_metadata->idx.named.status->md;
}
if (s->send_initial_metadata->idx.named.content_type != NULL) {
extra_headers_for_trailing_metadata
[num_extra_headers_for_trailing_metadata++] =
&s->send_initial_metadata->idx.named.content_type->md;
}
}
s->send_initial_metadata = NULL;
s->sent_initial_metadata = true;
sent_initial_metadata = true;
now_writing = true;
t->ping_state.pings_before_data_required =
t->ping_policy.max_pings_without_data;
if (!t->is_client) {
t->ping_recv_state.last_ping_recv_time =
gpr_inf_past(GPR_CLOCK_MONOTONIC);
t->ping_recv_state.ping_strikes = 0;
}
}
/* send any window updates */
if (s->announce_window > 0) {
@ -320,6 +362,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
if (s->send_trailing_metadata != NULL &&
s->fetching_send_message == NULL &&
s->flow_controlled_buffer.length == 0) {
GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
&s->stats.outgoing, &t->outbuf);
@ -337,6 +380,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
[GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE],
.stats = &s->stats.outgoing};
grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor,
extra_headers_for_trailing_metadata,
num_extra_headers_for_trailing_metadata,
s->send_trailing_metadata, &hopt,
&t->outbuf);
}

@ -766,20 +766,50 @@ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op,
bool is_canceled_or_failed = stream_state->state_op_done[OP_CANCEL_ERROR] ||
stream_state->state_callback_received[OP_FAILED];
if (is_canceled_or_failed) {
if (op_id == OP_SEND_INITIAL_METADATA) result = false;
if (op_id == OP_SEND_MESSAGE) result = false;
if (op_id == OP_SEND_TRAILING_METADATA) result = false;
if (op_id == OP_CANCEL_ERROR) result = false;
if (op_id == OP_SEND_INITIAL_METADATA) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_SEND_MESSAGE) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_SEND_TRAILING_METADATA) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_CANCEL_ERROR) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
/* already executed */
if (op_id == OP_RECV_INITIAL_METADATA &&
stream_state->state_op_done[OP_RECV_INITIAL_METADATA])
stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
if (op_id == OP_RECV_MESSAGE &&
stream_state->state_op_done[OP_RECV_MESSAGE])
}
if (op_id == OP_RECV_MESSAGE && op_state->state_op_done[OP_RECV_MESSAGE]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
if (op_id == OP_RECV_TRAILING_METADATA &&
stream_state->state_op_done[OP_RECV_TRAILING_METADATA])
stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
/* ON_COMPLETE can be processed if one of the following conditions is met:
* 1. the stream failed
* 2. the stream is cancelled, and the callback is received
* 3. the stream succeeded before cancel is effective
* 4. the stream is cancelled, and the stream is never started */
if (op_id == OP_ON_COMPLETE &&
!(stream_state->state_callback_received[OP_FAILED] ||
stream_state->state_callback_received[OP_CANCELED] ||
stream_state->state_callback_received[OP_SUCCEEDED] ||
!stream_state->state_op_done[OP_SEND_INITIAL_METADATA])) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
}
} else if (op_id == OP_SEND_INITIAL_METADATA) {
/* already executed */
if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false;
@ -868,7 +898,7 @@ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op,
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
} else if (curr_op->recv_message &&
!stream_state->state_op_done[OP_RECV_MESSAGE]) {
!op_state->state_op_done[OP_RECV_MESSAGE]) {
CRONET_LOG(GPR_DEBUG, "Because");
result = false;
} else if (curr_op->cancel_stream &&
@ -1067,6 +1097,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_state->state_callback_received[OP_FAILED]) {
CRONET_LOG(GPR_DEBUG, "Stream failed.");
@ -1074,6 +1105,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
stream_op->payload->recv_message.recv_message_ready,
GRPC_ERROR_NONE);
stream_state->state_op_done[OP_RECV_MESSAGE] = true;
oas->state.state_op_done[OP_RECV_MESSAGE] = true;
result = ACTION_TAKEN_NO_CALLBACK;
} else if (stream_state->rs.read_stream_closed == true) {
/* No more data will be received */
@ -1214,8 +1246,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
} else if (stream_op->cancel_stream &&
op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) {
CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) {
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs);
bidirectional_stream_cancel(s->cbs);
result = ACTION_TAKEN_WITH_CALLBACK;
} else {

@ -25,6 +25,7 @@
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/security/transport/security_handshaker.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/string.h"
@ -157,7 +158,6 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint)) {
grpc_channel_security_connector *sc = NULL;
on_done_closure *c = gpr_malloc(sizeof(*c));
const char *pem_root_certs = grpc_get_default_ssl_roots();
if (pem_root_certs == NULL) {
@ -168,11 +168,13 @@ static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
}
c->func = on_done;
c->arg = arg;
c->handshake_mgr = grpc_handshake_manager_create();
grpc_channel_security_connector *sc = NULL;
GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
exec_ctx, pem_root_certs, host, &sc) == GRPC_SECURITY_OK);
grpc_channel_security_connector_add_handshakers(exec_ctx, sc,
c->handshake_mgr);
grpc_arg channel_arg = grpc_security_connector_to_arg(&sc->base);
grpc_channel_args args = {1, &channel_arg};
c->handshake_mgr = grpc_handshake_manager_create();
grpc_handshakers_add(exec_ctx, HANDSHAKER_CLIENT, &args, c->handshake_mgr);
grpc_handshake_manager_do_handshake(
exec_ctx, c->handshake_mgr, tcp, NULL /* channel_args */, deadline,
NULL /* acceptor */, on_handshake_done, c /* user_data */);

@ -26,6 +26,10 @@
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/support/mpscq.h"
#ifdef __cplusplus
extern "C" {
#endif
struct grpc_closure;
typedef struct grpc_closure grpc_closure;
@ -42,7 +46,9 @@ typedef struct grpc_closure_list {
*
* \param arg Arbitrary input.
* \param error GRPC_ERROR_NONE if no error occurred, otherwise some grpc_error
* describing what went wrong */
* describing what went wrong.
* Error contract: it is not the cb's job to unref this error;
* the closure scheduler will do that after the cb returns */
typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error);
@ -195,4 +201,8 @@ void grpc_closure_list_sched(grpc_exec_ctx *exec_ctx,
grpc_closure_list_sched(exec_ctx, closure_list)
#endif
#ifdef __cplusplus
}
#endif
#endif /* GRPC_CORE_LIB_IOMGR_CLOSURE_H */

@ -840,11 +840,6 @@ static grpc_fd *fd_create(int fd, const char *name) {
char *fd_name;
gpr_asprintf(&fd_name, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name);
#ifndef NDEBUG
if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, new_fd, fd_name);
}
#endif
gpr_free(fd_name);
return new_fd;
}

@ -323,11 +323,6 @@ static grpc_fd *fd_create(int fd, const char *name) {
gpr_asprintf(&name2, "%s fd=%d", name, fd);
grpc_iomgr_register_object(&r->iomgr_object, name2);
gpr_free(name2);
#ifndef NDEBUG
if (GRPC_TRACER_ON(grpc_trace_fd_refcount)) {
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name);
}
#endif
return r;
}

@ -31,7 +31,7 @@ static void gpr_get_cycle_counter(int64_t int *clk) {
// ----------------------------------------------------------------
#elif defined(__x86_64__) || defined(__amd64__)
static void gpr_get_cycle_counter(int64_t *clk) {
unsigned int64_t low, high;
uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
*clk = (int64_t)(high << 32) | (int64_t)low;
}

@ -929,33 +929,6 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
return algorithm;
}
static void recv_common_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch *b) {
if (b->idx.named.grpc_status != NULL) {
uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
grpc_error *error =
status_code == GRPC_STATUS_OK
? GRPC_ERROR_NONE
: grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS,
(intptr_t)status_code);
if (b->idx.named.grpc_message != NULL) {
error = grpc_error_set_str(
error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
} else if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_empty_slice());
}
set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
}
}
static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
int is_trailing) {
if (b->list.count == 0) return;
@ -980,8 +953,6 @@ static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch *b) {
recv_common_filter(exec_ctx, call, b);
if (b->idx.named.grpc_encoding != NULL) {
GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
set_incoming_compression_algorithm(
@ -989,7 +960,6 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
GPR_TIMER_END("incoming_compression_algorithm", 0);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
}
if (b->idx.named.grpc_accept_encoding != NULL) {
GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
set_encodings_accepted_by_peer(exec_ctx, call,
@ -997,14 +967,33 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
GPR_TIMER_END("encodings_accepted_by_peer", 0);
}
publish_app_metadata(call, b, false);
}
static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
grpc_metadata_batch *b) {
grpc_call *call = args;
recv_common_filter(exec_ctx, call, b);
if (b->idx.named.grpc_status != NULL) {
uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
grpc_error *error =
status_code == GRPC_STATUS_OK
? GRPC_ERROR_NONE
: grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Error received from peer"),
GRPC_ERROR_INT_GRPC_STATUS,
(intptr_t)status_code);
if (b->idx.named.grpc_message != NULL) {
error = grpc_error_set_str(
error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
} else if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
grpc_empty_slice());
}
set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
}
publish_app_metadata(call, b, true);
}

@ -475,6 +475,7 @@ static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
*rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) {
*rc->data.registered.optional_payload = calld->payload;
calld->payload = NULL;
}
break;
default:
@ -878,6 +879,7 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_slice_unref_internal(exec_ctx, calld->path);
}
grpc_metadata_array_destroy(&calld->initial_metadata);
grpc_byte_buffer_destroy(calld->payload);
gpr_mu_destroy(&calld->mu_state);

@ -206,6 +206,11 @@ grpc_endpoint *grpc_transport_get_endpoint(grpc_exec_ctx *exec_ctx,
return transport->vtable->get_endpoint(exec_ctx, transport);
}
// grpc_transport_stream_op_batch_finish_with_failure
// is a function that must always unref cancel_error
// though it lives in lib, it handles transport stream ops sure
// it's grpc_transport_stream_op_batch_finish_with_failure
void grpc_transport_stream_op_batch_finish_with_failure(
grpc_exec_ctx *exec_ctx, grpc_transport_stream_op_batch *op,
grpc_error *error) {

@ -167,6 +167,10 @@ struct grpc_transport_stream_op_batch_payload {
uint32_t *recv_flags;
/** Should be enqueued when initial metadata is ready to be processed. */
grpc_closure *recv_initial_metadata_ready;
// If not NULL, will be set to true if trailing metadata is
// immediately available. This may be a signal that we received a
// Trailers-Only response.
bool *trailing_metadata_available;
} recv_initial_metadata;
struct {
@ -194,6 +198,8 @@ struct grpc_transport_stream_op_batch_payload {
grpc_chttp2_grpc_status_to_http2_error. Send a RST_STREAM with this
error. */
struct {
// Error contract: the transport that gets this op must cause cancel_error
// to be unref'ed after processing it
grpc_error *cancel_error;
} cancel_stream;
@ -208,9 +214,13 @@ typedef struct grpc_transport_op {
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
grpc_closure *on_connectivity_state_change;
grpc_connectivity_state *connectivity_state;
/** should the transport be disconnected */
/** should the transport be disconnected
* Error contract: the transport that gets this op must cause
* disconnect_with_error to be unref'ed after processing it */
grpc_error *disconnect_with_error;
/** what should the goaway contain? */
/** what should the goaway contain?
* Error contract: the transport that gets this op must cause
* goaway_error to be unref'ed after processing it */
grpc_error *goaway_error;
/** set the callback for accepting new streams;
this is a permanent callback, unlike the other one-shot closures.

@ -208,38 +208,45 @@ class TransportStreamOpBatch {
/// Represents channel data.
class ChannelData {
public:
ChannelData() {}
virtual ~ChannelData() {}
/// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx,
// TODO(roth): Come up with a more C++-like API for the channel element.
/// Initializes the channel data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) {
return GRPC_ERROR_NONE;
}
// TODO(roth): Find a way to avoid passing elem into these methods.
// Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
virtual void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, TransportOp *op);
virtual void GetInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info);
protected:
ChannelData() {}
};
/// Represents call data.
class CallData {
public:
CallData() {}
virtual ~CallData() {}
// TODO(roth): Come up with a more C++-like API for the call element.
/// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data,
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_element_args *args) {
return GRPC_ERROR_NONE;
}
// TODO(roth): Find a way to avoid passing elem into these methods.
// Called before destruction.
virtual void Destroy(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) {}
/// Starts a new stream operation.
virtual void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
@ -253,9 +260,6 @@ class CallData {
/// Gets the peer name.
virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
protected:
CallData() {}
};
namespace internal {
@ -271,19 +275,24 @@ class ChannelFilter final {
static grpc_error *InitChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_channel_element_args *args) {
// Construct the object in the already-allocated memory.
ChannelDataType *channel_data = new (elem->channel_data) ChannelDataType();
return channel_data->Init(exec_ctx, args);
return channel_data->Init(exec_ctx, elem, args);
}
static void DestroyChannelElement(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType();
ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->Destroy(exec_ctx, elem);
channel_data->~ChannelDataType();
}
static void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
TransportOp op_wrapper(op);
channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper);
}
@ -291,7 +300,8 @@ class ChannelFilter final {
static void GetChannelInfo(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
const grpc_channel_info *channel_info) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
ChannelDataType *channel_data =
reinterpret_cast<ChannelDataType *>(elem->channel_data);
channel_data->GetInfo(exec_ctx, elem, channel_info);
}
@ -300,24 +310,24 @@ class ChannelFilter final {
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
// Construct the object in the already-allocated memory.
CallDataType *call_data = new (elem->call_data) CallDataType();
return call_data->Init(exec_ctx, channel_data, args);
return call_data->Init(exec_ctx, elem, args);
}
static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
grpc_closure *then_call_closure) {
GPR_ASSERT(then_call_closure == NULL);
reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType();
CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
call_data->Destroy(exec_ctx, elem, final_info, then_call_closure);
call_data->~CallDataType();
}
static void StartTransportStreamOpBatch(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op_batch *op) {
CallDataType *call_data = (CallDataType *)elem->call_data;
CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
TransportStreamOpBatch op_wrapper(op);
call_data->StartTransportStreamOpBatch(exec_ctx, elem, &op_wrapper);
}
@ -325,12 +335,12 @@ class ChannelFilter final {
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_polling_entity *pollent) {
CallDataType *call_data = (CallDataType *)elem->call_data;
CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent);
}
static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
CallDataType *call_data = (CallDataType *)elem->call_data;
CallDataType *call_data = reinterpret_cast<CallDataType *>(elem->call_data);
return call_data->GetPeer(exec_ctx, elem);
}
};

@ -32,7 +32,7 @@ namespace Grpc.Testing {
"U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
"X2hvc3Rfb3ZlcnJpZGUYAiABKAkiTQoKQ2hhbm5lbEFyZxIMCgRuYW1lGAEg",
"ASgJEhMKCXN0cl92YWx1ZRgCIAEoCUgAEhMKCWludF92YWx1ZRgDIAEoBUgA",
"QgcKBXZhbHVlIqAECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY",
"QgcKBXZhbHVlItUECgxDbGllbnRDb25maWcSFgoOc2VydmVyX3RhcmdldHMY",
"ASADKAkSLQoLY2xpZW50X3R5cGUYAiABKA4yGC5ncnBjLnRlc3RpbmcuQ2xp",
"ZW50VHlwZRI1Cg9zZWN1cml0eV9wYXJhbXMYAyABKAsyHC5ncnBjLnRlc3Rp",
"bmcuU2VjdXJpdHlQYXJhbXMSJAocb3V0c3RhbmRpbmdfcnBjc19wZXJfY2hh",
@ -44,52 +44,57 @@ namespace Grpc.Testing {
"cxgMIAEoCzIdLmdycGMudGVzdGluZy5IaXN0b2dyYW1QYXJhbXMSEQoJY29y",
"ZV9saXN0GA0gAygFEhIKCmNvcmVfbGltaXQYDiABKAUSGAoQb3RoZXJfY2xp",
"ZW50X2FwaRgPIAEoCRIuCgxjaGFubmVsX2FyZ3MYECADKAsyGC5ncnBjLnRl",
"c3RpbmcuQ2hhbm5lbEFyZyI4CgxDbGllbnRTdGF0dXMSKAoFc3RhdHMYASAB",
"KAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMiFQoETWFyaxINCgVyZXNl",
"dBgBIAEoCCJoCgpDbGllbnRBcmdzEisKBXNldHVwGAEgASgLMhouZ3JwYy50",
"ZXN0aW5nLkNsaWVudENvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBjLnRl",
"c3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUitAIKDFNlcnZlckNvbmZpZxItCgtz",
"ZXJ2ZXJfdHlwZRgBIAEoDjIYLmdycGMudGVzdGluZy5TZXJ2ZXJUeXBlEjUK",
"D3NlY3VyaXR5X3BhcmFtcxgCIAEoCzIcLmdycGMudGVzdGluZy5TZWN1cml0",
"eVBhcmFtcxIMCgRwb3J0GAQgASgFEhwKFGFzeW5jX3NlcnZlcl90aHJlYWRz",
"GAcgASgFEhIKCmNvcmVfbGltaXQYCCABKAUSMwoOcGF5bG9hZF9jb25maWcY",
"CSABKAsyGy5ncnBjLnRlc3RpbmcuUGF5bG9hZENvbmZpZxIRCgljb3JlX2xp",
"c3QYCiADKAUSGAoQb3RoZXJfc2VydmVyX2FwaRgLIAEoCRIcChNyZXNvdXJj",
"ZV9xdW90YV9zaXplGOkHIAEoBSJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEg",
"ASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiAB",
"KAsyEi5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVy",
"U3RhdHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0",
"YXRzEgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVl",
"c3QiHQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEK",
"CFNjZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEo",
"CzIaLmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMY",
"AyABKAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5T",
"ZXJ2ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3Nl",
"Y29uZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bh",
"d25fbG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglz",
"Y2VuYXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8i+AIKFVNj",
"ZW5hcmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9z",
"ZXJ2ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAES",
"GAoQc2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3Rp",
"bWUYBSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5",
"XzUwGAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJ",
"IAEoARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgB",
"EhgKEHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1",
"ZXN0c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJf",
"c2Vjb25kGA4gASgBIoMDCg5TY2VuYXJpb1Jlc3VsdBIoCghzY2VuYXJpbxgB",
"IAEoCzIWLmdycGMudGVzdGluZy5TY2VuYXJpbxIuCglsYXRlbmNpZXMYAiAB",
"KAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIvCgxjbGllbnRfc3Rh",
"dHMYAyADKAsyGS5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHMSLwoMc2VydmVy",
"X3N0YXRzGAQgAygLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEhQKDHNl",
"cnZlcl9jb3JlcxgFIAMoBRI0CgdzdW1tYXJ5GAYgASgLMiMuZ3JwYy50ZXN0",
"aW5nLlNjZW5hcmlvUmVzdWx0U3VtbWFyeRIWCg5jbGllbnRfc3VjY2VzcxgH",
"IAMoCBIWCg5zZXJ2ZXJfc3VjY2VzcxgIIAMoCBI5Cg9yZXF1ZXN0X3Jlc3Vs",
"dHMYCSADKAsyIC5ncnBjLnRlc3RpbmcuUmVxdWVzdFJlc3VsdENvdW50KkEK",
"CkNsaWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQ",
"ARIQCgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VS",
"VkVSEAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJW",
"RVIQAhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAAS",
"DQoJU1RSRUFNSU5HEAFiBnByb3RvMw=="));
"c3RpbmcuQ2hhbm5lbEFyZxIWCg50aHJlYWRzX3Blcl9jcRgRIAEoBRIbChNt",
"ZXNzYWdlc19wZXJfc3RyZWFtGBIgASgFIjgKDENsaWVudFN0YXR1cxIoCgVz",
"dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
"Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
"Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
"LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSLMAgoMU2VydmVyQ29u",
"ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
"clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
"LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
"X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
"X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
"CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhYK",
"DnRocmVhZHNfcGVyX2NxGAwgASgFEhwKE3Jlc291cmNlX3F1b3RhX3NpemUY",
"6QcgASgFImgKClNlcnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRl",
"c3RpbmcuU2VydmVyQ29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVz",
"dGluZy5NYXJrSABCCQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3Rh",
"dHMYASABKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgC",
"IAEoBRINCgVjb3JlcxgDIAEoBSINCgtDb3JlUmVxdWVzdCIdCgxDb3JlUmVz",
"cG9uc2USDQoFY29yZXMYASABKAUiBgoEVm9pZCL9AQoIU2NlbmFyaW8SDAoE",
"bmFtZRgBIAEoCRIxCg1jbGllbnRfY29uZmlnGAIgASgLMhouZ3JwYy50ZXN0",
"aW5nLkNsaWVudENvbmZpZxITCgtudW1fY2xpZW50cxgDIAEoBRIxCg1zZXJ2",
"ZXJfY29uZmlnGAQgASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZxIT",
"CgtudW1fc2VydmVycxgFIAEoBRIWCg53YXJtdXBfc2Vjb25kcxgGIAEoBRIZ",
"ChFiZW5jaG1hcmtfc2Vjb25kcxgHIAEoBRIgChhzcGF3bl9sb2NhbF93b3Jr",
"ZXJfY291bnQYCCABKAUiNgoJU2NlbmFyaW9zEikKCXNjZW5hcmlvcxgBIAMo",
"CzIWLmdycGMudGVzdGluZy5TY2VuYXJpbyK8AwoVU2NlbmFyaW9SZXN1bHRT",
"dW1tYXJ5EgsKA3FwcxgBIAEoARIbChNxcHNfcGVyX3NlcnZlcl9jb3JlGAIg",
"ASgBEhoKEnNlcnZlcl9zeXN0ZW1fdGltZRgDIAEoARIYChBzZXJ2ZXJfdXNl",
"cl90aW1lGAQgASgBEhoKEmNsaWVudF9zeXN0ZW1fdGltZRgFIAEoARIYChBj",
"bGllbnRfdXNlcl90aW1lGAYgASgBEhIKCmxhdGVuY3lfNTAYByABKAESEgoK",
"bGF0ZW5jeV85MBgIIAEoARISCgpsYXRlbmN5Xzk1GAkgASgBEhIKCmxhdGVu",
"Y3lfOTkYCiABKAESEwoLbGF0ZW5jeV85OTkYCyABKAESGAoQc2VydmVyX2Nw",
"dV91c2FnZRgMIAEoARImCh5zdWNjZXNzZnVsX3JlcXVlc3RzX3Blcl9zZWNv",
"bmQYDSABKAESIgoaZmFpbGVkX3JlcXVlc3RzX3Blcl9zZWNvbmQYDiABKAES",
"IAoYY2xpZW50X3BvbGxzX3Blcl9yZXF1ZXN0GA8gASgBEiAKGHNlcnZlcl9w",
"b2xsc19wZXJfcmVxdWVzdBgQIAEoASKDAwoOU2NlbmFyaW9SZXN1bHQSKAoI",
"c2NlbmFyaW8YASABKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8SLgoJbGF0",
"ZW5jaWVzGAIgASgLMhsuZ3JwYy50ZXN0aW5nLkhpc3RvZ3JhbURhdGESLwoM",
"Y2xpZW50X3N0YXRzGAMgAygLMhkuZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXRz",
"Ei8KDHNlcnZlcl9zdGF0cxgEIAMoCzIZLmdycGMudGVzdGluZy5TZXJ2ZXJT",
"dGF0cxIUCgxzZXJ2ZXJfY29yZXMYBSADKAUSNAoHc3VtbWFyeRgGIAEoCzIj",
"LmdycGMudGVzdGluZy5TY2VuYXJpb1Jlc3VsdFN1bW1hcnkSFgoOY2xpZW50",
"X3N1Y2Nlc3MYByADKAgSFgoOc2VydmVyX3N1Y2Nlc3MYCCADKAgSOQoPcmVx",
"dWVzdF9yZXN1bHRzGAkgAygLMiAuZ3JwYy50ZXN0aW5nLlJlcXVlc3RSZXN1",
"bHRDb3VudCpBCgpDbGllbnRUeXBlEg8KC1NZTkNfQ0xJRU5UEAASEAoMQVNZ",
"TkNfQ0xJRU5UEAESEAoMT1RIRVJfQ0xJRU5UEAIqWwoKU2VydmVyVHlwZRIP",
"CgtTWU5DX1NFUlZFUhAAEhAKDEFTWU5DX1NFUlZFUhABEhgKFEFTWU5DX0dF",
"TkVSSUNfU0VSVkVSEAISEAoMT1RIRVJfU0VSVkVSEAMqcgoHUnBjVHlwZRIJ",
"CgVVTkFSWRAAEg0KCVNUUkVBTUlORxABEhkKFVNUUkVBTUlOR19GUk9NX0NM",
"SUVOVBACEhkKFVNUUkVBTUlOR19GUk9NX1NFUlZFUhADEhcKE1NUUkVBTUlO",
"R19CT1RIX1dBWVMQBGIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
@ -98,11 +103,11 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ResourceQuotaSize" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ThreadsPerCq", "ResourceQuotaSize" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
@ -110,7 +115,7 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond", "ClientPollsPerRequest", "ServerPollsPerRequest" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null)
}));
}
@ -144,6 +149,9 @@ namespace Grpc.Testing {
public enum RpcType {
[pbr::OriginalName("UNARY")] Unary = 0,
[pbr::OriginalName("STREAMING")] Streaming = 1,
[pbr::OriginalName("STREAMING_FROM_CLIENT")] StreamingFromClient = 2,
[pbr::OriginalName("STREAMING_FROM_SERVER")] StreamingFromServer = 3,
[pbr::OriginalName("STREAMING_BOTH_WAYS")] StreamingBothWays = 4,
}
#endregion
@ -942,6 +950,8 @@ namespace Grpc.Testing {
coreLimit_ = other.coreLimit_;
otherClientApi_ = other.otherClientApi_;
channelArgs_ = other.channelArgs_.Clone();
threadsPerCq_ = other.threadsPerCq_;
messagesPerStream_ = other.messagesPerStream_;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1123,6 +1133,34 @@ namespace Grpc.Testing {
get { return channelArgs_; }
}
/// <summary>Field number for the "threads_per_cq" field.</summary>
public const int ThreadsPerCqFieldNumber = 17;
private int threadsPerCq_;
/// <summary>
/// Number of threads that share each completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ThreadsPerCq {
get { return threadsPerCq_; }
set {
threadsPerCq_ = value;
}
}
/// <summary>Field number for the "messages_per_stream" field.</summary>
public const int MessagesPerStreamFieldNumber = 18;
private int messagesPerStream_;
/// <summary>
/// Number of messages on a stream before it gets finished/restarted
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int MessagesPerStream {
get { return messagesPerStream_; }
set {
messagesPerStream_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ClientConfig);
@ -1150,6 +1188,8 @@ namespace Grpc.Testing {
if (CoreLimit != other.CoreLimit) return false;
if (OtherClientApi != other.OtherClientApi) return false;
if(!channelArgs_.Equals(other.channelArgs_)) return false;
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (MessagesPerStream != other.MessagesPerStream) return false;
return true;
}
@ -1170,6 +1210,8 @@ namespace Grpc.Testing {
if (CoreLimit != 0) hash ^= CoreLimit.GetHashCode();
if (OtherClientApi.Length != 0) hash ^= OtherClientApi.GetHashCode();
hash ^= channelArgs_.GetHashCode();
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
return hash;
}
@ -1227,6 +1269,14 @@ namespace Grpc.Testing {
output.WriteString(OtherClientApi);
}
channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
if (ThreadsPerCq != 0) {
output.WriteRawTag(136, 1);
output.WriteInt32(ThreadsPerCq);
}
if (MessagesPerStream != 0) {
output.WriteRawTag(144, 1);
output.WriteInt32(MessagesPerStream);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1268,6 +1318,12 @@ namespace Grpc.Testing {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherClientApi);
}
size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
if (ThreadsPerCq != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
}
if (MessagesPerStream != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(MessagesPerStream);
}
return size;
}
@ -1324,6 +1380,12 @@ namespace Grpc.Testing {
OtherClientApi = other.OtherClientApi;
}
channelArgs_.Add(other.channelArgs_);
if (other.ThreadsPerCq != 0) {
ThreadsPerCq = other.ThreadsPerCq;
}
if (other.MessagesPerStream != 0) {
MessagesPerStream = other.MessagesPerStream;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1403,6 +1465,14 @@ namespace Grpc.Testing {
channelArgs_.AddEntriesFrom(input, _repeated_channelArgs_codec);
break;
}
case 136: {
ThreadsPerCq = input.ReadInt32();
break;
}
case 144: {
MessagesPerStream = input.ReadInt32();
break;
}
}
}
}
@ -1873,6 +1943,7 @@ namespace Grpc.Testing {
PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
coreList_ = other.coreList_.Clone();
otherServerApi_ = other.otherServerApi_;
threadsPerCq_ = other.threadsPerCq_;
resourceQuotaSize_ = other.resourceQuotaSize_;
}
@ -1989,6 +2060,20 @@ namespace Grpc.Testing {
}
}
/// <summary>Field number for the "threads_per_cq" field.</summary>
public const int ThreadsPerCqFieldNumber = 12;
private int threadsPerCq_;
/// <summary>
/// Number of threads that share each completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ThreadsPerCq {
get { return threadsPerCq_; }
set {
threadsPerCq_ = value;
}
}
/// <summary>Field number for the "resource_quota_size" field.</summary>
public const int ResourceQuotaSizeFieldNumber = 1001;
private int resourceQuotaSize_;
@ -2024,6 +2109,7 @@ namespace Grpc.Testing {
if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
if(!coreList_.Equals(other.coreList_)) return false;
if (OtherServerApi != other.OtherServerApi) return false;
if (ThreadsPerCq != other.ThreadsPerCq) return false;
if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
return true;
}
@ -2039,6 +2125,7 @@ namespace Grpc.Testing {
if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
hash ^= coreList_.GetHashCode();
if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
return hash;
}
@ -2079,6 +2166,10 @@ namespace Grpc.Testing {
output.WriteRawTag(90);
output.WriteString(OtherServerApi);
}
if (ThreadsPerCq != 0) {
output.WriteRawTag(96);
output.WriteInt32(ThreadsPerCq);
}
if (ResourceQuotaSize != 0) {
output.WriteRawTag(200, 62);
output.WriteInt32(ResourceQuotaSize);
@ -2110,6 +2201,9 @@ namespace Grpc.Testing {
if (OtherServerApi.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
}
if (ThreadsPerCq != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(ThreadsPerCq);
}
if (ResourceQuotaSize != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
}
@ -2149,6 +2243,9 @@ namespace Grpc.Testing {
if (other.OtherServerApi.Length != 0) {
OtherServerApi = other.OtherServerApi;
}
if (other.ThreadsPerCq != 0) {
ThreadsPerCq = other.ThreadsPerCq;
}
if (other.ResourceQuotaSize != 0) {
ResourceQuotaSize = other.ResourceQuotaSize;
}
@ -2201,6 +2298,10 @@ namespace Grpc.Testing {
OtherServerApi = input.ReadString();
break;
}
case 96: {
ThreadsPerCq = input.ReadInt32();
break;
}
case 8008: {
ResourceQuotaSize = input.ReadInt32();
break;
@ -3386,6 +3487,8 @@ namespace Grpc.Testing {
serverCpuUsage_ = other.serverCpuUsage_;
successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_;
failedRequestsPerSecond_ = other.failedRequestsPerSecond_;
clientPollsPerRequest_ = other.clientPollsPerRequest_;
serverPollsPerRequest_ = other.serverPollsPerRequest_;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3574,6 +3677,31 @@ namespace Grpc.Testing {
}
}
/// <summary>Field number for the "client_polls_per_request" field.</summary>
public const int ClientPollsPerRequestFieldNumber = 15;
private double clientPollsPerRequest_;
/// <summary>
/// Number of polls called inside completion queue per request
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ClientPollsPerRequest {
get { return clientPollsPerRequest_; }
set {
clientPollsPerRequest_ = value;
}
}
/// <summary>Field number for the "server_polls_per_request" field.</summary>
public const int ServerPollsPerRequestFieldNumber = 16;
private double serverPollsPerRequest_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerPollsPerRequest {
get { return serverPollsPerRequest_; }
set {
serverPollsPerRequest_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ScenarioResultSummary);
@ -3601,6 +3729,8 @@ namespace Grpc.Testing {
if (ServerCpuUsage != other.ServerCpuUsage) return false;
if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
if (ClientPollsPerRequest != other.ClientPollsPerRequest) return false;
if (ServerPollsPerRequest != other.ServerPollsPerRequest) return false;
return true;
}
@ -3621,6 +3751,8 @@ namespace Grpc.Testing {
if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
if (ClientPollsPerRequest != 0D) hash ^= ClientPollsPerRequest.GetHashCode();
if (ServerPollsPerRequest != 0D) hash ^= ServerPollsPerRequest.GetHashCode();
return hash;
}
@ -3687,6 +3819,14 @@ namespace Grpc.Testing {
output.WriteRawTag(113);
output.WriteDouble(FailedRequestsPerSecond);
}
if (ClientPollsPerRequest != 0D) {
output.WriteRawTag(121);
output.WriteDouble(ClientPollsPerRequest);
}
if (ServerPollsPerRequest != 0D) {
output.WriteRawTag(129, 1);
output.WriteDouble(ServerPollsPerRequest);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3734,6 +3874,12 @@ namespace Grpc.Testing {
if (FailedRequestsPerSecond != 0D) {
size += 1 + 8;
}
if (ClientPollsPerRequest != 0D) {
size += 1 + 8;
}
if (ServerPollsPerRequest != 0D) {
size += 2 + 8;
}
return size;
}
@ -3784,6 +3930,12 @@ namespace Grpc.Testing {
if (other.FailedRequestsPerSecond != 0D) {
FailedRequestsPerSecond = other.FailedRequestsPerSecond;
}
if (other.ClientPollsPerRequest != 0D) {
ClientPollsPerRequest = other.ClientPollsPerRequest;
}
if (other.ServerPollsPerRequest != 0D) {
ServerPollsPerRequest = other.ServerPollsPerRequest;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3850,6 +4002,14 @@ namespace Grpc.Testing {
FailedRequestsPerSecond = input.ReadDouble();
break;
}
case 121: {
ClientPollsPerRequest = input.ReadDouble();
break;
}
case 129: {
ServerPollsPerRequest = input.ReadDouble();
break;
}
}
}
}

@ -0,0 +1,112 @@
#region Copyright notice and license
// Copyright 2015-2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
/// <summary>
/// Shows how to attach custom error details as a binary trailer.
/// </summary>
public class CustomErrorDetailsTest
{
const string DebugInfoTrailerName = "debug-info-bin";
const string ExceptionDetail = "Exception thrown on purpose.";
const string Host = "localhost";
Server server;
Channel channel;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()
{
// Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755
server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Services = { TestService.BindService(new CustomErrorDetailsTestServiceImpl()) },
Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = new TestService.TestServiceClient(channel);
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public async Task UnaryCall()
{
var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 });
try
{
await call.ResponseAsync;
Assert.Fail();
}
catch (RpcException e)
{
Assert.AreEqual(StatusCode.Unknown, e.Status.StatusCode);
var debugInfo = GetDebugInfo(call.GetTrailers());
Assert.AreEqual(debugInfo.Detail, ExceptionDetail);
Assert.IsNotEmpty(debugInfo.StackEntries);
}
}
private DebugInfo GetDebugInfo(Metadata trailers)
{
var entry = trailers.First((e) => e.Key == DebugInfoTrailerName);
return DebugInfo.Parser.ParseFrom(entry.ValueBytes);
}
private class CustomErrorDetailsTestServiceImpl : TestService.TestServiceBase
{
public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
try
{
throw new ArgumentException(ExceptionDetail);
}
catch (Exception e)
{
// Fill debug info with some structured details about the failure.
var debugInfo = new DebugInfo();
debugInfo.Detail = e.Message;
debugInfo.StackEntries.AddRange(e.StackTrace.Split(new[] { Environment.NewLine }, StringSplitOptions.None));
context.ResponseTrailers.Add(DebugInfoTrailerName, debugInfo.ToByteArray());
throw new RpcException(new Status(StatusCode.Unknown, "The handler threw exception."));
}
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -24,20 +24,28 @@ namespace Grpc.Testing {
string.Concat(
"CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3NlcnZpY2VzLnByb3RvEgxncnBj",
"LnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVzc2FnZXMucHJv",
"dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bzKqAQoQ",
"QmVuY2htYXJrU2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3Rpbmcu",
"U2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJO",
"Cg1TdHJlYW1pbmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa",
"HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABMpcCCg1Xb3JrZXJT",
"ZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMudGVzdGluZy5TZXJ2ZXJBcmdz",
"GhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1cygBMAESRQoJUnVuQ2xpZW50",
"EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3MaGi5ncnBjLnRlc3RpbmcuQ2xp",
"ZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQSGS5ncnBjLnRlc3RpbmcuQ29y",
"ZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29yZVJlc3BvbnNlEjQKClF1aXRX",
"b3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoSLmdycGMudGVzdGluZy5Wb2lk",
"YgZwcm90bzM="));
"dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bxoic3Jj",
"L3Byb3RvL2dycGMvdGVzdGluZy9zdGF0cy5wcm90bzKmAwoQQmVuY2htYXJr",
"U2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVx",
"dWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJOCg1TdHJlYW1p",
"bmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRl",
"c3RpbmcuU2ltcGxlUmVzcG9uc2UoATABElIKE1N0cmVhbWluZ0Zyb21DbGll",
"bnQSGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGlu",
"Zy5TaW1wbGVSZXNwb25zZSgBElIKE1N0cmVhbWluZ0Zyb21TZXJ2ZXISGy5n",
"cnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1w",
"bGVSZXNwb25zZTABElIKEVN0cmVhbWluZ0JvdGhXYXlzEhsuZ3JwYy50ZXN0",
"aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9u",
"c2UoATABMpcCCg1Xb3JrZXJTZXJ2aWNlEkUKCVJ1blNlcnZlchIYLmdycGMu",
"dGVzdGluZy5TZXJ2ZXJBcmdzGhouZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXR1",
"cygBMAESRQoJUnVuQ2xpZW50EhguZ3JwYy50ZXN0aW5nLkNsaWVudEFyZ3Ma",
"Gi5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHVzKAEwARJCCglDb3JlQ291bnQS",
"GS5ncnBjLnRlc3RpbmcuQ29yZVJlcXVlc3QaGi5ncnBjLnRlc3RpbmcuQ29y",
"ZVJlc3BvbnNlEjQKClF1aXRXb3JrZXISEi5ncnBjLnRlc3RpbmcuVm9pZBoS",
"LmdycGMudGVzdGluZy5Wb2lkMl4KGFJlcG9ydFFwc1NjZW5hcmlvU2Vydmlj",
"ZRJCCg5SZXBvcnRTY2VuYXJpbxIcLmdycGMudGVzdGluZy5TY2VuYXJpb1Jl",
"c3VsdBoSLmdycGMudGVzdGluZy5Wb2lkYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, },
new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(null, null));
}
#endregion

@ -46,6 +46,27 @@ namespace Grpc.Testing {
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromClient = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
grpc::MethodType.ClientStreaming,
__ServiceName,
"StreamingFromClient",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromServer = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
grpc::MethodType.ServerStreaming,
__ServiceName,
"StreamingFromServer",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingBothWays = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
grpc::MethodType.DuplexStreaming,
__ServiceName,
"StreamingBothWays",
__Marshaller_SimpleRequest,
__Marshaller_SimpleResponse);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
@ -68,8 +89,9 @@ namespace Grpc.Testing {
}
/// <summary>
/// One request followed by one response.
/// The server returns the client payload as-is.
/// Repeated sequence of one request followed by one response.
/// Should be called streaming ping-pong
/// The server returns the client payload as-is on each response
/// </summary>
/// <param name="requestStream">Used for reading requests from the client.</param>
/// <param name="responseStream">Used for sending responses back to the client.</param>
@ -80,6 +102,44 @@ namespace Grpc.Testing {
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
/// <summary>
/// Single-sided unbounded streaming from client to server
/// The server returns the client payload as-is once the client does WritesDone
/// </summary>
/// <param name="requestStream">Used for reading requests from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
/// <summary>
/// Single-sided unbounded streaming from server to client
/// The server repeatedly returns the client payload as-is
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="responseStream">Used for sending responses back to the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>A task indicating completion of the handler.</returns>
public virtual global::System.Threading.Tasks.Task StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
/// <summary>
/// Two-sided unbounded streaming between server to client
/// Both sides send the content of their own choice to the other
/// </summary>
/// <param name="requestStream">Used for reading requests from the client.</param>
/// <param name="responseStream">Used for sending responses back to the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>A task indicating completion of the handler.</returns>
public virtual global::System.Threading.Tasks.Task StreamingBothWays(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for BenchmarkService</summary>
@ -154,8 +214,9 @@ namespace Grpc.Testing {
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
/// <summary>
/// One request followed by one response.
/// The server returns the client payload as-is.
/// Repeated sequence of one request followed by one response.
/// Should be called streaming ping-pong
/// The server returns the client payload as-is on each response
/// </summary>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
@ -166,8 +227,9 @@ namespace Grpc.Testing {
return StreamingCall(new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// One request followed by one response.
/// The server returns the client payload as-is.
/// Repeated sequence of one request followed by one response.
/// Should be called streaming ping-pong
/// The server returns the client payload as-is on each response
/// </summary>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
@ -175,6 +237,74 @@ namespace Grpc.Testing {
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
}
/// <summary>
/// Single-sided unbounded streaming from client to server
/// The server returns the client payload as-is once the client does WritesDone
/// </summary>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingFromClient(new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Single-sided unbounded streaming from client to server
/// The server returns the client payload as-is once the client does WritesDone
/// </summary>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_StreamingFromClient, null, options);
}
/// <summary>
/// Single-sided unbounded streaming from server to client
/// The server repeatedly returns the client payload as-is
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingFromServer(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Single-sided unbounded streaming from server to client
/// The server repeatedly returns the client payload as-is
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_StreamingFromServer, null, options, request);
}
/// <summary>
/// Two-sided unbounded streaming between server to client
/// Both sides send the content of their own choice to the other
/// </summary>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingBothWays(new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Two-sided unbounded streaming between server to client
/// Both sides send the content of their own choice to the other
/// </summary>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingBothWays, null, options);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
{
@ -188,7 +318,10 @@ namespace Grpc.Testing {
{
return grpc::ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall)
.AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient)
.AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer)
.AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build();
}
}
@ -489,5 +622,124 @@ namespace Grpc.Testing {
}
}
public static partial class ReportQpsScenarioService
{
static readonly string __ServiceName = "grpc.testing.ReportQpsScenarioService";
static readonly grpc::Marshaller<global::Grpc.Testing.ScenarioResult> __Marshaller_ScenarioResult = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ScenarioResult.Parser.ParseFrom);
static readonly grpc::Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
static readonly grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void> __Method_ReportScenario = new grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void>(
grpc::MethodType.Unary,
__ServiceName,
"ReportScenario",
__Marshaller_ScenarioResult,
__Marshaller_Void);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[2]; }
}
/// <summary>Base class for server-side implementations of ReportQpsScenarioService</summary>
public abstract partial class ReportQpsScenarioServiceBase
{
/// <summary>
/// Report results of a QPS test benchmark scenario.
/// </summary>
/// <param name="request">The request received from the client.</param>
/// <param name="context">The context of the server-side call handler being invoked.</param>
/// <returns>The response to send back to the client (wrapped by a task).</returns>
public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::ServerCallContext context)
{
throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for ReportQpsScenarioService</summary>
public partial class ReportQpsScenarioServiceClient : grpc::ClientBase<ReportQpsScenarioServiceClient>
{
/// <summary>Creates a new client for ReportQpsScenarioService</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public ReportQpsScenarioServiceClient(grpc::Channel channel) : base(channel)
{
}
/// <summary>Creates a new client for ReportQpsScenarioService that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public ReportQpsScenarioServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected ReportQpsScenarioServiceClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected ReportQpsScenarioServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// Report results of a QPS test benchmark scenario.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return ReportScenario(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Report results of a QPS test benchmark scenario.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The response received from the server.</returns>
public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_ReportScenario, null, options, request);
}
/// <summary>
/// Report results of a QPS test benchmark scenario.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
/// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
/// <param name="cancellationToken">An optional token for canceling the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return ReportScenarioAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// Report results of a QPS test benchmark scenario.
/// </summary>
/// <param name="request">The request to send to the server.</param>
/// <param name="options">The options for the call.</param>
/// <returns>The call object.</returns>
public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_ReportScenario, null, options, request);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override ReportQpsScenarioServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new ReportQpsScenarioServiceClient(configuration);
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
/// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
public static grpc::ServerServiceDefinition BindService(ReportQpsScenarioServiceBase serviceImpl)
{
return grpc::ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build();
}
}
}
#endregion

@ -23,27 +23,28 @@ namespace Grpc.Testing {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiJzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3N0YXRzLnByb3RvEgxncnBjLnRl",
"c3RpbmciegoLU2VydmVyU3RhdHMSFAoMdGltZV9lbGFwc2VkGAEgASgBEhEK",
"CXRpbWVfdXNlchgCIAEoARITCgt0aW1lX3N5c3RlbRgDIAEoARIWCg50b3Rh",
"bF9jcHVfdGltZRgEIAEoBBIVCg1pZGxlX2NwdV90aW1lGAUgASgEIjsKD0hp",
"c3RvZ3JhbVBhcmFtcxISCgpyZXNvbHV0aW9uGAEgASgBEhQKDG1heF9wb3Nz",
"aWJsZRgCIAEoASJ3Cg1IaXN0b2dyYW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQ",
"CghtaW5fc2VlbhgCIAEoARIQCghtYXhfc2VlbhgDIAEoARILCgNzdW0YBCAB",
"KAESFgoOc3VtX29mX3NxdWFyZXMYBSABKAESDQoFY291bnQYBiABKAEiOAoS",
"UmVxdWVzdFJlc3VsdENvdW50EhMKC3N0YXR1c19jb2RlGAEgASgFEg0KBWNv",
"dW50GAIgASgDIrYBCgtDbGllbnRTdGF0cxIuCglsYXRlbmNpZXMYASABKAsy",
"Gy5ncnBjLnRlc3RpbmcuSGlzdG9ncmFtRGF0YRIUCgx0aW1lX2VsYXBzZWQY",
"AiABKAESEQoJdGltZV91c2VyGAMgASgBEhMKC3RpbWVfc3lzdGVtGAQgASgB",
"EjkKD3JlcXVlc3RfcmVzdWx0cxgFIAMoCzIgLmdycGMudGVzdGluZy5SZXF1",
"ZXN0UmVzdWx0Q291bnRiBnByb3RvMw=="));
"c3RpbmcikQEKC1NlcnZlclN0YXRzEhQKDHRpbWVfZWxhcHNlZBgBIAEoARIR",
"Cgl0aW1lX3VzZXIYAiABKAESEwoLdGltZV9zeXN0ZW0YAyABKAESFgoOdG90",
"YWxfY3B1X3RpbWUYBCABKAQSFQoNaWRsZV9jcHVfdGltZRgFIAEoBBIVCg1j",
"cV9wb2xsX2NvdW50GAYgASgEIjsKD0hpc3RvZ3JhbVBhcmFtcxISCgpyZXNv",
"bHV0aW9uGAEgASgBEhQKDG1heF9wb3NzaWJsZRgCIAEoASJ3Cg1IaXN0b2dy",
"YW1EYXRhEg4KBmJ1Y2tldBgBIAMoDRIQCghtaW5fc2VlbhgCIAEoARIQCght",
"YXhfc2VlbhgDIAEoARILCgNzdW0YBCABKAESFgoOc3VtX29mX3NxdWFyZXMY",
"BSABKAESDQoFY291bnQYBiABKAEiOAoSUmVxdWVzdFJlc3VsdENvdW50EhMK",
"C3N0YXR1c19jb2RlGAEgASgFEg0KBWNvdW50GAIgASgDIs0BCgtDbGllbnRT",
"dGF0cxIuCglsYXRlbmNpZXMYASABKAsyGy5ncnBjLnRlc3RpbmcuSGlzdG9n",
"cmFtRGF0YRIUCgx0aW1lX2VsYXBzZWQYAiABKAESEQoJdGltZV91c2VyGAMg",
"ASgBEhMKC3RpbWVfc3lzdGVtGAQgASgBEjkKD3JlcXVlc3RfcmVzdWx0cxgF",
"IAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0Q291bnQSFQoNY3Ff",
"cG9sbF9jb3VudBgGIAEoBGIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem", "TotalCpuTime", "IdleCpuTime" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStats), global::Grpc.Testing.ServerStats.Parser, new[]{ "TimeElapsed", "TimeUser", "TimeSystem", "TotalCpuTime", "IdleCpuTime", "CqPollCount" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramParams), global::Grpc.Testing.HistogramParams.Parser, new[]{ "Resolution", "MaxPossible" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.HistogramData), global::Grpc.Testing.HistogramData.Parser, new[]{ "Bucket", "MinSeen", "MaxSeen", "Sum", "SumOfSquares", "Count" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.RequestResultCount), global::Grpc.Testing.RequestResultCount.Parser, new[]{ "StatusCode", "Count" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem", "RequestResults" }, null, null, null)
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStats), global::Grpc.Testing.ClientStats.Parser, new[]{ "Latencies", "TimeElapsed", "TimeUser", "TimeSystem", "RequestResults", "CqPollCount" }, null, null, null)
}));
}
#endregion
@ -79,6 +80,7 @@ namespace Grpc.Testing {
timeSystem_ = other.timeSystem_;
totalCpuTime_ = other.totalCpuTime_;
idleCpuTime_ = other.idleCpuTime_;
cqPollCount_ = other.cqPollCount_;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -157,6 +159,20 @@ namespace Grpc.Testing {
}
}
/// <summary>Field number for the "cq_poll_count" field.</summary>
public const int CqPollCountFieldNumber = 6;
private ulong cqPollCount_;
/// <summary>
/// Number of polls called inside completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ulong CqPollCount {
get { return cqPollCount_; }
set {
cqPollCount_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ServerStats);
@ -175,6 +191,7 @@ namespace Grpc.Testing {
if (TimeSystem != other.TimeSystem) return false;
if (TotalCpuTime != other.TotalCpuTime) return false;
if (IdleCpuTime != other.IdleCpuTime) return false;
if (CqPollCount != other.CqPollCount) return false;
return true;
}
@ -186,6 +203,7 @@ namespace Grpc.Testing {
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode();
if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode();
if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
return hash;
}
@ -216,6 +234,10 @@ namespace Grpc.Testing {
output.WriteRawTag(40);
output.WriteUInt64(IdleCpuTime);
}
if (CqPollCount != 0UL) {
output.WriteRawTag(48);
output.WriteUInt64(CqPollCount);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -236,6 +258,9 @@ namespace Grpc.Testing {
if (IdleCpuTime != 0UL) {
size += 1 + pb::CodedOutputStream.ComputeUInt64Size(IdleCpuTime);
}
if (CqPollCount != 0UL) {
size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount);
}
return size;
}
@ -259,6 +284,9 @@ namespace Grpc.Testing {
if (other.IdleCpuTime != 0UL) {
IdleCpuTime = other.IdleCpuTime;
}
if (other.CqPollCount != 0UL) {
CqPollCount = other.CqPollCount;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -289,6 +317,10 @@ namespace Grpc.Testing {
IdleCpuTime = input.ReadUInt64();
break;
}
case 48: {
CqPollCount = input.ReadUInt64();
break;
}
}
}
}
@ -876,6 +908,7 @@ namespace Grpc.Testing {
timeUser_ = other.timeUser_;
timeSystem_ = other.timeSystem_;
requestResults_ = other.requestResults_.Clone();
cqPollCount_ = other.cqPollCount_;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -946,6 +979,20 @@ namespace Grpc.Testing {
get { return requestResults_; }
}
/// <summary>Field number for the "cq_poll_count" field.</summary>
public const int CqPollCountFieldNumber = 6;
private ulong cqPollCount_;
/// <summary>
/// Number of polls called inside completion queue
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public ulong CqPollCount {
get { return cqPollCount_; }
set {
cqPollCount_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as ClientStats);
@ -964,6 +1011,7 @@ namespace Grpc.Testing {
if (TimeUser != other.TimeUser) return false;
if (TimeSystem != other.TimeSystem) return false;
if(!requestResults_.Equals(other.requestResults_)) return false;
if (CqPollCount != other.CqPollCount) return false;
return true;
}
@ -975,6 +1023,7 @@ namespace Grpc.Testing {
if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
hash ^= requestResults_.GetHashCode();
if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
return hash;
}
@ -1002,6 +1051,10 @@ namespace Grpc.Testing {
output.WriteDouble(TimeSystem);
}
requestResults_.WriteTo(output, _repeated_requestResults_codec);
if (CqPollCount != 0UL) {
output.WriteRawTag(48);
output.WriteUInt64(CqPollCount);
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1020,6 +1073,9 @@ namespace Grpc.Testing {
size += 1 + 8;
}
size += requestResults_.CalculateSize(_repeated_requestResults_codec);
if (CqPollCount != 0UL) {
size += 1 + pb::CodedOutputStream.ComputeUInt64Size(CqPollCount);
}
return size;
}
@ -1044,6 +1100,9 @@ namespace Grpc.Testing {
TimeSystem = other.TimeSystem;
}
requestResults_.Add(other.requestResults_);
if (other.CqPollCount != 0UL) {
CqPollCount = other.CqPollCount;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1077,6 +1136,10 @@ namespace Grpc.Testing {
requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec);
break;
}
case 48: {
CqPollCount = input.ReadUInt64();
break;
}
}
}
}

@ -37,4 +37,4 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR
# don't match the package names. Setting -I to the correct value src/proto
# breaks the code generation.
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto
-I . src/proto/grpc/testing/{control,echo_messages,empty,messages,metrics,payloads,services,stats,test}.proto

@ -42,6 +42,7 @@
"Grpc.HealthCheck.Tests.HealthServiceImplTest"
],
"Grpc.IntegrationTesting": [
"Grpc.IntegrationTesting.CustomErrorDetailsTest",
"Grpc.IntegrationTesting.GeneratedClientTest",
"Grpc.IntegrationTesting.GeneratedServiceBaseTest",
"Grpc.IntegrationTesting.HistogramTest",

@ -163,6 +163,12 @@ extern id const kGRPCTrailersKey;
/** Represents a single gRPC remote call. */
@interface GRPCCall : GRXWriter
/**
* The authority for the RPC. If nil, the default authority will be used. This property must be nil
* when Cronet transport is enabled.
*/
@property (atomic, readwrite) NSString *serverName;
/**
* The container of the request headers of an RPC conforms to this protocol, which is a subset of
* NSMutableDictionary's interface. It will become a NSMutableDictionary later on.

@ -425,7 +425,7 @@ static NSMutableDictionary *callFlags;
_responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable
dispatchQueue:_responseQueue];
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host path:_path];
_wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host serverName:_serverName path:_path];
NSAssert(_wrappedCall, @"Error allocating RPC objects. Low memory?");
[self sendHeaders:_requestHeaders];

@ -62,5 +62,6 @@ struct grpc_channel_credentials;
channelArgs:(nullable NSDictionary *)channelArgs;
- (nullable grpc_call *)unmanagedCallWithPath:(nonnull NSString *)path
serverName:(nonnull NSString *)serverName
completionQueue:(nonnull GRPCCompletionQueue *)queue;
@end

@ -181,14 +181,22 @@ static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) {
}
- (grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
completionQueue:(GRPCCompletionQueue *)queue {
grpc_slice host_slice;
if (serverName) {
host_slice = grpc_slice_from_copied_string(serverName.UTF8String);
}
grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String);
grpc_call *call = grpc_channel_create_call(_unmanagedChannel,
NULL, GRPC_PROPAGATE_DEFAULTS,
queue.unmanagedQueue,
path_slice,
NULL, // Passing NULL for host
serverName ? &host_slice : NULL,
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
if (serverName) {
grpc_slice_unref(host_slice);
}
grpc_slice_unref(path_slice);
return call;
}

@ -54,6 +54,7 @@ struct grpc_channel_credentials;
/** Create a grpc_call object to the provided path on this host. */
- (nullable struct grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
completionQueue:(GRPCCompletionQueue *)queue;
// TODO: There's a race when a new RPC is coming through just as an existing one is getting

@ -120,6 +120,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil;
}
- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
serverName:(NSString *)serverName
completionQueue:(GRPCCompletionQueue *)queue {
GRPCChannel *channel;
// This is racing -[GRPCHost disconnect].
@ -129,7 +130,7 @@ static GRPCConnectivityMonitor *connectivityMonitor = nil;
}
channel = _channel;
}
return [channel unmanagedCallWithPath:path completionQueue:queue];
return [channel unmanagedCallWithPath:path serverName:serverName completionQueue:queue];
}
- (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts

@ -75,6 +75,7 @@
@interface GRPCWrappedCall : NSObject
- (instancetype)initWithHost:(NSString *)host
serverName:(NSString *)serverName
path:(NSString *)path NS_DESIGNATED_INITIALIZER;
- (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)())errorHandler;

@ -75,6 +75,10 @@
}
- (void)dealloc {
for (int i = 0; i < _op.data.send_initial_metadata.count; i++) {
grpc_slice_unref(_op.data.send_initial_metadata.metadata[i].key);
grpc_slice_unref(_op.data.send_initial_metadata.metadata[i].value);
}
gpr_free(_op.data.send_initial_metadata.metadata);
}
@ -232,10 +236,11 @@
}
- (instancetype)init {
return [self initWithHost:nil path:nil];
return [self initWithHost:nil serverName:nil path:nil];
}
- (instancetype)initWithHost:(NSString *)host
serverName:(NSString *)serverName
path:(NSString *)path {
if (!path || !host) {
[NSException raise:NSInvalidArgumentException
@ -248,7 +253,7 @@
// queue. Currently we use a singleton queue.
_queue = [GRPCCompletionQueue completionQueue];
_call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path completionQueue:_queue];
_call = [[GRPCHost hostWithAddress:host] unmanagedCallWithPath:path serverName:serverName completionQueue:_queue];
if (_call == NULL) {
return nil;
}

@ -246,6 +246,10 @@ static char *roots_filename;
[self testIndividualCase:"cancel_after_invoke"];
}
- (void)testCancelAfterRoundTrip {
[self testIndividualCase:"cancel_after_round_trip"];
}
- (void)testCancelBeforeInvoke {
[self testIndividualCase:"cancel_before_invoke"];
}

@ -849,7 +849,10 @@ def _poll_connectivity(state, channel, initial_try_to_connect):
_common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
connectivity])
if not state.delivering:
callbacks = _deliveries(state)
# NOTE(nathaniel): The field is only ever used as a
# sequence so it's fine that both lists and tuples are
# assigned to it.
callbacks = _deliveries(state) # pylint: disable=redefined-variable-type
if callbacks:
_spawn_delivery(state, callbacks)

@ -16,10 +16,11 @@
import collections
import enum
import logging
import six
import threading
import time
import six
import grpc
from grpc import _common
from grpc._cython import cygrpc

@ -73,6 +73,11 @@
set(PACKAGE_TARNAME "<%text>${PACKAGE_NAME}-${PACKAGE_VERSION}</%text>")
set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
project(<%text>${PACKAGE_NAME}</%text> C CXX)
set(gRPC_INSTALL_BINDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/bin" CACHE PATH "Installation directory for executables")
set(gRPC_INSTALL_LIBDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/lib" CACHE PATH "Installation directory for libraries")
set(gRPC_INSTALL_INCLUDEDIR "<%text>${CMAKE_INSTALL_PREFIX}</%text>/include" CACHE PATH "Installation directory for headers")
set(gRPC_INSTALL_CMAKEDIR "<%text>${CMAKE_INSTALL_PREFIX}/lib/cmake/${PACKAGE_NAME}</%text>" CACHE PATH "Installation directory for cmake config files")
# Options
option(gRPC_BUILD_TESTS "Build tests" OFF)
@ -97,6 +102,9 @@
set(gRPC_PROTOBUF_PROVIDER "module" CACHE STRING "Provider of protobuf library")
set_property(CACHE gRPC_PROTOBUF_PROVIDER PROPERTY STRINGS "module" "package")
set(gRPC_PROTOBUF_PACKAGE_TYPE "" CACHE STRING "Algorithm for searching protobuf package")
set_property(CACHE gRPC_PROTOBUF_PACKAGE_TYPE PROPERTY STRINGS "CONFIG" "MODULE")
set(gRPC_GFLAGS_PROVIDER "module" CACHE STRING "Provider of gflags library")
set_property(CACHE gRPC_GFLAGS_PROVIDER PROPERTY STRINGS "module" "package")
@ -143,6 +151,9 @@
endif()
set(ZLIB_INCLUDE_DIR "<%text>${ZLIB_ROOT_DIR}</%text>")
if(EXISTS "<%text>${ZLIB_ROOT_DIR}</%text>/CMakeLists.txt")
# TODO(jtattermusch): workaround for https://github.com/madler/zlib/issues/218
include_directories(<%text>${ZLIB_INCLUDE_DIR}</%text>)
add_subdirectory(<%text>${ZLIB_ROOT_DIR}</%text> third_party/zlib)
if(TARGET zlibstatic)
set(_gRPC_ZLIB_LIBRARIES zlibstatic)
@ -204,6 +215,11 @@
if(NOT protobuf_BUILD_TESTS)
set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build protobuf tests")
endif()
# Disable building protobuf with zlib. Building protobuf with zlib breaks
# the build if zlib is not installed on the system.
if(NOT protobuf_WITH_ZLIB)
set(protobuf_WITH_ZLIB OFF CACHE BOOL "Build protobuf with zlib.")
endif()
if(NOT PROTOBUF_ROOT_DIR)
set(PROTOBUF_ROOT_DIR <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/third_party/protobuf)
endif()
@ -228,21 +244,27 @@
set(gRPC_INSTALL FALSE)
endif()
elseif("<%text>${gRPC_PROTOBUF_PROVIDER}</%text>" STREQUAL "package")
find_package(protobuf CONFIG)
if(protobuf_FOUND)
find_package(Protobuf <%text>${gRPC_PROTOBUF_PACKAGE_TYPE}</%text>)
if(Protobuf_FOUND OR PROTOBUF_FOUND)
if(TARGET protobuf::<%text>${_gRPC_PROTOBUF_LIBRARY_NAME}</%text>)
set(_gRPC_PROTOBUF_LIBRARIES protobuf::<%text>${_gRPC_PROTOBUF_LIBRARY_NAME}</%text>)
else()
set(_gRPC_PROTOBUF_LIBRARIES <%text>${PROTOBUF_LIBRARIES}</%text>)
endif()
if(TARGET protobuf::libprotoc)
set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc)
else()
set(_gRPC_PROTOBUF_PROTOC_LIBRARIES <%text>${PROTOBUF_PROTOC_LIBRARIES}</%text>)
endif()
if(TARGET protobuf::protoc)
set(_gRPC_PROTOBUF_PROTOC protobuf::protoc)
else()
set(_gRPC_PROTOBUF_PROTOC <%text>${PROTOBUF_PROTOC_EXECUTABLE}</%text>)
endif()
set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n find_package(protobuf CONFIG)\nendif()")
else()
find_package(Protobuf MODULE)
set(_gRPC_FIND_PROTOBUF "if(NOT Protobuf_FOUND)\n find_package(Protobuf)\nendif()")
set(_gRPC_FIND_PROTOBUF "if(NOT Protobuf_FOUND AND NOT PROTOBUF_FOUND)\n find_package(Protobuf <%text>${gRPC_PROTOBUF_PACKAGE_TYPE}</%text>)\nendif()")
endif()
if(PROTOBUF_FOUND)
include_directories(<%text>${PROTOBUF_INCLUDE_DIRS}</%text>)
endif()
set(PROTOBUF_WELLKNOWN_IMPORT_DIR /usr/local/include)
endif()
@ -327,11 +349,6 @@
set(_gRPC_BASELIB_LIBRARIES wsock32 ws2_32)
endif()
include(GNUInstallDirs)
if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR)
set(CMAKE_INSTALL_CMAKEDIR "<%text>${CMAKE_INSTALL_LIBDIR}</%text>/cmake/gRPC")
endif()
# Create directory for generated .proto files
set(_gRPC_PROTO_GENS_DIR <%text>${CMAKE_BINARY_DIR}/gens</%text>)
file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_GENS_DIR}</%text>)
@ -492,7 +509,7 @@
)
if (gRPC_INSTALL)
install(FILES <%text>${CMAKE_CURRENT_BINARY_DIR}/</%text>${lib.name}.pdb
DESTINATION <%text>${CMAKE_INSTALL_LIBDIR}</%text> OPTIONAL
DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text> OPTIONAL
)
endif()
endif()
@ -506,8 +523,8 @@
% endfor
target_include_directories(${lib.name}
PUBLIC <%text>$<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include></%text>
PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>/include
PRIVATE <%text>${BORINGSSL_ROOT_DIR}</%text>/include
PRIVATE <%text>${PROTOBUF_ROOT_DIR}</%text>/src
PRIVATE <%text>${ZLIB_INCLUDE_DIR}</%text>
@ -546,7 +563,7 @@
string(REPLACE "include/" "" _path <%text>${_hdr}</%text>)
get_filename_component(_path <%text>${_path}</%text> PATH)
install(FILES <%text>${_hdr}</%text>
DESTINATION "<%text>${CMAKE_INSTALL_INCLUDEDIR}/${_path}</%text>"
DESTINATION "<%text>${gRPC_INSTALL_INCLUDEDIR}/${_path}</%text>"
)
endforeach()
% endif
@ -614,16 +631,16 @@
<%def name="cc_install(tgt)">
if (gRPC_INSTALL)
install(TARGETS ${tgt.name} EXPORT gRPCTargets
RUNTIME DESTINATION <%text>${CMAKE_INSTALL_BINDIR}</%text>
LIBRARY DESTINATION <%text>${CMAKE_INSTALL_LIBDIR}</%text>
ARCHIVE DESTINATION <%text>${CMAKE_INSTALL_LIBDIR}</%text>
RUNTIME DESTINATION <%text>${gRPC_INSTALL_BINDIR}</%text>
LIBRARY DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text>
ARCHIVE DESTINATION <%text>${gRPC_INSTALL_LIBDIR}</%text>
)
endif()
</%def>
if (gRPC_INSTALL)
install(EXPORT gRPCTargets
DESTINATION <%text>${CMAKE_INSTALL_CMAKEDIR}</%text>
DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
NAMESPACE gRPC::
)
endif()
@ -632,6 +649,6 @@
configure_file(tools/cmake/<%text>${_config}</%text>.cmake.in
<%text>${_config}</%text>.cmake @ONLY)
install(FILES <%text>${CMAKE_CURRENT_BINARY_DIR}/${_config}</%text>.cmake
DESTINATION <%text>${CMAKE_INSTALL_CMAKEDIR}</%text>
DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
)
endforeach()

@ -0,0 +1,78 @@
%YAML 1.2
--- |
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM debian:jessie
# Install JDK 8 and Git
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && ${'\\'}
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
RUN apt-get update && apt-get -y install ${'\\'}
git ${'\\'}
libapr1 ${'\\'}
oracle-java8-installer ${'\\'}
&& ${'\\'}
apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
ENV PATH $PATH:$JAVA_HOME/bin
# Install protobuf
RUN apt-get update && apt-get install -y ${'\\'}
autoconf ${'\\'}
build-essential ${'\\'}
curl ${'\\'}
gcc ${'\\'}
libtool ${'\\'}
unzip ${'\\'}
&& ${'\\'}
apt-get clean
WORKDIR /
RUN git clone https://github.com/google/protobuf.git
WORKDIR /protobuf
RUN git checkout v3.3.1 && ${'\\'}
./autogen.sh && ${'\\'}
./configure && ${'\\'}
make && ${'\\'}
make check && ${'\\'}
make install
# Install gcloud command line tools
ENV CLOUD_SDK_REPO "cloud-sdk-jessie"
RUN echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && ${'\\'}
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && ${'\\'}
apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && ${'\\'}
gcloud config set component_manager/disable_update_check true
# Download and install grpc-java
WORKDIR /
RUN git clone https://github.com/grpc/grpc-java.git
WORKDIR /grpc-java
RUN ./gradlew install
# Setup the Android SDK licenses
ENV ANDROID_HOME "/grpc-java/android-interop-testing/.android"
RUN mkdir -p "<%text>${ANDROID_HOME}</%text>/licenses"
RUN echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "<%text>${ANDROID_HOME}</%text>/licenses/android-sdk-license"
RUN echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "<%text>${ANDROID_HOME}</%text>/licenses/android-sdk-preview-license"
# Build the Android interop apks
WORKDIR /grpc-java/android-interop-testing
RUN ../gradlew assembleDebug
RUN ../gradlew assembleDebugAndroidTest
# Define the default command.
CMD ["bash"]

@ -5,7 +5,8 @@
RUN touch .profile
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
# Install all versions of node that we want to test
RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm alias default 4"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 6 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 8 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm alias default 8"

@ -44,6 +44,8 @@ extern void cancel_after_client_done(grpc_end2end_test_config config);
extern void cancel_after_client_done_pre_init(void);
extern void cancel_after_invoke(grpc_end2end_test_config config);
extern void cancel_after_invoke_pre_init(void);
extern void cancel_after_round_trip(grpc_end2end_test_config config);
extern void cancel_after_round_trip_pre_init(void);
extern void cancel_before_invoke(grpc_end2end_test_config config);
extern void cancel_before_invoke_pre_init(void);
extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
@ -148,6 +150,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_after_accept_pre_init();
cancel_after_client_done_pre_init();
cancel_after_invoke_pre_init();
cancel_after_round_trip_pre_init();
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
@ -210,6 +213,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_after_accept(config);
cancel_after_client_done(config);
cancel_after_invoke(config);
cancel_after_round_trip(config);
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
@ -288,6 +292,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_after_invoke(config);
continue;
}
if (0 == strcmp("cancel_after_round_trip", argv[i])) {
cancel_after_round_trip(config);
continue;
}
if (0 == strcmp("cancel_before_invoke", argv[i])) {
cancel_before_invoke(config);
continue;

@ -46,6 +46,8 @@ extern void cancel_after_client_done(grpc_end2end_test_config config);
extern void cancel_after_client_done_pre_init(void);
extern void cancel_after_invoke(grpc_end2end_test_config config);
extern void cancel_after_invoke_pre_init(void);
extern void cancel_after_round_trip(grpc_end2end_test_config config);
extern void cancel_after_round_trip_pre_init(void);
extern void cancel_before_invoke(grpc_end2end_test_config config);
extern void cancel_before_invoke_pre_init(void);
extern void cancel_in_a_vacuum(grpc_end2end_test_config config);
@ -151,6 +153,7 @@ void grpc_end2end_tests_pre_init(void) {
cancel_after_accept_pre_init();
cancel_after_client_done_pre_init();
cancel_after_invoke_pre_init();
cancel_after_round_trip_pre_init();
cancel_before_invoke_pre_init();
cancel_in_a_vacuum_pre_init();
cancel_with_status_pre_init();
@ -214,6 +217,7 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_after_accept(config);
cancel_after_client_done(config);
cancel_after_invoke(config);
cancel_after_round_trip(config);
cancel_before_invoke(config);
cancel_in_a_vacuum(config);
cancel_with_status(config);
@ -296,6 +300,10 @@ void grpc_end2end_tests(int argc, char **argv,
cancel_after_invoke(config);
continue;
}
if (0 == strcmp("cancel_after_round_trip", argv[i])) {
cancel_after_round_trip(config);
continue;
}
if (0 == strcmp("cancel_before_invoke", argv[i])) {
cancel_before_invoke(config);
continue;

@ -87,6 +87,7 @@ END2END_TESTS = {
'cancel_after_accept': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_after_client_done': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_after_invoke': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_after_round_trip': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_before_invoke': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_in_a_vacuum': default_test_options._replace(cpu_cost=LOWCPU),
'cancel_with_status': default_test_options._replace(cpu_cost=LOWCPU),

@ -79,6 +79,7 @@ END2END_TESTS = {
'cancel_after_accept': test_options(),
'cancel_after_client_done': test_options(),
'cancel_after_invoke': test_options(),
'cancel_after_round_trip': test_options(),
'cancel_before_invoke': test_options(),
'cancel_in_a_vacuum': test_options(),
'cancel_with_status': test_options(),

@ -81,7 +81,10 @@ static void test_bad_ping(grpc_end2end_test_config config) {
.value.integer = 300000 /* 5 minutes */},
{.type = GRPC_ARG_INTEGER,
.key = GRPC_ARG_HTTP2_MAX_PING_STRIKES,
.value.integer = MAX_PING_STRIKES}};
.value.integer = MAX_PING_STRIKES},
{.type = GRPC_ARG_INTEGER,
.key = GRPC_ARG_HTTP2_BDP_PROBE,
.value.integer = 0}};
grpc_channel_args client_args = {.num_args = GPR_ARRAY_SIZE(client_a),
.args = client_a};
grpc_channel_args server_args = {.num_args = GPR_ARRAY_SIZE(server_a),

@ -0,0 +1,298 @@
/*
*
* Copyright 2017 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
#include <string.h>
#include <grpc/byte_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/service_config.h"
#include "test/core/end2end/cq_verifier.h"
#include "test/core/end2end/tests/cancel_test_helpers.h"
static void *tag(intptr_t t) { return (void *)t; }
static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
const char *test_name,
grpc_channel_args *client_args,
grpc_channel_args *server_args) {
grpc_end2end_test_fixture f;
gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
f = config.create_fixture(client_args, server_args);
config.init_server(&f, server_args);
config.init_client(&f, client_args);
return f;
}
static gpr_timespec n_seconds_from_now(int n) {
return grpc_timeout_seconds_to_deadline(n);
}
static gpr_timespec five_seconds_from_now(void) {
return n_seconds_from_now(5);
}
static void drain_cq(grpc_completion_queue *cq) {
grpc_event ev;
do {
ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL);
} while (ev.type != GRPC_QUEUE_SHUTDOWN);
}
static void shutdown_server(grpc_end2end_test_fixture *f) {
if (!f->server) return;
grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
grpc_timeout_seconds_to_deadline(5),
NULL)
.type == GRPC_OP_COMPLETE);
grpc_server_destroy(f->server);
f->server = NULL;
}
static void shutdown_client(grpc_end2end_test_fixture *f) {
if (!f->client) return;
grpc_channel_destroy(f->client);
f->client = NULL;
}
static void end_test(grpc_end2end_test_fixture *f) {
shutdown_server(f);
shutdown_client(f);
grpc_completion_queue_shutdown(f->cq);
drain_cq(f->cq);
grpc_completion_queue_destroy(f->cq);
grpc_completion_queue_destroy(f->shutdown_cq);
}
/* Cancel after accept, no payload */
static void test_cancel_after_round_trip(grpc_end2end_test_config config,
cancellation_mode mode,
bool use_service_config) {
grpc_op ops[6];
grpc_op *op;
grpc_call *c;
grpc_call *s;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
grpc_call_details call_details;
grpc_status_code status;
grpc_call_error error;
grpc_slice details;
grpc_byte_buffer *request_payload_recv = NULL;
grpc_byte_buffer *response_payload_recv = NULL;
grpc_slice request_payload_slice =
grpc_slice_from_copied_string("hello world");
grpc_slice response_payload_slice =
grpc_slice_from_copied_string("hello you");
grpc_byte_buffer *request_payload =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
int was_cancelled = 2;
grpc_channel_args *args = NULL;
if (use_service_config) {
grpc_arg arg;
arg.type = GRPC_ARG_STRING;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.string =
"{\n"
" \"methodConfig\": [ {\n"
" \"name\": [\n"
" { \"service\": \"service\", \"method\": \"method\" }\n"
" ],\n"
" \"timeout\": \"5s\"\n"
" } ]\n"
"}";
args = grpc_channel_args_copy_and_add(args, &arg, 1);
}
grpc_end2end_test_fixture f =
begin_test(config, "cancel_after_round_trip", args, NULL);
cq_verifier *cqv = cq_verifier_create(f.cq);
gpr_timespec deadline = use_service_config
? gpr_inf_future(GPR_CLOCK_MONOTONIC)
: five_seconds_from_now();
c = grpc_channel_create_call(
f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
grpc_slice_from_static_string("/service/method"),
get_host_override_slice("foo.test.google.fr:1234", config), deadline,
NULL);
GPR_ASSERT(c);
grpc_metadata_array_init(&initial_metadata_recv);
grpc_metadata_array_init(&trailing_metadata_recv);
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
cq_verify(cqv);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &request_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = response_payload;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
request_payload_recv = NULL;
response_payload_recv = NULL;
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL));
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = response_payload;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
cq_verify(cqv);
GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL);
GPR_ASSERT(was_cancelled == 1);
grpc_metadata_array_destroy(&initial_metadata_recv);
grpc_metadata_array_destroy(&trailing_metadata_recv);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(response_payload);
grpc_byte_buffer_destroy(request_payload_recv);
grpc_byte_buffer_destroy(response_payload_recv);
grpc_slice_unref(details);
grpc_call_unref(c);
grpc_call_unref(s);
if (args != NULL) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_channel_args_destroy(&exec_ctx, args);
grpc_exec_ctx_finish(&exec_ctx);
}
cq_verifier_destroy(cqv);
end_test(&f);
config.tear_down_data(&f);
}
void cancel_after_round_trip(grpc_end2end_test_config config) {
unsigned i;
for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) {
test_cancel_after_round_trip(config, cancellation_modes[i],
false /* use_service_config */);
if (config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL &&
cancellation_modes[i].expect_status == GRPC_STATUS_DEADLINE_EXCEEDED) {
test_cancel_after_round_trip(config, cancellation_modes[i],
true /* use_service_config */);
}
}
}
void cancel_after_round_trip_pre_init(void) {}

@ -274,11 +274,12 @@ static void request_with_payload_template(
grpc_compression_algorithm expected_algorithm_from_client,
grpc_compression_algorithm expected_algorithm_from_server,
grpc_metadata *client_init_metadata, bool set_server_level,
grpc_compression_level server_compression_level) {
grpc_compression_level server_compression_level,
bool send_message_before_initial_metadata) {
grpc_call *c;
grpc_call *s;
grpc_slice request_payload_slice;
grpc_byte_buffer *request_payload;
grpc_byte_buffer *request_payload = NULL;
grpc_channel_args *client_args;
grpc_channel_args *server_args;
grpc_end2end_test_fixture f;
@ -330,6 +331,20 @@ static void request_with_payload_template(
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
if (send_message_before_initial_metadata) {
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = client_send_flags_bitmask;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(2), true);
}
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
@ -394,23 +409,21 @@ static void request_with_payload_template(
GPR_ASSERT(GRPC_CALL_OK == error);
for (int i = 0; i < 2; i++) {
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = client_send_flags_bitmask;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
if (i > 0 || !send_message_before_initial_metadata) {
request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = client_send_flags_bitmask;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
}
memset(ops, 0, sizeof(ops));
op = ops;
@ -421,6 +434,7 @@ static void request_with_payload_template(
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
cq_verify(cqv);
@ -438,8 +452,19 @@ static void request_with_payload_template(
op++;
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(103), 1);
CQ_EXPECT_COMPLETION(cqv, tag(2), 1);
CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
cq_verify(cqv);
GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW);
@ -469,7 +494,7 @@ static void request_with_payload_template(
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL);
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
memset(ops, 0, sizeof(ops));
@ -486,7 +511,7 @@ static void request_with_payload_template(
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
CQ_EXPECT_COMPLETION(cqv, tag(3), 1);
CQ_EXPECT_COMPLETION(cqv, tag(4), 1);
CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
CQ_EXPECT_COMPLETION(cqv, tag(104), 1);
cq_verify(cqv);
@ -526,7 +551,7 @@ static void test_invoke_request_with_exceptionally_uncompressed_payload(
config, "test_invoke_request_with_exceptionally_uncompressed_payload",
GRPC_WRITE_NO_COMPRESS, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, NULL, false,
/* ignored */ GRPC_COMPRESS_LEVEL_NONE);
/* ignored */ GRPC_COMPRESS_LEVEL_NONE, false);
}
static void test_invoke_request_with_uncompressed_payload(
@ -534,7 +559,8 @@ static void test_invoke_request_with_uncompressed_payload(
request_with_payload_template(
config, "test_invoke_request_with_uncompressed_payload", 0,
GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE,
GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE);
GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE,
false);
}
static void test_invoke_request_with_compressed_payload(
@ -542,7 +568,17 @@ static void test_invoke_request_with_compressed_payload(
request_with_payload_template(
config, "test_invoke_request_with_compressed_payload", 0,
GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE);
GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE,
false);
}
static void test_invoke_request_with_send_message_before_initial_metadata(
grpc_end2end_test_config config) {
request_with_payload_template(
config, "test_invoke_request_with_compressed_payload", 0,
GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE,
true);
}
static void test_invoke_request_with_server_level(
@ -550,7 +586,7 @@ static void test_invoke_request_with_server_level(
request_with_payload_template(
config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE,
GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */,
NULL, true, GRPC_COMPRESS_LEVEL_HIGH);
NULL, true, GRPC_COMPRESS_LEVEL_HIGH, false);
}
static void test_invoke_request_with_compressed_payload_md_override(
@ -574,21 +610,21 @@ static void test_invoke_request_with_compressed_payload_md_override(
config, "test_invoke_request_with_compressed_payload_md_override_1", 0,
GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_NONE, &gzip_compression_override, false,
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE);
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false);
/* Channel default DEFLATE, call override to GZIP */
request_with_payload_template(
config, "test_invoke_request_with_compressed_payload_md_override_2", 0,
GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP,
GRPC_COMPRESS_NONE, &gzip_compression_override, false,
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE);
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false);
/* Channel default DEFLATE, call override to NONE (aka IDENTITY) */
request_with_payload_template(
config, "test_invoke_request_with_compressed_payload_md_override_3", 0,
GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE,
GRPC_COMPRESS_NONE, &identity_compression_override, false,
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE);
/*ignored*/ GRPC_COMPRESS_LEVEL_NONE, false);
}
static void test_invoke_request_with_disabled_algorithm(
@ -602,6 +638,7 @@ void compressed_payload(grpc_end2end_test_config config) {
test_invoke_request_with_exceptionally_uncompressed_payload(config);
test_invoke_request_with_uncompressed_payload(config);
test_invoke_request_with_compressed_payload(config);
test_invoke_request_with_send_message_before_initial_metadata(config);
test_invoke_request_with_server_level(config);
test_invoke_request_with_compressed_payload_md_override(config);
test_invoke_request_with_disabled_algorithm(config);

@ -95,7 +95,8 @@ static void verify(grpc_exec_ctx *exec_ctx, size_t window_available, bool eof,
.max_frame_size = 16384,
.stats = &stats,
};
grpc_chttp2_encode_header(exec_ctx, &g_compressor, &b, &hopt, &output);
grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt,
&output);
merged = grpc_slice_merge(output.slices, output.count);
grpc_slice_buffer_destroy_internal(exec_ctx, &output);
grpc_metadata_batch_destroy(exec_ctx, &b);
@ -213,7 +214,8 @@ static void verify_table_size_change_match_elem_size(grpc_exec_ctx *exec_ctx,
.use_true_binary_metadata = false,
.max_frame_size = 16384,
.stats = &stats};
grpc_chttp2_encode_header(exec_ctx, &g_compressor, &b, &hopt, &output);
grpc_chttp2_encode_header(exec_ctx, &g_compressor, NULL, 0, &b, &hopt,
&output);
grpc_slice_buffer_destroy_internal(exec_ctx, &output);
grpc_metadata_batch_destroy(exec_ctx, &b);

@ -40,6 +40,37 @@ TEST(AlarmTest, RegularExpiry) {
EXPECT_EQ(junk, output_tag);
}
TEST(AlarmTest, MoveConstructor) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
Alarm first(&cq, grpc_timeout_seconds_to_deadline(1), junk);
Alarm second(std::move(first));
void* output_tag;
bool ok;
const CompletionQueue::NextStatus status = cq.AsyncNext(
(void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
EXPECT_TRUE(ok);
EXPECT_EQ(junk, output_tag);
}
TEST(AlarmTest, MoveAssignment) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);
Alarm first(&cq, grpc_timeout_seconds_to_deadline(1), junk);
Alarm second(std::move(first));
first = std::move(second);
void* output_tag;
bool ok;
const CompletionQueue::NextStatus status = cq.AsyncNext(
(void**)&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
EXPECT_TRUE(ok);
EXPECT_EQ(junk, output_tag);
}
TEST(AlarmTest, RegularExpiryChrono) {
CompletionQueue cq;
void* junk = reinterpret_cast<void*>(1618033);

@ -28,7 +28,7 @@ class MyChannelData : public ChannelData {
public:
MyChannelData() {}
grpc_error* Init(grpc_exec_ctx* exec_ctx,
grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem,
grpc_channel_element_args* args) override {
(void)args->channel_args; // Make sure field is available.
return GRPC_ERROR_NONE;
@ -39,7 +39,7 @@ class MyCallData : public CallData {
public:
MyCallData() {}
grpc_error* Init(grpc_exec_ctx* exec_ctx, ChannelData* channel_data,
grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_element_args* args) override {
(void)args->path; // Make sure field is available.
return GRPC_ERROR_NONE;

@ -97,9 +97,12 @@ class ClientLbEnd2endTest : public ::testing::Test {
}
}
void StartServers(int num_servers) {
for (int i = 0; i < num_servers; ++i) {
servers_.emplace_back(new ServerData(server_host_));
void StartServers(size_t num_servers,
std::vector<int> ports = std::vector<int>()) {
for (size_t i = 0; i < num_servers; ++i) {
int port = 0;
if (ports.size() == num_servers) port = ports[i];
servers_.emplace_back(new ServerData(server_host_, port));
}
}
@ -146,14 +149,18 @@ class ClientLbEnd2endTest : public ::testing::Test {
stub_ = grpc::testing::EchoTestService::NewStub(channel_);
}
void SendRpc() {
void SendRpc(bool expect_ok = true) {
EchoRequest request;
EchoResponse response;
request.set_message("Live long and prosper.");
ClientContext context;
Status status = stub_->Echo(&context, request, &response);
EXPECT_TRUE(status.ok());
EXPECT_EQ(response.message(), request.message());
if (expect_ok) {
EXPECT_TRUE(status.ok());
EXPECT_EQ(response.message(), request.message());
} else {
EXPECT_FALSE(status.ok());
}
}
struct ServerData {
@ -162,8 +169,8 @@ class ClientLbEnd2endTest : public ::testing::Test {
MyTestServiceImpl service_;
std::unique_ptr<std::thread> thread_;
explicit ServerData(const grpc::string& server_host) {
port_ = grpc_pick_unused_port_or_die();
explicit ServerData(const grpc::string& server_host, int port = 0) {
port_ = port > 0 ? port : grpc_pick_unused_port_or_die();
gpr_log(GPR_INFO, "starting server on port %d", port_);
std::mutex mu;
std::condition_variable cond;
@ -187,9 +194,9 @@ class ClientLbEnd2endTest : public ::testing::Test {
cond->notify_one();
}
void Shutdown() {
void Shutdown(bool join = true) {
server_->Shutdown();
thread_->join();
if (join) thread_->join();
}
};
@ -456,6 +463,39 @@ TEST_F(ClientLbEnd2endTest, RoundRobinManyUpdates) {
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
}
TEST_F(ClientLbEnd2endTest, RoundRobinReconnect) {
// Start servers and send one RPC per server.
const int kNumServers = 1;
std::vector<int> ports;
ports.push_back(grpc_pick_unused_port_or_die());
StartServers(kNumServers, ports);
ResetStub("round_robin");
SetNextResolution(ports);
// Send one RPC per backend and make sure they are used in order.
// Note: This relies on the fact that the subchannels are reported in
// state READY in the order in which the addresses are specified,
// which is only true because the backends are all local.
for (size_t i = 0; i < servers_.size(); ++i) {
SendRpc();
EXPECT_EQ(1, servers_[i]->service_.request_count()) << "for backend #" << i;
}
// Check LB policy name for the channel.
EXPECT_EQ("round_robin", channel_->GetLoadBalancingPolicyName());
// Kill all servers
for (size_t i = 0; i < servers_.size(); ++i) {
servers_[i]->Shutdown(false);
}
// Client request should fail.
SendRpc(false);
// Bring servers back up on the same port (we aren't recreating the channel).
StartServers(kNumServers, ports);
// Client request should succeed.
SendRpc();
}
} // namespace
} // namespace testing
} // namespace grpc

@ -100,7 +100,8 @@ int GetCallCounterValue() {
class ChannelDataImpl : public ChannelData {
public:
grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_channel_element_args* args) {
grpc_error* Init(grpc_exec_ctx* exec_ctx, grpc_channel_element* elem,
grpc_channel_element_args* args) {
IncrementConnectionCounter();
return GRPC_ERROR_NONE;
}

@ -82,7 +82,7 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State &state) {
(size_t)state.range(1),
&stats,
};
grpc_chttp2_encode_header(&exec_ctx, &c, &b, &hopt, &outbuf);
grpc_chttp2_encode_header(&exec_ctx, &c, NULL, 0, &b, &hopt, &outbuf);
if (!logged_representative_output && state.iterations() > 3) {
logged_representative_output = true;
for (size_t i = 0; i < outbuf.count; i++) {

@ -78,6 +78,7 @@ cc_library(
"cares/ares_version.h",
"cares/bitncmp.h",
"cares/config-win32.h",
"cares/nameser.h",
"cares/setup_once.h",
] + select({
":darwin": ["config_darwin/ares_config.h"],

@ -19,15 +19,16 @@ set -ex
cd "$(dirname "$0")/../.."
DIRS=(
'src/python/grpcio/grpc'
'src/python/grpcio_reflection/grpc_reflection'
'src/python/grpcio_health_checking/grpc_health'
'src/python/grpcio/grpc'
'src/python/grpcio_health_checking/grpc_health'
'src/python/grpcio_reflection/grpc_reflection'
)
VIRTUALENV=python_pylint_venv
virtualenv $VIRTUALENV
PYTHON=$(realpath $VIRTUALENV/bin/python)
$PYTHON -m pip install --upgrade pip
$PYTHON -m pip install pylint==1.6.5
for dir in "${DIRS[@]}"; do

@ -0,0 +1,76 @@
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM debian:jessie
# Install JDK 8 and Git
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \
echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
RUN apt-get update && apt-get -y install \
git \
libapr1 \
oracle-java8-installer \
&& \
apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
ENV PATH $PATH:$JAVA_HOME/bin
# Install protobuf
RUN apt-get update && apt-get install -y \
autoconf \
build-essential \
curl \
gcc \
libtool \
unzip \
&& \
apt-get clean
WORKDIR /
RUN git clone https://github.com/google/protobuf.git
WORKDIR /protobuf
RUN git checkout v3.3.1 && \
./autogen.sh && \
./configure && \
make && \
make check && \
make install
# Install gcloud command line tools
ENV CLOUD_SDK_REPO "cloud-sdk-jessie"
RUN echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && \
gcloud config set component_manager/disable_update_check true
# Download and install grpc-java
WORKDIR /
RUN git clone https://github.com/grpc/grpc-java.git
WORKDIR /grpc-java
RUN ./gradlew install
# Setup the Android SDK licenses
ENV ANDROID_HOME "/grpc-java/android-interop-testing/.android"
RUN mkdir -p "${ANDROID_HOME}/licenses"
RUN echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "${ANDROID_HOME}/licenses/android-sdk-license"
RUN echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "${ANDROID_HOME}/licenses/android-sdk-preview-license"
# Build the Android interop apks
WORKDIR /grpc-java/android-interop-testing
RUN ../gradlew assembleDebug
RUN ../gradlew assembleDebugAndroidTest
# Define the default command.
CMD ["bash"]

@ -70,10 +70,11 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0
RUN touch .profile
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
# Install all versions of node that we want to test
RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm alias default 4"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 6 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 8 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm alias default 8"
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++

@ -81,10 +81,11 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c
RUN touch .profile
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
# Install all versions of node that we want to test
RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm alias default 4"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 6 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 8 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm alias default 8"
#=================
# PHP dependencies

@ -85,10 +85,11 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0
RUN touch .profile
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash
# Install all versions of node that we want to test
RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache"
RUN /bin/bash -l -c "nvm alias default 4"
RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 6 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm install 8 && npm config set cache /tmp/npm-cache && npm install -g npm"
RUN /bin/bash -l -c "nvm alias default 8"
# Prepare ccache
RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
RUN ln -s /usr/bin/ccache /usr/local/bin/g++

@ -116,6 +116,33 @@ def create_table2(big_query, project_id, dataset_id, table_id, fields_schema,
return is_success
def patch_table(big_query, project_id, dataset_id, table_id, fields_schema):
is_success = True
body = {
'schema': {
'fields': fields_schema
},
'tableReference': {
'datasetId': dataset_id,
'projectId': project_id,
'tableId': table_id
}
}
try:
table_req = big_query.tables().patch(projectId=project_id,
datasetId=dataset_id,
tableId=table_id,
body=body)
res = table_req.execute(num_retries=NUM_RETRIES)
print 'Successfully patched %s "%s"' % (res['kind'], res['id'])
except HttpError as http_error:
print 'Error in creating table: %s. Err: %s' % (table_id, http_error)
is_success = False
return is_success
def insert_rows(big_query, project_id, dataset_id, table_id, rows_list):
is_success = True
body = {'rows': rows_list}

@ -1,52 +0,0 @@
# Copyright 2016 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM ubuntu:14.04
RUN apt-get update && \
apt-get install -y \
git build-essential \
pkg-config flex \
bison \
libkrb5-dev \
libsasl2-dev \
libnuma-dev \
pkg-config \
libssl-dev \
autoconf libtool \
cmake \
libiberty-dev \
g++ unzip \
curl make automake libtool libboost-dev
# Configure git
RUN git config --global user.name "Jenkins" && \
git config --global user.email "jenkins@grpc"
# Clone gRPC
RUN git clone https://github.com/grpc/grpc
# Update Submodules
RUN cd grpc && git submodule update --init
# Install protobuf
RUN cd grpc/third_party/protobuf && ./autogen.sh && ./configure && \
make -j && make check -j && make install && ldconfig
# Install gRPC
RUN cd grpc && make -j && make install
# Install thrift
RUN cd grpc/third_party/thrift && git am --signoff < ../../tools/grift/grpc_plugins_generator.patch && \
./bootstrap.sh && ./configure && make -j && make install

@ -1,24 +0,0 @@
# Documentation
grift is integration of [Apache Thrift](https://github.com/apache/thrift.git) Serializer with gRPC.
This integration allows you to use grpc to send thrift messages in C++ and java.
grift uses Compact Protocol to serialize thrift messages.
## generating grpc plugins for thrift services
### C++
```sh
$ thrift --gen cpp <thrift-file>
```
### Java
```sh
$ thrift --gen java <thrift-file>
```
# Installation
Before Installing thrift make sure to apply this [patch](grpc_plugins_generator.patch) to third_party/thrift.
Go to third_party/thrift and follow the [INSTALLATION](https://github.com/apache/thrift.git) instructions to install thrift with commit id bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c.

File diff suppressed because it is too large Load Diff

@ -15,53 +15,37 @@
# Source this rc script to prepare the environment for macos builds
# TODO(jtattermusch): remove all deps once installed on MacOS workers
ulimit -n 1000
# brew and C++ deps
yes | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install autoconf automake libtool ccache cmake gflags gpg wget
# show current limits
ulimit -a
# TODO(jtattermusch): hkp://keys.gnupg.net fails with "No route to host"
gpg --keyserver hkp://193.164.133.100 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://get.rvm.io | sudo bash -s stable
# add ourselves to rvm group to prevent later "access denied" errors.
sudo dseditgroup -o edit -a `whoami` -t user rvm
set +ex
source /etc/profile.d/rvm.sh
rvm install ruby-2.3
gem install bundler
# required to build protobuf
brew install gflags
set +ex # rvm script is very verbose and exits with errorcode
source $HOME/.rvm/scripts/rvm
set -e # rvm commands are very verbose
rvm install ruby-2.4
rvm osx-ssl-certs status all
rvm osx-ssl-certs update all
set -ex
gem install bundler
# cocoapods
gem install cocoapods --version 1.0.0
export LANG=en_US.UTF-8
gem install cocoapods
pod repo update # needed by python
# python
wget -q https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
brew install coreutils # we need grealpath
sudo pip install virtualenv
sudo pip install -U six tox setuptools
# TODO(jtattermusch): install python3
# mono
wget -q https://download.mono-project.com/archive/5.0.1/macos-10-universal/MonoFramework-MDK-5.0.1.1.macos10.xamarin.universal.pkg
sudo installer -pkg MonoFramework-MDK-5.0.1.1.macos10.xamarin.universal.pkg -target /
ln -s /Library/Frameworks/Mono.framework/Versions/Current/bin/mono /usr/local/bin/mono
# dotnet SDK
brew install openssl
wget -q https://go.microsoft.com/fwlink/?linkid=843444 -O dotnet-dev-osx-x64.1.0.1.pkg
sudo installer -pkg dotnet-dev-osx-x64.1.0.1.pkg -target /
ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/dotnet
dotnet --version # bootstrap dotnet SDK
# nvm
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash
# TODO(jtattermusch): install node if needed
# python 3.4
wget -q https://www.python.org/ftp/python/3.4.4/python-3.4.4-macosx10.6.pkg
sudo installer -pkg python-3.4.4-macosx10.6.pkg -target /
git submodule update --init

@ -18,6 +18,31 @@ set -ex
# change to grpc repo root
cd $(dirname $0)/../../..
git submodule update --init
source tools/internal_ci/helper_scripts/prepare_build_macos_rc
# python 3.5
wget -q https://www.python.org/ftp/python/3.5.2/python-3.5.2-macosx10.6.pkg
sudo installer -pkg python-3.5.2-macosx10.6.pkg -target /
# install cython for all python versions
python2.7 -m pip install cython setuptools wheel
python3.4 -m pip install cython setuptools wheel
python3.5 -m pip install cython setuptools wheel
python3.6 -m pip install cython setuptools wheel
# node-gyp (needed for node artifacts)
npm install -g node-gyp
# php dependencies: pecl
curl -O http://pear.php.net/go-pear.phar
sudo php -d detect_unicode=0 go-pear.phar
# needed to build ruby artifacts
gem install rake-compiler
wget https://raw.githubusercontent.com/grpc/grpc/master/tools/distrib/build_ruby_environment_macos.sh
bash build_ruby_environment_macos.sh
gem install rubygems-update
update_rubygems
tools/run_tests/task_runner.py -f artifact macos

@ -20,7 +20,7 @@ cd $(dirname $0)/../../..
source tools/internal_ci/helper_scripts/prepare_build_macos_rc
tools/run_tests/run_tests_matrix.py -f basictests macos --internal_ci || FAILED="true"
tools/run_tests/run_tests_matrix.py -f basictests macos --internal_ci -j 2 --inner_jobs 4 || FAILED="true"
# kill port_server.py to prevent the build from hanging
ps aux | grep port_server\\.py | awk '{print $2}' | xargs kill -9

@ -16,7 +16,7 @@
NODE_TARGET_ARCH=$1
source ~/.nvm/nvm.sh
nvm use 4
nvm use 8
set -ex
cd $(dirname $0)/../../..

@ -15,7 +15,7 @@
source ~/.nvm/nvm.sh
nvm use 4
nvm use 8
set -ex
cd $(dirname $0)/../../..

@ -7209,6 +7209,7 @@
"test/core/end2end/tests/cancel_after_accept.c",
"test/core/end2end/tests/cancel_after_client_done.c",
"test/core/end2end/tests/cancel_after_invoke.c",
"test/core/end2end/tests/cancel_after_round_trip.c",
"test/core/end2end/tests/cancel_before_invoke.c",
"test/core/end2end/tests/cancel_in_a_vacuum.c",
"test/core/end2end/tests/cancel_test_helpers.h",
@ -7285,6 +7286,7 @@
"test/core/end2end/tests/cancel_after_accept.c",
"test/core/end2end/tests/cancel_after_client_done.c",
"test/core/end2end/tests/cancel_after_invoke.c",
"test/core/end2end/tests/cancel_after_round_trip.c",
"test/core/end2end/tests/cancel_before_invoke.c",
"test/core/end2end/tests/cancel_in_a_vacuum.c",
"test/core/end2end/tests/cancel_test_helpers.h",

File diff suppressed because it is too large Load Diff

@ -17,7 +17,7 @@
ELECTRON_VERSION=$1
source ~/.nvm/nvm.sh
nvm use 6
nvm use 8
set -ex
# change to grpc repo root
@ -28,4 +28,5 @@ export npm_config_disturl=https://atom.io/download/atom-shell
export npm_config_runtime=electron
export npm_config_build_from_source=true
mkdir -p ~/.electron-gyp
HOME=~/.electron-gyp npm update --prefer-online
HOME=~/.electron-gyp npm install --unsafe-perm

@ -20,9 +20,6 @@ source ~/.nvm/nvm.sh
nvm install $NODE_VERSION
set -ex
# Update npm to at least version 5
npm update -g npm
export GRPC_CONFIG=${CONFIG:-opt}
npm update --prefer-online

@ -16,7 +16,7 @@
ELECTRON_VERSION=$1
nvm install 6
nvm install 8
set -ex
npm install xvfb-maybe

@ -15,7 +15,7 @@
source ~/.nvm/nvm.sh
nvm use 6
nvm use 8
set -ex
# change to grpc repo root

@ -0,0 +1,36 @@
#!/bin/bash
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Helper that runs inside the docker container and builds the APKs and
# invokes Firebase Test Lab via gcloud.
SERVICE_KEY=$1
gcloud auth activate-service-account --key-file=$SERVICE_KEY || exit 1
gcloud config set project grpc-testing || exit 1
rm -rf grpc-java
git clone https://github.com/grpc/grpc-java.git
cd grpc-java
./gradlew install || exit 1
cd android-interop-testing
../gradlew assembleDebug
../gradlew assembleDebugAndroidTest
gcloud firebase test android run \
--type instrumentation \
--app app/build/outputs/apk/app-debug.apk \
--test app/build/outputs/apk/app-debug-androidTest.apk \
--device model=Nexus6,version=21,locale=en,orientation=portrait

@ -0,0 +1,30 @@
#!/bin/bash
# Copyright 2017 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds the gRPC Android instrumented interop tests inside a docker container
# and runs them on Firebase Test Lab
DOCKERFILE=tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
DOCKER_TAG=android_interop_test
SERVICE_KEY=~/android-interops-service-key.json
HELPER=$(pwd)/tools/run_tests/interop/android/android_interop_helper.sh
docker build -t $DOCKER_TAG -f $DOCKERFILE .
docker run --interactive --rm \
--volume="$SERVICE_KEY":/service-key.json:ro \
--volume="$HELPER":/android_interop_helper.sh:ro \
$DOCKER_TAG \
/bin/bash -c "/android_interop_helper.sh /service-key.json"

@ -0,0 +1,55 @@
#!/usr/bin/env python
# Copyright 2016 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Use to patch schema of existing scenario results tables (after adding fields).
from __future__ import print_function
import argparse
import calendar
import json
import os
import sys
import time
import uuid
gcp_utils_dir = os.path.abspath(os.path.join(
os.path.dirname(__file__), '../../gcp/utils'))
sys.path.append(gcp_utils_dir)
import big_query_utils
_PROJECT_ID='grpc-testing'
def _patch_results_table(dataset_id, table_id):
bq = big_query_utils.create_big_query()
with open(os.path.dirname(__file__) + '/scenario_result_schema.json', 'r') as f:
table_schema = json.loads(f.read())
desc = 'Results of performance benchmarks.'
return big_query_utils.patch_table(bq, _PROJECT_ID, dataset_id,
table_id, table_schema)
argp = argparse.ArgumentParser(description='Patch schema of scenario results table.')
argp.add_argument('--bq_result_table', required=True, default=None, type=str,
help='Bigquery "dataset.table" to patch.')
args = argp.parse_args()
dataset_id, table_id = args.bq_result_table.split('.', 2)
_patch_results_table(dataset_id, table_id)
print('Successfully patched schema of %s.\n' % args.bq_result_table)

@ -14,7 +14,7 @@
# limitations under the License.
source ~/.nvm/nvm.sh
nvm use 7
nvm use 8
set -ex

@ -107,6 +107,11 @@
"name": "timeSystem",
"type": "FLOAT",
"mode": "NULLABLE"
},
{
"name": "cqPollCount",
"type": "INTEGER",
"mode": "NULLABLE"
}
]
},
@ -129,6 +134,11 @@
"name": "timeSystem",
"type": "FLOAT",
"mode": "NULLABLE"
},
{
"name": "cqPollCount",
"type": "INTEGER",
"mode": "NULLABLE"
}
]
},
@ -196,6 +206,16 @@
"name": "latency999",
"type": "FLOAT",
"mode": "NULLABLE"
},
{
"name": "clientPollsPerRequest",
"type": "FLOAT",
"mode": "NULLABLE"
},
{
"name": "serverPollsPerRequest",
"type": "FLOAT",
"mode": "NULLABLE"
}
]
},

@ -49,6 +49,7 @@ _RESULTS_SCHEMA = [
('elapsed_time', 'FLOAT', 'How long test took to run'),
('cpu_estimated', 'FLOAT', 'Estimated CPU usage of test'),
('cpu_measured', 'FLOAT', 'Actual CPU usage of test'),
('return_code', 'INTEGER', 'Exit code of test'),
]
@ -96,6 +97,7 @@ def upload_results_to_bq(resultset, bq_table, args, platform):
test_results['language'] = args.language[0]
test_results['platform'] = platform
test_results['result'] = result.state
test_results['return_code'] = result.returncode
test_results['test_name'] = shortname
test_results['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S')

@ -81,7 +81,7 @@ def get_flaky_tests(limit=None):
FROM
[grpc-testing:jenkins_test_results.aggregate_results]
WHERE
timestamp >= DATE_ADD(DATE(CURRENT_TIMESTAMP()), -1, "WEEK")
timestamp >= DATE_ADD(CURRENT_DATE(), -1, "WEEK")
AND NOT REGEXP_MATCH(job_name, '.*portability.*')
GROUP BY
test_name

@ -169,6 +169,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_invoke.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_round_trip.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_before_invoke.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_in_a_vacuum.c">

@ -28,6 +28,9 @@
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_invoke.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_round_trip.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_before_invoke.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>

@ -171,6 +171,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_invoke.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_round_trip.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_before_invoke.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_in_a_vacuum.c">

@ -31,6 +31,9 @@
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_invoke.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_after_round_trip.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\cancel_before_invoke.c">
<Filter>test\core\end2end\tests</Filter>
</ClCompile>

Loading…
Cancel
Save