Merge branch 'master' into failhijackedrecv

pull/17179/head
Yash Tibrewal 6 years ago
commit b05ca9697b
  1. 2
      CMakeLists.txt
  2. 6
      Rakefile
  3. 5
      doc/python/sphinx/grpc.rst
  4. 2
      gRPC-Core.podspec
  5. 30
      include/grpcpp/impl/codegen/call_op_set.h
  6. 8
      include/grpcpp/impl/codegen/client_callback.h
  7. 2
      include/grpcpp/impl/codegen/client_unary_call.h
  8. 8
      include/grpcpp/impl/codegen/interceptor.h
  9. 20
      include/grpcpp/impl/codegen/interceptor_common.h
  10. 4
      include/grpcpp/impl/codegen/method_handler_impl.h
  11. 12
      include/grpcpp/impl/codegen/server_callback.h
  12. 10
      include/grpcpp/impl/codegen/sync_stream.h
  13. 2
      setup.py
  14. 1
      src/core/lib/iomgr/resource_quota.cc
  15. 94
      src/core/lib/iomgr/tcp_windows.cc
  16. 104
      src/core/lib/surface/server.cc
  17. 1
      src/core/lib/transport/metadata.cc
  18. 5
      src/python/grpcio/grpc/__init__.py
  19. 13
      src/python/grpcio/grpc/_cython/_cygrpc/arguments.pxd.pxi
  20. 37
      src/python/grpcio/grpc/_cython/_cygrpc/arguments.pyx.pxi
  21. 9
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
  22. 1
      src/python/grpcio/grpc/_cython/_cygrpc/server.pxd.pxi
  23. 8
      src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
  24. 80
      src/python/grpcio_health_checking/grpc_health/v1/health.py
  25. 1
      src/python/grpcio_tests/commands.py
  26. 1
      src/python/grpcio_tests/tests/health_check/BUILD.bazel
  27. 179
      src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
  28. 1
      src/python/grpcio_tests/tests/tests.json
  29. 1
      src/python/grpcio_tests/tests/unit/BUILD.bazel
  30. 30
      src/python/grpcio_tests/tests/unit/_version_test.py
  31. 2
      templates/CMakeLists.txt.template
  32. 2
      templates/gRPC-Core.podspec.template
  33. 14
      templates/tools/dockerfile/ruby_deps.include
  34. 9
      test/core/end2end/fixtures/h2_full+trace.cc
  35. 9
      test/core/end2end/fixtures/h2_sockpair+trace.cc
  36. 6
      test/core/memory_usage/BUILD
  37. 14
      test/cpp/end2end/client_interceptors_end2end_test.cc
  38. 36
      test/cpp/end2end/server_interceptors_end2end_test.cc
  39. 3
      third_party/rake-compiler-dock/Dockerfile
  40. 2
      tools/distrib/build_ruby_environment_macos.sh
  41. 15
      tools/dockerfile/distribtest/ruby_centos6_x64/Dockerfile
  42. 18
      tools/dockerfile/distribtest/ruby_centos7_x64/Dockerfile
  43. 21
      tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
  44. 19
      tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
  45. 40
      tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_2/Dockerfile
  46. 41
      tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_3/Dockerfile
  47. 40
      tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_4/Dockerfile
  48. 40
      tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_5/Dockerfile
  49. 14
      tools/dockerfile/distribtest/ruby_jessie_x64_ruby_2_6/Dockerfile
  50. 4
      tools/dockerfile/grpc_artifact_linux_x64/Dockerfile
  51. 4
      tools/dockerfile/grpc_artifact_linux_x86/Dockerfile
  52. 14
      tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
  53. 2
      tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh
  54. 14
      tools/dockerfile/test/ruby_jessie_x64/Dockerfile
  55. 2
      tools/internal_ci/helper_scripts/prepare_build_macos_rc
  56. 2
      tools/run_tests/artifacts/build_artifact_ruby.sh
  57. 8
      tools/run_tests/artifacts/distribtest_targets.py

@ -94,7 +94,7 @@ endif()
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
add_definitions(-DPB_FIELD_16BIT)
add_definitions(-DPB_FIELD_32BIT)
if (MSVC)
include(cmake/msvc_static_runtime.cmake)

@ -105,7 +105,7 @@ task 'dlls' do
env_comp = "CC=#{opt[:cross]}-gcc "
env_comp += "CXX=#{opt[:cross]}-g++ "
env_comp += "LD=#{opt[:cross]}-gcc "
docker_for_windows "gem update --system --no-ri --no-doc && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
docker_for_windows "gem update --system --no-document && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
end
end
@ -124,10 +124,10 @@ task 'gem:native' do
"invoked on macos with ruby #{RUBY_VERSION}. The ruby macos artifact " \
"build should be running on ruby 2.5."
end
system "rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
system "rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
else
Rake::Task['dlls'].execute
docker_for_windows "gem update --system --no-ri --no-doc && bundle && rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
docker_for_windows "gem update --system --no-document && bundle && rake cross native gem RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0:2.2.2 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
end
end

