aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar temiola <temiola@google.com>2014-12-08 15:09:07 -0800
committerGravatar Nicolas Noble <nnoble@google.com>2014-12-08 18:50:13 -0800
commitba22e87c6874d240ecd821d0c30c5f01d62c2fdd (patch)
tree59419ecdba4ee135eda6307c79b89c29b94451c5 /src
parent5ef51949bcd339c8bc615ec98f13c71bc503484a (diff)
Adds ruby versions of the interop server and client
- Adds the service and message classes generated from beefcake and a patched proto compiler - Adds an interop client that uses these service and message classes - Adds an interop server that implement the service description TESTED interop client works with the interop server Change on 2014/12/08 by temiola <temiola@google.com> ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=81615139
Diffstat (limited to 'src')
-rwxr-xr-xsrc/ruby/bin/interop/README.md11
-rw-r--r--src/ruby/bin/interop/interop_client.rb229
-rw-r--r--src/ruby/bin/interop/interop_server.rb185
-rwxr-xr-xsrc/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb14
-rwxr-xr-xsrc/ruby/bin/interop/net/proto2/proto/empty.pb.rb12
-rwxr-xr-xsrc/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb94
-rwxr-xr-xsrc/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb30
-rwxr-xr-xsrc/ruby/grpc.gemspec1
-rw-r--r--src/ruby/lib/grpc/generic/rpc_desc.rb4
9 files changed, 578 insertions, 2 deletions
diff --git a/src/ruby/bin/interop/README.md b/src/ruby/bin/interop/README.md
new file mode 100755
index 0000000000..04020868a4
--- /dev/null
+++ b/src/ruby/bin/interop/README.md
@@ -0,0 +1,11 @@
+Interop test protos
+===================
+
+These were generated by a patched version of beefcake and a patched version of
+protoc.
+
+- set up and access of the patched versions is described in ../../README.md
+
+The actual test proto is found in Google3 at
+
+- third_party/stubby/testing/proto/test.proto
diff --git a/src/ruby/bin/interop/interop_client.rb b/src/ruby/bin/interop/interop_client.rb
new file mode 100644
index 0000000000..309dd337ec
--- /dev/null
+++ b/src/ruby/bin/interop/interop_client.rb
@@ -0,0 +1,229 @@
+# Copyright 2014, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#!/usr/bin/env ruby
+# interop_client is a testing tool that accesses a gRPC interop testing
+# server and runs a test on it.
+#
+# Helps validate interoperation b/w different gRPC implementations.
+#
+# Usage: $ path/to/interop_client.rb --server_host=<hostname> \
+# --server_port=<port> \
+# --test_case=<testcase_name>
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'optparse'
+require 'minitest'
+require 'minitest/assertions'
+
+require 'grpc'
+require 'grpc/generic/client_stub'
+require 'grpc/generic/service'
+
+require 'third_party/stubby/testing/proto/test.pb'
+require 'third_party/stubby/testing/proto/messages.pb'
+
+# loads the certificates used to access the test server securely.
+def load_test_certs
+ this_dir = File.expand_path(File.dirname(__FILE__))
+ data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
+ files = ['ca.pem', 'server1.key', 'server1.pem']
+ files.map { |f| File.open(File.join(data_dir, f)).read }
+end
+
+# creates a Credentials from the test certificates.
+def test_creds
+ certs = load_test_certs
+ creds = GRPC::Core::Credentials.new(certs[0])
+end
+
+# creates a test stub that accesses host:port securely.
+def create_stub(host, port)
+ address = "#{host}:#{port}"
+ stub_opts = {
+ :creds => test_creds,
+ GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.com',
+ }
+ logger.info("... connecting securely to #{address}")
+ stub = Grpc::Testing::TestService::Stub.new(address, **stub_opts)
+end
+
+# produces a string of null chars (\0) of length l.
+def nulls(l)
+ raise 'requires #{l} to be +ve' if l < 0
+ [].pack('x' * l)
+end
+
+# defines methods corresponding to each interop test case.
+class NamedTests
+ include Minitest::Assertions
+ include Grpc::Testing
+ include Grpc::Testing::PayloadType
+ attr_accessor :assertions # required by Minitest::Assertions
+
+ def initialize(stub)
+ @assertions = 0 # required by Minitest::Assertions
+ @stub = stub
+ end
+
+ # TESTING
+ # PASSED
+ # FAIL
+ # ruby server: fails beefcake throws on deserializing the 0-length message
+ def empty_unary
+ resp = @stub.empty_call(Proto2::Empty.new)
+ assert resp.is_a?(Proto::Empty), 'empty_unary: invalid response'
+ p 'OK: empty_unary'
+ end
+
+ # TESTING
+ # PASSED
+ # ruby server
+ # FAILED
+ def large_unary
+ req_size, wanted_response_size = 271828, 314159
+ payload = Payload.new(:type => COMPRESSABLE, :body => nulls(req_size))
+ req = SimpleRequest.new(:response_type => COMPRESSABLE,
+ :response_size => wanted_response_size,
+ :payload => payload)
+ resp = @stub.unary_call(req)
+ assert_equal(wanted_response_size, resp.payload.body.length,
+ 'large_unary: payload had the wrong length')
+ assert_equal(nulls(wanted_response_size), resp.payload.body,
+ 'large_unary: payload content is invalid')
+ p 'OK: large_unary'
+ end
+
+ # TESTING:
+ # PASSED
+ # ruby server
+ # FAILED
+ def client_streaming
+ msg_sizes = [27182, 8, 1828, 45904]
+ wanted_aggregate_size = 74922
+ reqs = msg_sizes.map do |x|
+ req = Payload.new(:body => nulls(x))
+ StreamingInputCallRequest.new(:payload => req)
+ end
+ resp = @stub.streaming_input_call(reqs)
+ assert_equal(wanted_aggregate_size, resp.aggregated_payload_size,
+ 'client_streaming: aggregate payload size is incorrect')
+ p 'OK: client_streaming'
+ end
+
+ # TESTING:
+ # PASSED
+ # ruby server
+ # FAILED
+ def server_streaming
+ msg_sizes = [31415, 9, 2653, 58979]
+ response_spec = msg_sizes.map { |s| ResponseParameters.new(:size => s) }
+ req = StreamingOutputCallRequest.new(:response_type => COMPRESSABLE,
+ :response_parameters => response_spec)
+ resps = @stub.streaming_output_call(req)
+ resps.each_with_index do |r, i|
+ assert i < msg_sizes.length, 'too many responses'
+ assert_equal(COMPRESSABLE, r.payload.type, 'payload type is wrong')
+ assert_equal(msg_sizes[i], r.payload.body.length,
+ 'payload body #{i} has the wrong length')
+ end
+ p 'OK: server_streaming'
+ end
+
+ # TESTING:
+ # PASSED
+ # ruby server
+ # FAILED
+ #
+ # TODO(temiola): update this test to stay consistent with the java test's
+ # interpretation of the test spec.
+ def ping_pong
+ req_cls, param_cls= StreamingOutputCallRequest, ResponseParameters # short
+ msg_sizes = [[27182, 31415], [8, 9], [1828, 2653], [45904, 58979]]
+ reqs = msg_sizes.map do |x|
+ req_size, resp_size = x
+ req_cls.new(:payload => Payload.new(:body => nulls(req_size)),
+ :response_type => COMPRESSABLE,
+ :response_parameters => param_cls.new(:size => resp_size))
+ end
+ resps = @stub.full_duplex_call(reqs)
+ resps.each_with_index do |r, i|
+ assert i < msg_sizes.length, 'too many responses'
+ assert_equal(COMPRESSABLE, r.payload.type, 'payload type is wrong')
+ assert_equal(msg_sizes[i][1], r.payload.body.length,
+ 'payload body #{i} has the wrong length')
+ end
+ p 'OK ping_pong'
+ end
+
+end
+
+# validates the the command line options, returning them as a Hash.
+def parse_options
+ options = {
+ 'server_host' => nil,
+ 'server_port' => nil,
+ 'test_case' => nil,
+ }
+ OptionParser.new do |opts|
+ opts.banner = 'Usage: --server_host <server_host> --server_port server_port'
+ opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
+ options['server_host'] = v
+ end
+ opts.on('--server_port SERVER_PORT', 'server port') do |v|
+ options['server_port'] = v
+ end
+ # instance_methods(false) gives only the methods defined in that class
+ test_cases = NamedTests.instance_methods(false).map { |t| t.to_s }
+ test_case_list = test_cases.join(',')
+ opts.on("--test_case CODE", test_cases, {}, "select a test_case",
+ " (#{test_case_list})") do |v|
+ options['test_case'] = v
+ end
+ end.parse!
+
+ ['server_host', 'server_port', 'test_case'].each do |arg|
+ if options[arg].nil?
+ raise OptionParser::MissingArgument.new("please specify --#{arg}")
+ end
+ end
+ options
+end
+
+def main
+ opts = parse_options
+ stub = create_stub(opts['server_host'], opts['server_port'])
+ NamedTests.new(stub).method(opts['test_case']).call
+end
+
+main
diff --git a/src/ruby/bin/interop/interop_server.rb b/src/ruby/bin/interop/interop_server.rb
new file mode 100644
index 0000000000..9e5c20d443
--- /dev/null
+++ b/src/ruby/bin/interop/interop_server.rb
@@ -0,0 +1,185 @@
+# Copyright 2014, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#!/usr/bin/env ruby
+#
+# interop_server is a Testing app that runs a gRPC interop testing server.
+#
+# It helps validate interoperation b/w gRPC in different environments
+#
+# Helps validate interoperation b/w different gRPC implementations.
+#
+# Usage: $ path/to/interop_server.rb --port
+
+this_dir = File.expand_path(File.dirname(__FILE__))
+lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
+$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
+$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
+
+require 'forwardable'
+require 'optparse'
+
+require 'grpc'
+require 'grpc/generic/service'
+require 'grpc/generic/rpc_server'
+
+require 'third_party/stubby/testing/proto/test.pb'
+require 'third_party/stubby/testing/proto/messages.pb'
+
+# loads the certificates by the test server.
+def load_test_certs
+ this_dir = File.expand_path(File.dirname(__FILE__))
+ data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
+ files = ['ca.pem', 'server1.key', 'server1.pem']
+ files.map { |f| File.open(File.join(data_dir, f)).read }
+end
+
+# creates a ServerCredentials from the test certificates.
+def test_server_creds
+ certs = load_test_certs
+ server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
+end
+
+# produces a string of null chars (\0) of length l.
+def nulls(l)
+ raise 'requires #{l} to be +ve' if l < 0
+ [].pack('x' * l)
+end
+
+# A EnumeratorQueue wraps a Queue yielding the items added to it via each_item.
+class EnumeratorQueue
+ extend Forwardable
+ def_delegators :@q, :push
+
+ def initialize(sentinel)
+ @q = Queue.new
+ @sentinel = sentinel
+ end
+
+ def each_item
+ return enum_for(:each_item) unless block_given?
+ loop do
+ r = @q.pop
+ break if r.equal?(@sentinel)
+ raise r if r.is_a?Exception
+ yield r
+ end
+ end
+end
+
+# A runnable implementation of the schema-specified testing service, with each
+# service method implemented as required by the interop testing spec.
+class TestTarget < Grpc::Testing::TestService::Service
+ include Grpc::Testing
+ include Grpc::Testing::PayloadType
+
+ def empty_call(empty, call)
+ Proto::Empty.new
+ end
+
+ def unary_call(simple_req, call)
+ req_size = simple_req.response_size
+ SimpleResponse.new(:payload => Payload.new(:type => COMPRESSABLE,
+ :body => nulls(req_size)))
+ end
+
+ def streaming_input_call(call)
+ sizes = call.each_remote_read.map { |x| x.payload.body.length }
+ sum = sizes.inject { |sum,x| sum + x }
+ StreamingInputCallResponse.new(:aggregated_payload_size => sum)
+ end
+
+ def streaming_output_call(req, call)
+ cls = StreamingOutputCallResponse
+ req.response_parameters.map do |p|
+ cls.new(:payload => Payload.new(:type => req.response_type,
+ :body => nulls(p.size)))
+ end
+ end
+
+ def full_duplex_call(reqs)
+ # reqs is a lazy Enumerator of the requests sent by the client.
+ q = EnumeratorQueue.new(self)
+ cls = StreamingOutputCallResponse
+ t = Thread.new do
+ begin
+ reqs.each do |req|
+ logger.info("read #{req.inspect}")
+ resp_size = req.response_parameters[0].size
+ resp = cls.new(:payload => Payload.new(:type => req.response_type,
+ :body => nulls(resp_size)))
+ q.push(resp)
+ end
+ logger.info('finished reads')
+ q.push(self)
+ rescue StandardError => e
+ q.push(e) # share the exception with the enumerator
+ end
+ end
+ q.each_item
+ end
+
+ def half_duplex_call(reqs)
+ # TODO(temiola): clarify the behaviour of the half_duplex_call, it's not
+ # currently used in any tests
+ full_duplex_call(reqs)
+ end
+
+end
+
+# validates the the command line options, returning them as a Hash.
+def parse_options
+ options = {
+ 'port' => nil,
+ }
+ OptionParser.new do |opts|
+ opts.banner = 'Usage: --port port'
+ opts.on('--port PORT', 'server port') do |v|
+ options['port'] = v
+ end
+ end.parse!
+
+ if options['port'].nil?
+ raise OptionParser::MissingArgument.new("please specify --port")
+ end
+ options
+end
+
+def main
+ opts = parse_options
+ host = "0.0.0.0:#{opts['port']}"
+ s = GRPC::RpcServer.new(creds: test_server_creds)
+ s.add_http2_port(host, true)
+ logger.info("... running securely on #{host}")
+
+ s.handle(TestTarget)
+ s.run
+end
+
+main
diff --git a/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb b/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb
new file mode 100755
index 0000000000..eadd1d4ceb
--- /dev/null
+++ b/src/ruby/bin/interop/net/proto2/bridge/proto/message_set.pb.rb
@@ -0,0 +1,14 @@
+## Generated from net/proto2/bridge/proto/message_set.proto for proto2.bridge
+require 'beefcake'
+
+module Proto2
+ module Bridge
+
+ class MessageSet
+ include Beefcake::Message
+ end
+
+ class MessageSet
+ end
+ end
+end
diff --git a/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb b/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb
new file mode 100755
index 0000000000..2aa0c76509
--- /dev/null
+++ b/src/ruby/bin/interop/net/proto2/proto/empty.pb.rb
@@ -0,0 +1,12 @@
+## Generated from net/proto2/proto/empty.proto for proto2
+require 'beefcake'
+
+module Proto2
+
+ class Empty
+ include Beefcake::Message
+ end
+
+ class Empty
+ end
+end
diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb
new file mode 100755
index 0000000000..9a913f93e5
--- /dev/null
+++ b/src/ruby/bin/interop/third_party/stubby/testing/proto/messages.pb.rb
@@ -0,0 +1,94 @@
+## Generated from third_party/stubby/testing/proto/messages.proto for grpc.testing
+require 'beefcake'
+
+require 'net/proto2/bridge/proto/message_set.pb'
+
+module Grpc
+ module Testing
+
+ module PayloadType
+ COMPRESSABLE = 0
+ UNCOMPRESSABLE = 1
+ RANDOM = 2
+ end
+
+ class Payload
+ include Beefcake::Message
+ end
+
+ class SimpleRequest
+ include Beefcake::Message
+ end
+
+ class SimpleResponse
+ include Beefcake::Message
+ end
+
+ class SimpleContext
+ include Beefcake::Message
+ end
+
+ class StreamingInputCallRequest
+ include Beefcake::Message
+ end
+
+ class StreamingInputCallResponse
+ include Beefcake::Message
+ end
+
+ class ResponseParameters
+ include Beefcake::Message
+ end
+
+ class StreamingOutputCallRequest
+ include Beefcake::Message
+ end
+
+ class StreamingOutputCallResponse
+ include Beefcake::Message
+ end
+
+ class Payload
+ optional :type, PayloadType, 1
+ optional :body, :bytes, 2
+ end
+
+ class SimpleRequest
+ optional :response_type, PayloadType, 1
+ optional :response_size, :int32, 2
+ optional :payload, Payload, 3
+ end
+
+ class SimpleResponse
+ optional :payload, Payload, 1
+ optional :effective_gaia_user_id, :int64, 2
+ end
+
+ class SimpleContext
+ optional :value, :string, 1
+ end
+
+ class StreamingInputCallRequest
+ optional :payload, Payload, 1
+ end
+
+ class StreamingInputCallResponse
+ optional :aggregated_payload_size, :int32, 1
+ end
+
+ class ResponseParameters
+ optional :size, :int32, 1
+ optional :interval_us, :int32, 2
+ end
+
+ class StreamingOutputCallRequest
+ optional :response_type, PayloadType, 1
+ repeated :response_parameters, ResponseParameters, 2
+ optional :payload, Payload, 3
+ end
+
+ class StreamingOutputCallResponse
+ optional :payload, Payload, 1
+ end
+ end
+end
diff --git a/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb b/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb
new file mode 100755
index 0000000000..2e21460fe6
--- /dev/null
+++ b/src/ruby/bin/interop/third_party/stubby/testing/proto/test.pb.rb
@@ -0,0 +1,30 @@
+## Generated from third_party/stubby/testing/proto/test.proto for grpc.testing
+require 'beefcake'
+require 'grpc'
+
+require 'third_party/stubby/testing/proto/messages.pb'
+require 'net/proto2/proto/empty.pb'
+
+module Grpc
+ module Testing
+
+ module TestService
+
+ class Service
+ include GRPC::GenericService
+
+ self.marshal_class_method = :encode
+ self.unmarshal_class_method = :decode
+
+ rpc :EmptyCall, Proto2::Empty, Proto2::Empty
+ rpc :UnaryCall, SimpleRequest, SimpleResponse
+ rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse)
+ rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse
+ rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse)
+ rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse)
+ end
+ Stub = Service.rpc_stub_class
+
+ end
+ end
+end
diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec
index c63c80dd58..b535de4946 100755
--- a/src/ruby/grpc.gemspec
+++ b/src/ruby/grpc.gemspec
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
s.add_dependency 'xray'
s.add_dependency 'logging', '~> 1.8'
s.add_dependency 'beefcake', '~> 1.1'
+ s.add_dependency 'minitest', '~> 5.4' # not a dev dependency, used by the interop tests
s.add_development_dependency "bundler", "~> 1.7"
s.add_development_dependency "rake", "~> 10.0"
diff --git a/src/ruby/lib/grpc/generic/rpc_desc.rb b/src/ruby/lib/grpc/generic/rpc_desc.rb
index eef886a72f..b41543e084 100644
--- a/src/ruby/lib/grpc/generic/rpc_desc.rb
+++ b/src/ruby/lib/grpc/generic/rpc_desc.rb
@@ -90,7 +90,7 @@ module GRPC
# error code and detail message.
logger.debug("app error: #{active_call}, status:#{e.code}:#{e.details}")
send_status(active_call, e.code, e.details)
- rescue CallError => e
+ rescue Core::CallError => e
# This is raised by GRPC internals but should rarely, if ever happen.
# Log it, but don't notify the other endpoint..
logger.warn("failed call: #{active_call}\n#{e}")
@@ -99,7 +99,7 @@ module GRPC
# event. Send a status of deadline exceeded
logger.warn("late call: #{active_call}")
send_status(active_call, DEADLINE_EXCEEDED, 'late')
- rescue EventError => e
+ rescue Core::EventError => e
# This is raised by GRPC internals but should rarely, if ever happen.
# Log it, but don't notify the other endpoint..
logger.warn("failed call: #{active_call}\n#{e}")