@ -19,6 +19,11 @@ Go to `gRPC Python Examples <https://github.com/grpc/grpc/tree/master/examples/p
Module Contents
---------------
Version
^^^^^^^
The version string is available as :code:`grpc.__version__`.
Create Client
^^^^^^^^^^^^^

@ -93,7 +93,7 @@ Pod::Spec.new do |s|
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_32BIT'
s.libraries = 'c++'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its

@ -303,6 +303,18 @@ class CallOpSendMessage {
template <class M>
Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
/// Send \a message using \a options for the write. The \a options are cleared
/// after use. This form of SendMessage allows gRPC to reference \a message
/// beyond the lifetime of SendMessage.
template <class M>
Status SendMessagePtr(const M* message,
WriteOptions options) GRPC_MUST_USE_RESULT;
/// This form of SendMessage allows gRPC to reference \a message beyond the
/// lifetime of SendMessage.
template <class M>
Status SendMessagePtr(const M* message) GRPC_MUST_USE_RESULT;
protected:
void AddOp(grpc_op* ops, size_t* nops) {
if (!send_buf_.Valid() || hijacked_) return;
@ -321,14 +333,14 @@ class CallOpSendMessage {
if (!send_buf_.Valid()) return;
interceptor_methods->AddInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE);
interceptor_methods->SetSendMessage(&send_buf_);
interceptor_methods->SetSendMessage(&send_buf_, msg_);
}
void SetFinishInterceptionHookPoint(
InterceptorBatchMethodsImpl* interceptor_methods) {
// The contents of the SendMessage value that was previously set
// has had its references stolen by core's operations
interceptor_methods->SetSendMessage(nullptr);
interceptor_methods->SetSendMessage(nullptr, nullptr);
}
void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
@ -336,6 +348,7 @@ class CallOpSendMessage {
}
private:
const void* msg_ = nullptr; // The original non-serialized message
bool hijacked_ = false;
ByteBuffer send_buf_;
WriteOptions write_options_;
@ -362,6 +375,19 @@ Status CallOpSendMessage::SendMessage(const M& message) {
return SendMessage(message, WriteOptions());
}
template <class M>
Status CallOpSendMessage::SendMessagePtr(const M* message,
WriteOptions options) {
msg_ = message;
return SendMessage(*message, options);
}
template <class M>
Status CallOpSendMessage::SendMessagePtr(const M* message) {
msg_ = message;
return SendMessage(*message, WriteOptions());
}
template <class R>
class CallOpRecvMessage {
public:

@ -73,7 +73,7 @@ class CallbackUnaryCallImpl {
CallbackWithStatusTag(call.call(), on_completion, ops);
// TODO(vjpai): Unify code with sync API as much as possible
Status s = ops->SendMessage(*request);
Status s = ops->SendMessagePtr(request);
if (!s.ok()) {
tag->force_run(s);
return;
@ -341,7 +341,7 @@ class ClientCallbackReaderWriterImpl
start_corked_ = false;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok());
if (options.is_last_message()) {
options.set_buffer_hint();
@ -524,7 +524,7 @@ class ClientCallbackReaderImpl
: context_(context), call_(call), reactor_(reactor) {
this->BindReactor(reactor);
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(start_ops_.SendMessage(*request).ok());
GPR_CODEGEN_ASSERT(start_ops_.SendMessagePtr(request).ok());
start_ops_.ClientSendClose();
}
@ -650,7 +650,7 @@ class ClientCallbackWriterImpl
start_corked_ = false;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(msg).ok());
if (options.is_last_message()) {
options.set_buffer_hint();

@ -57,7 +57,7 @@ class BlockingUnaryCallImpl {
CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
CallOpClientSendClose, CallOpClientRecvStatus>
ops;
status_ = ops.SendMessage(request);
status_ = ops.SendMessagePtr(&request);
if (!status_.ok()) {
return;
}

@ -109,7 +109,13 @@ class InterceptorBatchMethods {
/// Returns a modifable ByteBuffer holding the serialized form of the message
/// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions.
/// A return value of nullptr indicates that this ByteBuffer is not valid.
virtual ByteBuffer* GetSendMessage() = 0;
virtual ByteBuffer* GetSerializedSendMessage() = 0;
/// Returns a non-modifiable pointer to the original non-serialized form of
/// the message. Valid for PRE_SEND_MESSAGE interceptions. A return value of
/// nullptr indicates that this field is not valid. Also note that this is
/// only supported for sync and callback APIs at the present moment.
virtual const void* GetSendMessage() = 0;
/// Returns a modifiable multimap of the initial metadata to be sent. Valid
/// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates

@ -79,7 +79,9 @@ class InterceptorBatchMethodsImpl
hooks_[static_cast<size_t>(type)] = true;
}
ByteBuffer* GetSendMessage() override { return send_message_; }
ByteBuffer* GetSerializedSendMessage() override { return send_message_; }
const void* GetSendMessage() override { return orig_send_message_; }
std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
return send_initial_metadata_;
@ -115,7 +117,10 @@ class InterceptorBatchMethodsImpl
return recv_trailing_metadata_->map();
}
void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; }
void SetSendMessage(ByteBuffer* buf, const void* msg) {
send_message_ = buf;
orig_send_message_ = msg;
}
void SetSendInitialMetadata(
std::multimap<grpc::string, grpc::string>* metadata) {
@ -343,6 +348,7 @@ class InterceptorBatchMethodsImpl
std::function<void(void)> callback_;
ByteBuffer* send_message_ = nullptr;
const void* orig_send_message_ = nullptr;
std::multimap<grpc::string, grpc::string>* send_initial_metadata_;
@ -389,13 +395,21 @@ class CancelInterceptorBatchMethods
"Cancel notification");
}
ByteBuffer* GetSendMessage() override {
ByteBuffer* GetSerializedSendMessage() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call GetSendMessage on a method which "
"has a Cancel notification");
return nullptr;
}
const void* GetSendMessage() override {
GPR_CODEGEN_ASSERT(
false &&
"It is illegal to call GetOriginalSendMessage on a method which "
"has a Cancel notification");
return nullptr;
}
std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
GPR_CODEGEN_ASSERT(false &&
"It is illegal to call GetSendInitialMetadata on a "

@ -79,7 +79,7 @@ class RpcMethodHandler : public MethodHandler {
ops.set_compression_level(param.server_context->compression_level());
}
if (status.ok()) {
status = ops.SendMessage(rsp);
status = ops.SendMessagePtr(&rsp);
}
ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -139,7 +139,7 @@ class ClientStreamingHandler : public MethodHandler {
}
}
if (status.ok()) {
status = ops.SendMessage(rsp);
status = ops.SendMessagePtr(&rsp);
}
ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);

@ -320,7 +320,7 @@ class CallbackUnaryHandler : public MethodHandler {
// The response is dropped if the status is not OK.
if (s.ok()) {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
finish_ops_.SendMessage(resp_));
finish_ops_.SendMessagePtr(&resp_));
} else {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
}
@ -449,7 +449,7 @@ class CallbackClientStreamingHandler : public MethodHandler {
// The response is dropped if the status is not OK.
if (s.ok()) {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
finish_ops_.SendMessage(resp_));
finish_ops_.SendMessagePtr(&resp_));
} else {
finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
}
@ -642,7 +642,7 @@ class CallbackServerStreamingHandler : public MethodHandler {
ctx_->sent_initial_metadata_ = true;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok());
call_.PerformOps(&write_ops_);
}
@ -652,7 +652,7 @@ class CallbackServerStreamingHandler : public MethodHandler {
// Don't send any message if the status is bad
if (s.ok()) {
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok());
}
Finish(std::move(s));
}
@ -804,7 +804,7 @@ class CallbackBidiHandler : public MethodHandler {
ctx_->sent_initial_metadata_ = true;
}
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessagePtr(resp, options).ok());
call_.PerformOps(&write_ops_);
}
@ -813,7 +813,7 @@ class CallbackBidiHandler : public MethodHandler {
// Don't send any message if the status is bad
if (s.ok()) {
// TODO(vjpai): don't assert
GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
GPR_CODEGEN_ASSERT(finish_ops_.SendMessagePtr(resp, options).ok());
}
Finish(std::move(s));
}

@ -253,7 +253,7 @@ class ClientReader final : public ClientReaderInterface<R> {
ops.SendInitialMetadata(&context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
GPR_CODEGEN_ASSERT(ops.SendMessagePtr(&request).ok());
ops.ClientSendClose();
call_.PerformOps(&ops);
cq_.Pluck(&ops);
@ -331,7 +331,7 @@ class ClientWriter : public ClientWriterInterface<W> {
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
if (!ops.SendMessagePtr(&msg, options).ok()) {
return false;
}
@ -502,7 +502,7 @@ class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
context_->initial_metadata_flags());
context_->set_initial_metadata_corked(false);
}
if (!ops.SendMessage(msg, options).ok()) {
if (!ops.SendMessagePtr(&msg, options).ok()) {
return false;
}
@ -656,7 +656,7 @@ class ServerWriter final : public ServerWriterInterface<W> {
options.set_buffer_hint();
}
if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {
@ -734,7 +734,7 @@ class ServerReaderWriterBody final {
if (options.is_last_message()) {
options.set_buffer_hint();
}
if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
if (!ctx_->pending_ops_.SendMessagePtr(&msg, options).ok()) {
return false;
}
if (!ctx_->sent_initial_metadata_) {

@ -160,7 +160,7 @@ if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
elif "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'
EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_32BIT'
if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = ''

@ -665,6 +665,7 @@ void grpc_resource_quota_unref_internal(grpc_resource_quota* resource_quota) {
GPR_ASSERT(resource_quota->num_threads_allocated == 0);
GRPC_COMBINER_UNREF(resource_quota->combiner, "resource_quota");
gpr_free(resource_quota->name);
gpr_mu_destroy(&resource_quota->thread_count_mu);
gpr_free(resource_quota);
}
}

@ -42,6 +42,7 @@
#include "src/core/lib/iomgr/tcp_windows.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/slice/slice_string_helpers.h"
#if defined(__MSYS__) && defined(GPR_ARCH_64)
/* Nasty workaround for nasty bug when using the 64 bits msys compiler
@ -112,7 +113,10 @@ typedef struct grpc_tcp {
grpc_closure* read_cb;
grpc_closure* write_cb;
grpc_slice read_slice;
/* garbage after the last read */
grpc_slice_buffer last_read_buffer;
grpc_slice_buffer* write_slices;
grpc_slice_buffer* read_slices;
@ -131,6 +135,7 @@ static void tcp_free(grpc_tcp* tcp) {
grpc_winsocket_destroy(tcp->socket);
gpr_mu_destroy(&tcp->mu);
gpr_free(tcp->peer_string);
grpc_slice_buffer_destroy_internal(&tcp->last_read_buffer);
grpc_resource_user_unref(tcp->resource_user);
if (tcp->shutting_down) GRPC_ERROR_UNREF(tcp->shutdown_error);
gpr_free(tcp);
@ -179,9 +184,12 @@ static void on_read(void* tcpp, grpc_error* error) {
grpc_tcp* tcp = (grpc_tcp*)tcpp;
grpc_closure* cb = tcp->read_cb;
grpc_winsocket* socket = tcp->socket;
grpc_slice sub;
grpc_winsocket_callback_info* info = &socket->read_info;
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p on_read", tcp);
}
GRPC_ERROR_REF(error);
if (error == GRPC_ERROR_NONE) {
@ -189,13 +197,35 @@ static void on_read(void* tcpp, grpc_error* error) {
char* utf8_message = gpr_format_message(info->wsa_error);
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(utf8_message);
gpr_free(utf8_message);
grpc_slice_unref_internal(tcp->read_slice);
grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices);
} else {
if (info->bytes_transfered != 0 && !tcp->shutting_down) {
sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered);
grpc_slice_buffer_add(tcp->read_slices, sub);
GPR_ASSERT((size_t)info->bytes_transfered <= tcp->read_slices->length);
if (static_cast<size_t>(info->bytes_transfered) !=
tcp->read_slices->length) {
grpc_slice_buffer_trim_end(
tcp->read_slices,
tcp->read_slices->length -
static_cast<size_t>(info->bytes_transfered),
&tcp->last_read_buffer);
}
GPR_ASSERT((size_t)info->bytes_transfered == tcp->read_slices->length);
if (grpc_tcp_trace.enabled()) {
size_t i;
for (i = 0; i < tcp->read_slices->count; i++) {
char* dump = grpc_dump_slice(tcp->read_slices->slices[i],
GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string,
dump);
gpr_free(dump);
}
}
} else {
grpc_slice_unref_internal(tcp->read_slice);
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p unref read_slice", tcp);
}
grpc_slice_buffer_reset_and_unref_internal(tcp->read_slices);
error = tcp->shutting_down
? GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"TCP stream shutting down", &tcp->shutdown_error, 1)
@ -209,6 +239,8 @@ static void on_read(void* tcpp, grpc_error* error) {
GRPC_CLOSURE_SCHED(cb, error);
}
#define DEFAULT_TARGET_READ_SIZE 8192
#define MAX_WSABUF_COUNT 16
static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices,
grpc_closure* cb) {
grpc_tcp* tcp = (grpc_tcp*)ep;
@ -217,7 +249,12 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices,
int status;
DWORD bytes_read = 0;
DWORD flags = 0;
WSABUF buffer;
WSABUF buffers[MAX_WSABUF_COUNT];
size_t i;
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p win_read", tcp);
}
if (tcp->shutting_down) {
GRPC_CLOSURE_SCHED(
@ -229,18 +266,27 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices,
tcp->read_cb = cb;
tcp->read_slices = read_slices;
grpc_slice_buffer_reset_and_unref_internal(read_slices);
grpc_slice_buffer_swap(read_slices, &tcp->last_read_buffer);
tcp->read_slice = GRPC_SLICE_MALLOC(8192);
if (tcp->read_slices->length < DEFAULT_TARGET_READ_SIZE / 2 &&
tcp->read_slices->count < MAX_WSABUF_COUNT) {
// TODO(jtattermusch): slice should be allocated using resource quota
grpc_slice_buffer_add(tcp->read_slices,
GRPC_SLICE_MALLOC(DEFAULT_TARGET_READ_SIZE));
}
buffer.len = (ULONG)GRPC_SLICE_LENGTH(
tcp->read_slice); // we know slice size fits in 32bit.
buffer.buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slice);
GPR_ASSERT(tcp->read_slices->count <= MAX_WSABUF_COUNT);
for (i = 0; i < tcp->read_slices->count; i++) {
buffers[i].len = (ULONG)GRPC_SLICE_LENGTH(
tcp->read_slices->slices[i]); // we know slice size fits in 32bit.
buffers[i].buf = (char*)GRPC_SLICE_START_PTR(tcp->read_slices->slices[i]);
}
TCP_REF(tcp, "read");
/* First let's try a synchronous, non-blocking read. */
status =
WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL);
status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count,
&bytes_read, &flags, NULL, NULL);
info->wsa_error = status == 0 ? 0 : WSAGetLastError();
/* Did we get data immediately ? Yay. */
@ -252,8 +298,8 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices,
/* Otherwise, let's retry, by queuing a read. */
memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED));
status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
&info->overlapped, NULL);
status = WSARecv(tcp->socket->socket, buffers, (DWORD)tcp->read_slices->count,
&bytes_read, &flags, &info->overlapped, NULL);
if (status != 0) {
int wsa_error = WSAGetLastError();
@ -275,6 +321,10 @@ static void on_write(void* tcpp, grpc_error* error) {
grpc_winsocket_callback_info* info = &handle->write_info;
grpc_closure* cb;
if (grpc_tcp_trace.enabled()) {
gpr_log(GPR_INFO, "TCP:%p on_write", tcp);
}
GRPC_ERROR_REF(error);
gpr_mu_lock(&tcp->mu);
@ -303,11 +353,21 @@ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices,
unsigned i;
DWORD bytes_sent;
int status;
WSABUF local_buffers[16];
WSABUF local_buffers[MAX_WSABUF_COUNT];
WSABUF* allocated = NULL;
WSABUF* buffers = local_buffers;
size_t len;
if (grpc_tcp_trace.enabled()) {
size_t i;
for (i = 0; i < slices->count; i++) {
char* data =
grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
gpr_free(data);
}
}
if (tcp->shutting_down) {
GRPC_CLOSURE_SCHED(
cb, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
@ -412,6 +472,7 @@ static void win_shutdown(grpc_endpoint* ep, grpc_error* why) {
static void win_destroy(grpc_endpoint* ep) {
grpc_network_status_unregister_endpoint(ep);
grpc_tcp* tcp = (grpc_tcp*)ep;
grpc_slice_buffer_reset_and_unref_internal(&tcp->last_read_buffer);
TCP_UNREF(tcp, "destroy");
}
@ -463,6 +524,7 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket,
GRPC_CLOSURE_INIT(&tcp->on_read, on_read, tcp, grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_INIT(&tcp->on_write, on_write, tcp, grpc_schedule_on_exec_ctx);
tcp->peer_string = gpr_strdup(peer_string);
grpc_slice_buffer_init(&tcp->last_read_buffer);
tcp->resource_user = grpc_resource_user_create(resource_quota, peer_string);
/* Tell network status tracking code about the new endpoint */
grpc_network_status_register_endpoint(&tcp->base);

@ -194,13 +194,10 @@ struct call_data {
};
struct request_matcher {
request_matcher(grpc_server* server);
~request_matcher();
grpc_server* server;
std::atomic<call_data*> pending_head{nullptr};
call_data* pending_tail = nullptr;
gpr_locked_mpscq* requests_per_cq = nullptr;
call_data* pending_head;
call_data* pending_tail;
gpr_locked_mpscq* requests_per_cq;
};
struct registered_method {
@ -349,30 +346,22 @@ static void channel_broadcaster_shutdown(channel_broadcaster* cb,
* request_matcher
*/
namespace {
request_matcher::request_matcher(grpc_server* server) : server(server) {
requests_per_cq = static_cast<gpr_locked_mpscq*>(
gpr_malloc(sizeof(*requests_per_cq) * server->cq_count));
for (size_t i = 0; i < server->cq_count; i++) {
gpr_locked_mpscq_init(&requests_per_cq[i]);
}
}
request_matcher::~request_matcher() {
static void request_matcher_init(request_matcher* rm, grpc_server* server) {
memset(rm, 0, sizeof(*rm));
rm->server = server;
rm->requests_per_cq = static_cast<gpr_locked_mpscq*>(
gpr_malloc(sizeof(*rm->requests_per_cq) * server->cq_count));
for (size_t i = 0; i < server->cq_count; i++) {
GPR_ASSERT(gpr_locked_mpscq_pop(&requests_per_cq[i]) == nullptr);
gpr_locked_mpscq_destroy(&requests_per_cq[i]);
gpr_locked_mpscq_init(&rm->requests_per_cq[i]);
}
gpr_free(requests_per_cq);
}
} // namespace
static void request_matcher_init(request_matcher* rm, grpc_server* server) {
new (rm) request_matcher(server);
}
static void request_matcher_destroy(request_matcher* rm) {
rm->~request_matcher();
for (size_t i = 0; i < rm->server->cq_count; i++) {
GPR_ASSERT(gpr_locked_mpscq_pop(&rm->requests_per_cq[i]) == nullptr);
gpr_locked_mpscq_destroy(&rm->requests_per_cq[i]);
}
gpr_free(rm->requests_per_cq);
}
static void kill_zombie(void* elem, grpc_error* error) {
@ -381,10 +370,9 @@ static void kill_zombie(void* elem, grpc_error* error) {
}
static void request_matcher_zombify_all_pending_calls(request_matcher* rm) {
call_data* calld;
while ((calld = rm->pending_head.load(std::memory_order_relaxed)) !=
nullptr) {
rm->pending_head.store(calld->pending_next, std::memory_order_relaxed);
while (rm->pending_head) {
call_data* calld = rm->pending_head;
rm->pending_head = calld->pending_next;
gpr_atm_no_barrier_store(&calld->state, ZOMBIED);
GRPC_CLOSURE_INIT(
&calld->kill_zombie_closure, kill_zombie,
@ -582,9 +570,8 @@ static void publish_new_rpc(void* arg, grpc_error* error) {
}
gpr_atm_no_barrier_store(&calld->state, PENDING);
if (rm->pending_head.load(std::memory_order_relaxed) == nullptr) {
rm->pending_head.store(calld, std::memory_order_relaxed);
rm->pending_tail = calld;
if (rm->pending_head == nullptr) {
rm->pending_tail = rm->pending_head = calld;
} else {
rm->pending_tail->pending_next = calld;
rm->pending_tail = calld;
@ -1448,39 +1435,30 @@ static grpc_call_error queue_call_request(grpc_server* server, size_t cq_idx,
rm = &rc->data.registered.method->matcher;
break;
}
// Fast path: if there is no pending request to be processed, immediately
// return.
if (!gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link) ||
// Note: We are reading the pending_head without holding the server's call
// mutex. Even if we read a non-null value here due to reordering,
// we will check it below again after grabbing the lock.
rm->pending_head.load(std::memory_order_relaxed) == nullptr) {
return GRPC_CALL_OK;
}
// Slow path: This was the first queued request and there are pendings:
// We need to lock and start matching calls.
gpr_mu_lock(&server->mu_call);
while ((calld = rm->pending_head.load(std::memory_order_relaxed)) !=
nullptr) {
rc = reinterpret_cast<requested_call*>(
gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]));
if (rc == nullptr) break;
rm->pending_head.store(calld->pending_next, std::memory_order_relaxed);
gpr_mu_unlock(&server->mu_call);
if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) {
// Zombied Call
GRPC_CLOSURE_INIT(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(&calld->kill_zombie_closure, GRPC_ERROR_NONE);
} else {
publish_call(server, calld, cq_idx, rc);
}
if (gpr_locked_mpscq_push(&rm->requests_per_cq[cq_idx], &rc->request_link)) {
/* this was the first queued request: we need to lock and start
matching calls */
gpr_mu_lock(&server->mu_call);
while ((calld = rm->pending_head) != nullptr) {
rc = reinterpret_cast<requested_call*>(
gpr_locked_mpscq_pop(&rm->requests_per_cq[cq_idx]));
if (rc == nullptr) break;
rm->pending_head = calld->pending_next;
gpr_mu_unlock(&server->mu_call);
if (!gpr_atm_full_cas(&calld->state, PENDING, ACTIVATED)) {
// Zombied Call
GRPC_CLOSURE_INIT(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0),
grpc_schedule_on_exec_ctx);
GRPC_CLOSURE_SCHED(&calld->kill_zombie_closure, GRPC_ERROR_NONE);
} else {
publish_call(server, calld, cq_idx, rc);
}
gpr_mu_lock(&server->mu_call);
}
gpr_mu_unlock(&server->mu_call);
}
gpr_mu_unlock(&server->mu_call);
return GRPC_CALL_OK;
}

@ -187,6 +187,7 @@ static void gc_mdtab(mdtab_shard* shard) {
((destroy_user_data_func)gpr_atm_no_barrier_load(
&md->destroy_user_data))(user_data);
}
gpr_mu_destroy(&md->mu_user_data);
gpr_free(md);
*prev_next = next;
num_freed++;

@ -23,6 +23,11 @@ from grpc._cython import cygrpc as _cygrpc
logging.getLogger(__name__).addHandler(logging.NullHandler())
try:
from ._grpcio_metadata import __version__
except ImportError:
__version__ = "dev0"
############################## Future Interface ###############################

@ -28,19 +28,22 @@ cdef tuple _wrap_grpc_arg(grpc_arg arg)
cdef grpc_arg _unwrap_grpc_arg(tuple wrapped_arg)
cdef class _ArgumentProcessor:
cdef class _ChannelArg:
cdef grpc_arg c_argument
cdef void c(self, argument, grpc_arg_pointer_vtable *vtable, references) except *
cdef class _ArgumentsProcessor:
cdef class _ChannelArgs:
cdef readonly tuple _arguments
cdef list _argument_processors
cdef list _channel_args
cdef readonly list _references
cdef grpc_channel_args _c_arguments
cdef grpc_channel_args *c(self, grpc_arg_pointer_vtable *vtable) except *
cdef un_c(self)
cdef void _c(self, grpc_arg_pointer_vtable *vtable) except *
cdef grpc_channel_args *c_args(self) except *
@staticmethod
cdef _ChannelArgs from_args(object arguments, grpc_arg_pointer_vtable * vtable)

@ -50,7 +50,7 @@ cdef grpc_arg _unwrap_grpc_arg(tuple wrapped_arg):
return wrapped.arg
cdef class _ArgumentProcessor:
cdef class _ChannelArg:
cdef void c(self, argument, grpc_arg_pointer_vtable *vtable, references) except *:
key, value = argument
@ -82,27 +82,34 @@ cdef class _ArgumentProcessor:
'Expected int, bytes, or behavior, got {}'.format(type(value)))
cdef class _ArgumentsProcessor:
cdef class _ChannelArgs:
def __cinit__(self, arguments):
self._arguments = () if arguments is None else tuple(arguments)
self._argument_processors = []
self._channel_args = []
self._references = []
self._c_arguments.arguments = NULL
cdef grpc_channel_args *c(self, grpc_arg_pointer_vtable *vtable) except *:
cdef void _c(self, grpc_arg_pointer_vtable *vtable) except *:
self._c_arguments.arguments_length = len(self._arguments)
if self._c_arguments.arguments_length == 0:
return NULL
else:
if self._c_arguments.arguments_length != 0:
self._c_arguments.arguments = <grpc_arg *>gpr_malloc(
self._c_arguments.arguments_length * sizeof(grpc_arg))
for index, argument in enumerate(self._arguments):
argument_processor = _ArgumentProcessor()
argument_processor.c(argument, vtable, self._references)
self._c_arguments.arguments[index] = argument_processor.c_argument
self._argument_processors.append(argument_processor)
return &self._c_arguments
cdef un_c(self):
if self._arguments:
channel_arg = _ChannelArg()
channel_arg.c(argument, vtable, self._references)
self._c_arguments.arguments[index] = channel_arg.c_argument
self._channel_args.append(channel_arg)
cdef grpc_channel_args *c_args(self) except *:
return &self._c_arguments
def __dealloc__(self):
if self._c_arguments.arguments != NULL:
gpr_free(self._c_arguments.arguments)
@staticmethod
cdef _ChannelArgs from_args(object arguments, grpc_arg_pointer_vtable * vtable):
cdef _ChannelArgs channel_args = _ChannelArgs(arguments)
channel_args._c(vtable)
return channel_args

@ -423,16 +423,15 @@ cdef class Channel:
self._vtable.copy = &_copy_pointer
self._vtable.destroy = &_destroy_pointer
self._vtable.cmp = &_compare_pointer
cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor(
arguments)
cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable)
cdef _ChannelArgs channel_args = _ChannelArgs.from_args(
arguments, &self._vtable)
if channel_credentials is None:
self._state.c_channel = grpc_insecure_channel_create(
<char *>target, c_arguments, NULL)
<char *>target, channel_args.c_args(), NULL)
else:
c_channel_credentials = channel_credentials.c()
self._state.c_channel = grpc_secure_channel_create(
c_channel_credentials, <char *>target, c_arguments, NULL)
c_channel_credentials, <char *>target, channel_args.c_args(), NULL)
grpc_channel_credentials_release(c_channel_credentials)
self._state.c_call_completion_queue = (
grpc_completion_queue_create_for_next(NULL))

@ -16,7 +16,6 @@
cdef class Server:
cdef grpc_arg_pointer_vtable _vtable
cdef readonly _ArgumentsProcessor _arguments_processor
cdef grpc_server *c_server
cdef bint is_started # start has been called
cdef bint is_shutting_down # shutdown has been called

@ -29,11 +29,9 @@ cdef class Server:
self._vtable.copy = &_copy_pointer
self._vtable.destroy = &_destroy_pointer
self._vtable.cmp = &_compare_pointer
cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor(
arguments)
cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable)
self.c_server = grpc_server_create(c_arguments, NULL)
arguments_processor.un_c()
cdef _ChannelArgs channel_args = _ChannelArgs.from_args(
arguments, &self._vtable)
self.c_server = grpc_server_create(channel_args.c_args(), NULL)
self.references.append(arguments)
self.is_started = False
self.is_shutting_down = False

@ -23,15 +23,61 @@ from grpc_health.v1 import health_pb2_grpc as _health_pb2_grpc
SERVICE_NAME = _health_pb2.DESCRIPTOR.services_by_name['Health'].full_name
class _Watcher():
def __init__(self):
self._condition = threading.Condition()
self._responses = list()
self._open = True
def __iter__(self):
return self
def _next(self):
with self._condition:
while not self._responses and self._open:
self._condition.wait()
if self._responses:
return self._responses.pop(0)
else:
raise StopIteration()
def next(self):
return self._next()
def __next__(self):
return self._next()
def add(self, response):
with self._condition:
self._responses.append(response)
self._condition.notify()
def close(self):
with self._condition:
self._open = False
self._condition.notify()
class HealthServicer(_health_pb2_grpc.HealthServicer):
"""Servicer handling RPCs for service statuses."""
def __init__(self):
self._server_status_lock = threading.Lock()
self._lock = threading.RLock()
self._server_status = {}
self._watchers = {}
def _on_close_callback(self, watcher, service):
def callback():
with self._lock:
self._watchers[service].remove(watcher)
watcher.close()
return callback
def Check(self, request, context):
with self._server_status_lock:
with self._lock:
status = self._server_status.get(request.service)
if status is None:
context.set_code(grpc.StatusCode.NOT_FOUND)
@ -39,14 +85,30 @@ class HealthServicer(_health_pb2_grpc.HealthServicer):
else:
return _health_pb2.HealthCheckResponse(status=status)
def Watch(self, request, context):
service = request.service
with self._lock:
status = self._server_status.get(service)
if status is None:
status = _health_pb2.HealthCheckResponse.SERVICE_UNKNOWN # pylint: disable=no-member
watcher = _Watcher()
watcher.add(_health_pb2.HealthCheckResponse(status=status))
if service not in self._watchers:
self._watchers[service] = set()
self._watchers[service].add(watcher)
context.add_callback(self._on_close_callback(watcher, service))
return watcher
def set(self, service, status):
"""Sets the status of a service.
Args:
service: string, the name of the service.
NOTE, '' must be set.
status: HealthCheckResponse.status enum value indicating
the status of the service
"""
with self._server_status_lock:
Args:
service: string, the name of the service. NOTE, '' must be set.
status: HealthCheckResponse.status enum value indicating the status of
the service
"""
with self._lock:
self._server_status[service] = status
if service in self._watchers:
for watcher in self._watchers[service]:
watcher.add(_health_pb2.HealthCheckResponse(status=status))

@ -141,6 +141,7 @@ class TestGevent(setuptools.Command):
'unit._exit_test.ExitTest.test_in_flight_partial_unary_stream_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_unary_call',
'unit._exit_test.ExitTest.test_in_flight_partial_stream_stream_call',
'health_check._health_servicer_test.HealthServicerTest.test_cancelled_watch_removed_from_watch_list',
# TODO(https://github.com/grpc/grpc/issues/17330) enable these three tests
'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels',
'channelz._channelz_servicer_test.ChannelzServicerTest.test_many_subchannels_and_sockets',

@ -9,6 +9,7 @@ py_test(
"//src/python/grpcio/grpc:grpcio",
"//src/python/grpcio_health_checking/grpc_health/v1:grpc_health",
"//src/python/grpcio_tests/tests/unit:test_common",
"//src/python/grpcio_tests/tests/unit/framework/common:common",
],
imports = ["../../",],
)

@ -13,6 +13,8 @@
# limitations under the License.
"""Tests of grpc_health.v1.health."""
import threading
import time
import unittest
import grpc
@ -21,22 +23,36 @@ from grpc_health.v1 import health_pb2
from grpc_health.v1 import health_pb2_grpc
from tests.unit import test_common
from tests.unit.framework.common import test_constants
from six.moves import queue
_SERVING_SERVICE = 'grpc.test.TestServiceServing'
_UNKNOWN_SERVICE = 'grpc.test.TestServiceUnknown'
_NOT_SERVING_SERVICE = 'grpc.test.TestServiceNotServing'
_WATCH_SERVICE = 'grpc.test.WatchService'
def _consume_responses(response_iterator, response_queue):
for response in response_iterator:
response_queue.put(response)
class HealthServicerTest(unittest.TestCase):
def setUp(self):
servicer = health.HealthServicer()
servicer.set('', health_pb2.HealthCheckResponse.SERVING)
servicer.set('grpc.test.TestServiceServing',
health_pb2.HealthCheckResponse.SERVING)
servicer.set('grpc.test.TestServiceUnknown',
health_pb2.HealthCheckResponse.UNKNOWN)
servicer.set('grpc.test.TestServiceNotServing',
health_pb2.HealthCheckResponse.NOT_SERVING)
self._servicer = health.HealthServicer()
self._servicer.set('', health_pb2.HealthCheckResponse.SERVING)
self._servicer.set(_SERVING_SERVICE,
health_pb2.HealthCheckResponse.SERVING)
self._servicer.set(_UNKNOWN_SERVICE,
health_pb2.HealthCheckResponse.UNKNOWN)
self._servicer.set(_NOT_SERVING_SERVICE,
health_pb2.HealthCheckResponse.NOT_SERVING)
self._server = test_common.test_server()
port = self._server.add_insecure_port('[::]:0')
health_pb2_grpc.add_HealthServicer_to_server(servicer, self._server)
health_pb2_grpc.add_HealthServicer_to_server(self._servicer,
self._server)
self._server.start()
self._channel = grpc.insecure_channel('localhost:%d' % port)
@ -46,37 +62,160 @@ class HealthServicerTest(unittest.TestCase):
self._server.stop(None)
self._channel.close()
def test_empty_service(self):
def test_check_empty_service(self):
request = health_pb2.HealthCheckRequest()
resp = self._stub.Check(request)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
def test_serving_service(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceServing')
def test_check_serving_service(self):
request = health_pb2.HealthCheckRequest(service=_SERVING_SERVICE)
resp = self._stub.Check(request)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING, resp.status)
def test_unknown_serivce(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceUnknown')
def test_check_unknown_serivce(self):
request = health_pb2.HealthCheckRequest(service=_UNKNOWN_SERVICE)
resp = self._stub.Check(request)
self.assertEqual(health_pb2.HealthCheckResponse.UNKNOWN, resp.status)
def test_not_serving_service(self):
request = health_pb2.HealthCheckRequest(
service='grpc.test.TestServiceNotServing')
def test_check_not_serving_service(self):
request = health_pb2.HealthCheckRequest(service=_NOT_SERVING_SERVICE)
resp = self._stub.Check(request)
self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING,
resp.status)
def test_not_found_service(self):
def test_check_not_found_service(self):
request = health_pb2.HealthCheckRequest(service='not-found')
with self.assertRaises(grpc.RpcError) as context:
resp = self._stub.Check(request)
self.assertEqual(grpc.StatusCode.NOT_FOUND, context.exception.code())
def test_watch_empty_service(self):
request = health_pb2.HealthCheckRequest(service='')
response_queue = queue.Queue()
rendezvous = self._stub.Watch(request)
thread = threading.Thread(
target=_consume_responses, args=(rendezvous, response_queue))
thread.start()
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING,
response.status)
rendezvous.cancel()
thread.join()
self.assertTrue(response_queue.empty())
def test_watch_new_service(self):
request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE)
response_queue = queue.Queue()
rendezvous = self._stub.Watch(request)
thread = threading.Thread(
target=_consume_responses, args=(rendezvous, response_queue))
thread.start()
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN,
response.status)
self._servicer.set(_WATCH_SERVICE,
health_pb2.HealthCheckResponse.SERVING)
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING,
response.status)
self._servicer.set(_WATCH_SERVICE,
health_pb2.HealthCheckResponse.NOT_SERVING)
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.NOT_SERVING,
response.status)
rendezvous.cancel()
thread.join()
self.assertTrue(response_queue.empty())
def test_watch_service_isolation(self):
request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE)
response_queue = queue.Queue()
rendezvous = self._stub.Watch(request)
thread = threading.Thread(
target=_consume_responses, args=(rendezvous, response_queue))
thread.start()
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN,
response.status)
self._servicer.set('some-other-service',
health_pb2.HealthCheckResponse.SERVING)
with self.assertRaises(queue.Empty):
response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
rendezvous.cancel()
thread.join()
self.assertTrue(response_queue.empty())
def test_two_watchers(self):
request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE)
response_queue1 = queue.Queue()
response_queue2 = queue.Queue()
rendezvous1 = self._stub.Watch(request)
rendezvous2 = self._stub.Watch(request)
thread1 = threading.Thread(
target=_consume_responses, args=(rendezvous1, response_queue1))
thread2 = threading.Thread(
target=_consume_responses, args=(rendezvous2, response_queue2))
thread1.start()
thread2.start()
response1 = response_queue1.get(timeout=test_constants.SHORT_TIMEOUT)
response2 = response_queue2.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN,
response1.status)
self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN,
response2.status)
self._servicer.set(_WATCH_SERVICE,
health_pb2.HealthCheckResponse.SERVING)
response1 = response_queue1.get(timeout=test_constants.SHORT_TIMEOUT)
response2 = response_queue2.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING,
response1.status)
self.assertEqual(health_pb2.HealthCheckResponse.SERVING,
response2.status)
rendezvous1.cancel()
rendezvous2.cancel()
thread1.join()
thread2.join()
self.assertTrue(response_queue1.empty())
self.assertTrue(response_queue2.empty())
def test_cancelled_watch_removed_from_watch_list(self):
request = health_pb2.HealthCheckRequest(service=_WATCH_SERVICE)
response_queue = queue.Queue()
rendezvous = self._stub.Watch(request)
thread = threading.Thread(
target=_consume_responses, args=(rendezvous, response_queue))
thread.start()
response = response_queue.get(timeout=test_constants.SHORT_TIMEOUT)
self.assertEqual(health_pb2.HealthCheckResponse.SERVICE_UNKNOWN,
response.status)
rendezvous.cancel()
self._servicer.set(_WATCH_SERVICE,
health_pb2.HealthCheckResponse.SERVING)
thread.join()
# Wait, if necessary, for serving thread to process client cancellation
timeout = time.time() + test_constants.SHORT_TIMEOUT
while time.time() < timeout and self._servicer._watchers[_WATCH_SERVICE]:
time.sleep(1)
self.assertFalse(self._servicer._watchers[_WATCH_SERVICE],
'watch set should be empty')
self.assertTrue(response_queue.empty())
def test_health_service_name(self):
self.assertEqual(health.SERVICE_NAME, 'grpc.health.v1.Health')

@ -64,6 +64,7 @@
"unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithoutClientAuth",
"unit._server_test.ServerTest",
"unit._session_cache_test.SSLSessionCacheTest",
"unit._version_test.VersionTest",
"unit.beta._beta_features_test.BetaFeaturesTest",
"unit.beta._beta_features_test.ContextManagementAndLifecycleTest",
"unit.beta._connectivity_channel_test.ConnectivityStatesTest",

@ -7,6 +7,7 @@ GRPCIO_TESTS_UNIT = [
"_api_test.py",
"_auth_context_test.py",
"_auth_test.py",
"_version_test.py",
"_channel_args_test.py",
"_channel_close_test.py",
"_channel_connectivity_test.py",

@ -0,0 +1,30 @@
# Copyright 2018 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.
"""Test for grpc.__version__"""
import unittest
import grpc
import logging
from grpc import _grpcio_metadata
class VersionTest(unittest.TestCase):
def test_get_version(self):
self.assertEqual(grpc.__version__, _grpcio_metadata.__version__)
if __name__ == '__main__':
logging.basicConfig()
unittest.main(verbosity=2)

@ -143,7 +143,7 @@
## Some libraries are shared even with BUILD_SHARED_LIBRARIES=OFF
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
add_definitions(-DPB_FIELD_16BIT)
add_definitions(-DPB_FIELD_32BIT)
if (MSVC)
include(cmake/msvc_static_runtime.cmake)

@ -152,7 +152,7 @@
}
s.default_subspecs = 'Interface', 'Implementation'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_16BIT'
s.compiler_flags = '-DGRPC_ARES=0', '-DPB_FIELD_32BIT'
s.libraries = 'c++'
# Like many other C libraries, gRPC-Core has its public headers under `include/<libname>/` and its

@ -2,13 +2,13 @@
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.1"
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
# Install Ruby 2.5
RUN /bin/bash -l -c "rvm install ruby-2.5"
RUN /bin/bash -l -c "rvm use --default ruby-2.5"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-document"

@ -113,6 +113,15 @@ int main(int argc, char** argv) {
g_fixture_slowdown_factor = 10;
#endif
#ifdef GPR_WINDOWS
/* on Windows, writing logs to stderr is very slow
when stderr is redirected to a disk file.
The "trace" tests fixtures generates large amount
of logs, so setting a buffer for stderr prevents certain
test cases from timing out. */
setvbuf(stderr, NULL, _IOLBF, 1024);
#endif
grpc::testing::TestEnvironment env(argc, argv);
grpc_end2end_tests_pre_init();
grpc_init();

@ -140,6 +140,15 @@ int main(int argc, char** argv) {
g_fixture_slowdown_factor = 10;
#endif
#ifdef GPR_WINDOWS
/* on Windows, writing logs to stderr is very slow
when stderr is redirected to a disk file.
The "trace" tests fixtures generates large amount
of logs, so setting a buffer for stderr prevents certain
test cases from timing out. */
setvbuf(stderr, NULL, _IOLBF, 1024);
#endif
grpc::testing::TestEnvironment env(argc, argv);
grpc_end2end_tests_pre_init();
grpc_init();

@ -12,13 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_test", "grpc_package")
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
grpc_package(name = "test/core/memory_usage")
licenses(["notice"]) # Apache v2
grpc_cc_binary(
grpc_cc_library(
name = "memory_usage_client",
testonly = 1,
srcs = ["client.cc"],
@ -29,7 +29,7 @@ grpc_cc_binary(
],
)
grpc_cc_binary(
grpc_cc_library(
name = "memory_usage_server",
testonly = 1,
srcs = ["server.cc"],

@ -68,7 +68,7 @@ class HijackingInterceptor : public experimental::Interceptor {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EchoRequest req;
auto* buffer = methods->GetSendMessage();
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EXPECT_TRUE(
SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
@ -173,7 +173,7 @@ class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EchoRequest req;
auto* buffer = methods->GetSendMessage();
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EXPECT_TRUE(
SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
@ -384,12 +384,16 @@ class LoggingInterceptor : public experimental::Interceptor {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EchoRequest req;
auto* buffer = methods->GetSendMessage();
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EXPECT_TRUE(
SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
.ok());
EXPECT_TRUE(req.message().find("Hello") == 0);
EXPECT_TRUE(req.message().find("Hello") == 0u);
EXPECT_EQ(static_cast<const EchoRequest*>(methods->GetSendMessage())
->message()
.find("Hello"),
0u);
}
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_CLOSE)) {
@ -405,7 +409,7 @@ class LoggingInterceptor : public experimental::Interceptor {
experimental::InterceptionHookPoints::POST_RECV_MESSAGE)) {
EchoResponse* resp =
static_cast<EchoResponse*>(methods->GetRecvMessage());
EXPECT_TRUE(resp->message().find("Hello") == 0);
EXPECT_TRUE(resp->message().find("Hello") == 0u);
}
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::POST_RECV_STATUS)) {

@ -73,7 +73,7 @@ class LoggingInterceptor : public experimental::Interceptor {
type == experimental::ServerRpcInfo::Type::BIDI_STREAMING));
}
virtual void Intercept(experimental::InterceptorBatchMethods* methods) {
void Intercept(experimental::InterceptorBatchMethods* methods) override {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA)) {
auto* map = methods->GetSendInitialMetadata();
@ -83,7 +83,7 @@ class LoggingInterceptor : public experimental::Interceptor {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EchoRequest req;
auto* buffer = methods->GetSendMessage();
auto* buffer = methods->GetSerializedSendMessage();
auto copied_buffer = *buffer;
EXPECT_TRUE(
SerializationTraits<EchoRequest>::Deserialize(&copied_buffer, &req)
@ -142,6 +142,32 @@ class LoggingInterceptorFactory
}
};
// Test if GetSendMessage works as expected
class GetSendMessageTester : public experimental::Interceptor {
public:
GetSendMessageTester(experimental::ServerRpcInfo* info) {}
void Intercept(experimental::InterceptorBatchMethods* methods) override {
if (methods->QueryInterceptionHookPoint(
experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
EXPECT_EQ(static_cast<const EchoRequest*>(methods->GetSendMessage())
->message()
.find("Hello"),
0u);
}
methods->Proceed();
}
};
class GetSendMessageTesterFactory
: public experimental::ServerInterceptorFactoryInterface {
public:
virtual experimental::Interceptor* CreateServerInterceptor(
experimental::ServerRpcInfo* info) override {
return new GetSendMessageTester(info);
}
};
void MakeBidiStreamingCall(const std::shared_ptr<Channel>& channel) {
auto stub = grpc::testing::EchoTestService::NewStub(channel);
ClientContext ctx;
@ -176,6 +202,9 @@ class ServerInterceptorsEnd2endSyncUnaryTest : public ::testing::Test {
creators.push_back(
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>(
new LoggingInterceptorFactory()));
creators.push_back(
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>(
new GetSendMessageTesterFactory()));
// Add 20 dummy interceptor factories and null interceptor factories
for (auto i = 0; i < 20; i++) {
creators.push_back(std::unique_ptr<DummyInterceptorFactory>(
@ -216,6 +245,9 @@ class ServerInterceptorsEnd2endSyncStreamingTest : public ::testing::Test {
creators.push_back(
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>(
new LoggingInterceptorFactory()));
creators.push_back(
std::unique_ptr<experimental::ServerInterceptorFactoryInterface>(
new GetSendMessageTesterFactory()));
for (auto i = 0; i < 20; i++) {
creators.push_back(std::unique_ptr<DummyInterceptorFactory>(
new DummyInterceptorFactory()));

@ -1,8 +1,7 @@
FROM larskanis/rake-compiler-dock:0.6.2
FROM larskanis/rake-compiler-dock-mri:0.7.0
RUN find / -name rbconfig.rb | while read f ; do sed -i 's/0x0501/0x0600/' $f ; done
RUN find / -name win32.h | while read f ; do sed -i 's/gettimeofday/rb_gettimeofday/' $f ; done
RUN sed -i 's/defined.__MINGW64__.$/1/' /usr/local/rake-compiler/ruby/i686-w64-mingw32/ruby-2.0.0-p645/include/ruby-2.0.0/ruby/win32.h
RUN find / -name libwinpthread.dll.a | xargs rm
RUN find / -name libwinpthread-1.dll | xargs rm
RUN find / -name *msvcrt-ruby*.dll.a | while read f ; do n=`echo $f | sed s/.dll//` ; mv $f $n ; done

@ -49,7 +49,7 @@ EOF
MAKE="make -j8"
for v in 2.5.0 2.4.0 2.3.0 2.2.2 2.1.6 2.0.0-p645 ; do
for v in 2.6.0 2.5.0 2.4.0 2.3.0 2.2.2 ; do
ccache -c
rake -f "$CROSS_RUBY" cross-ruby VERSION="$v" HOST=x86_64-darwin11 MAKE="$MAKE"
done

@ -19,10 +19,19 @@ RUN yum install -y curl
RUN yum install -y tar which
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.2
# Running the installation twice to work around docker issue when using overlay.
# https://github.com/docker/docker/issues/10180
RUN (curl -sSL https://get.rvm.io | bash -s stable --ruby) || (curl -sSL https://get.rvm.io | bash -s stable --ruby)
RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10")
RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install --update bundler"

@ -14,6 +14,20 @@
FROM centos:7
RUN yum install -y ruby
RUN yum update && yum install -y curl tar which
RUN gem install bundler
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.2
RUN /bin/bash -l -c "rvm install ruby-2.2.10"
RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"

@ -14,6 +14,23 @@
FROM fedora:20
RUN yum clean all && yum update -y && yum install -y ruby findutils
# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19
RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils
RUN gem install bundler
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.2
# Running the installation twice to work around docker issue when using overlay.
# https://github.com/docker/docker/issues/10180
RUN (/bin/bash -l -c "rvm install ruby-2.2.10") || (/bin/bash -l -c "rvm install ruby-2.2.10")
RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"

@ -19,6 +19,21 @@ FROM fedora:21
# https://github.com/docker/docker/issues/10180
RUN yum install -y yum-plugin-ovl
RUN yum clean all && yum update -y && yum install -y ruby findutils
# distro-sync and install openssl, per https://github.com/fedora-cloud/docker-brew-fedora/issues/19
RUN yum clean all && yum update -y && yum distro-sync -y && yum install -y openssl gnupg which findutils tar
RUN gem install bundler
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.2
RUN /bin/bash -l -c "rvm install ruby-2.2.10"
RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
RUN /bin/bash -l -c "echo '. /etc/profile.d/rvm.sh' >> ~/.bashrc"

@ -0,0 +1,40 @@
# Copyright 2015 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 Git and basic packages.
RUN apt-get update && apt-get install -y \
curl \
gcc && apt-get clean
#==================
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.2
RUN /bin/bash -l -c "rvm install ruby-2.2.10"
RUN /bin/bash -l -c "rvm use --default ruby-2.2.10"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.2.10' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
# Define the default command.
CMD ["bash"]

@ -0,0 +1,41 @@
# Copyright 2015 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 Git and basic packages.
RUN apt-get update && apt-get install -y \
curl \
gcc && apt-get clean
#==================
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.3
RUN /bin/bash -l -c "rvm install ruby-2.3.8"
RUN /bin/bash -l -c "rvm use --default ruby-2.3.8"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.3.8' >> ~/.bashrc"
RUN /bin/bash -l -c "gem update --system"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
# Define the default command.
CMD ["bash"]

@ -0,0 +1,40 @@
# Copyright 2015 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 Git and basic packages.
RUN apt-get update && apt-get install -y \
curl \
gcc && apt-get clean
#==================
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.4
RUN /bin/bash -l -c "rvm install ruby-2.4.5"
RUN /bin/bash -l -c "rvm use --default ruby-2.4.5"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.4.5' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
# Define the default command.
CMD ["bash"]

@ -0,0 +1,40 @@
# Copyright 2015 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 Git and basic packages.
RUN apt-get update && apt-get install -y \
curl \
gcc && apt-get clean
#==================
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.5
RUN /bin/bash -l -c "rvm install ruby-2.5.3"
RUN /bin/bash -l -c "rvm use --default ruby-2.5.3"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5.3' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-document"
RUN mkdir /var/local/jenkins
# Define the default command.
CMD ["bash"]

@ -23,16 +23,16 @@ RUN apt-get update && apt-get install -y \
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.0"
RUN /bin/bash -l -c "rvm use --default ruby-2.0"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
# Install Ruby 2.6
RUN /bin/bash -l -c "rvm install ruby-2.6.0"
RUN /bin/bash -l -c "rvm use --default ruby-2.6.0"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.0' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.6.0' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-document"
RUN mkdir /var/local/jenkins

@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y \
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
@ -58,7 +58,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc"
##################

@ -49,7 +49,7 @@ RUN apt-get update && apt-get install -y \
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
@ -58,7 +58,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc"
##################
# C# dependencies (needed to build grpc_csharp_ext)

@ -68,16 +68,16 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.1"
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
# Install Ruby 2.5
RUN /bin/bash -l -c "rvm install ruby-2.5"
RUN /bin/bash -l -c "rvm use --default ruby-2.5"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-document"
RUN mkdir /var/local/jenkins

@ -27,7 +27,7 @@ ${name}')
cp -r /var/local/jenkins/service_account $HOME || true
cd /var/local/git/grpc
rvm --default use ruby-2.1
rvm --default use ruby-2.5
# build Ruby interop client and server
(cd src/ruby && gem update bundler && bundle && rake compile)

@ -72,16 +72,16 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t
# Ruby dependencies
# Install rvm
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
RUN \curl -sSL https://get.rvm.io | bash -s stable
# Install Ruby 2.1
RUN /bin/bash -l -c "rvm install ruby-2.1"
RUN /bin/bash -l -c "rvm use --default ruby-2.1"
RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc"
# Install Ruby 2.5
RUN /bin/bash -l -c "rvm install ruby-2.5"
RUN /bin/bash -l -c "rvm use --default ruby-2.5"
RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.gemrc"
RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc"
RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.5' >> ~/.bashrc"
RUN /bin/bash -l -c "gem install bundler --no-document"
RUN mkdir /var/local/jenkins

@ -42,7 +42,7 @@ source $HOME/.rvm/scripts/rvm
set -e # rvm commands are very verbose
time rvm install 2.5.0
rvm use 2.5.0 --default
time gem install bundler --no-ri --no-doc
time gem install bundler -v 1.17.3 --no-ri --no-doc
time gem install cocoapods --version 1.3.1 --no-ri --no-doc
time gem install rake-compiler --no-ri --no-doc
rvm osx-ssl-certs status all

@ -38,7 +38,7 @@ fi
set +ex
rvm use default
gem install bundler --update
gem install bundler -v 1.17.3
tools/run_tests/helper_scripts/bundle_install_wrapper.sh

@ -336,9 +336,11 @@ def targets():
PythonDistribTest('linux', 'x64', 'ubuntu1404', source=True),
PythonDistribTest('linux', 'x64', 'ubuntu1604', source=True),
RubyDistribTest('linux', 'x64', 'wheezy'),
RubyDistribTest('linux', 'x64', 'jessie'),
RubyDistribTest('linux', 'x86', 'jessie'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_0_0'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_2'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_3'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_4'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_5'),
RubyDistribTest('linux', 'x64', 'jessie', ruby_version='ruby_2_6'),
RubyDistribTest('linux', 'x64', 'centos6'),
RubyDistribTest('linux', 'x64', 'centos7'),
RubyDistribTest('linux', 'x64', 'fedora20'),

Loading…
Cancel
Save