| Index: third_party/grpc/src/ruby/spec/generic/rpc_desc_spec.rb
|
| diff --git a/third_party/grpc/src/ruby/spec/generic/rpc_desc_spec.rb b/third_party/grpc/src/ruby/spec/generic/rpc_desc_spec.rb
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..083632a080fbe3f4b7a6e1688f1b412500c93c28
|
| --- /dev/null
|
| +++ b/third_party/grpc/src/ruby/spec/generic/rpc_desc_spec.rb
|
| @@ -0,0 +1,331 @@
|
| +# Copyright 2015, Google Inc.
|
| +# All rights reserved.
|
| +#
|
| +# Redistribution and use in source and binary forms, with or without
|
| +# modification, are permitted provided that the following conditions are
|
| +# met:
|
| +#
|
| +# * Redistributions of source code must retain the above copyright
|
| +# notice, this list of conditions and the following disclaimer.
|
| +# * Redistributions in binary form must reproduce the above
|
| +# copyright notice, this list of conditions and the following disclaimer
|
| +# in the documentation and/or other materials provided with the
|
| +# distribution.
|
| +# * Neither the name of Google Inc. nor the names of its
|
| +# contributors may be used to endorse or promote products derived from
|
| +# this software without specific prior written permission.
|
| +#
|
| +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +require 'grpc'
|
| +require 'grpc/generic/rpc_desc'
|
| +
|
| +describe GRPC::RpcDesc do
|
| + RpcDesc = GRPC::RpcDesc
|
| + Stream = RpcDesc::Stream
|
| + OK = GRPC::Core::StatusCodes::OK
|
| + INTERNAL = GRPC::Core::StatusCodes::INTERNAL
|
| + UNKNOWN = GRPC::Core::StatusCodes::UNKNOWN
|
| + CallError = GRPC::Core::CallError
|
| +
|
| + before(:each) do
|
| + @request_response = RpcDesc.new('rr', Object.new, Object.new, 'encode',
|
| + 'decode')
|
| + @client_streamer = RpcDesc.new('cs', Stream.new(Object.new), Object.new,
|
| + 'encode', 'decode')
|
| + @server_streamer = RpcDesc.new('ss', Object.new, Stream.new(Object.new),
|
| + 'encode', 'decode')
|
| + @bidi_streamer = RpcDesc.new('ss', Stream.new(Object.new),
|
| + Stream.new(Object.new), 'encode', 'decode')
|
| + @bs_code = INTERNAL
|
| + @no_reason = 'no reason given'
|
| + @ok_response = Object.new
|
| + end
|
| +
|
| + shared_examples 'it handles errors' do
|
| + it 'sends the specified status if BadStatus is raised' do
|
| + expect(@call).to receive(:remote_read).once.and_return(Object.new)
|
| + expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
|
| + {})
|
| + this_desc.run_server_method(@call, method(:bad_status))
|
| + end
|
| +
|
| + it 'sends status UNKNOWN if other StandardErrors are raised' do
|
| + expect(@call).to receive(:remote_read).once.and_return(Object.new)
|
| + expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason,
|
| + false, {})
|
| + this_desc.run_server_method(@call, method(:other_error))
|
| + end
|
| +
|
| + it 'absorbs CallError with no further action' do
|
| + expect(@call).to receive(:remote_read).once.and_raise(CallError)
|
| + blk = proc do
|
| + this_desc.run_server_method(@call, method(:fake_reqresp))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| + end
|
| +
|
| + describe '#run_server_method' do
|
| + let(:fake_md) { { k1: 'v1', k2: 'v2' } }
|
| + describe 'for request responses' do
|
| + let(:this_desc) { @request_response }
|
| + before(:each) do
|
| + @call = double('active_call')
|
| + allow(@call).to receive(:single_req_view).and_return(@call)
|
| + end
|
| +
|
| + it_behaves_like 'it handles errors'
|
| +
|
| + it 'sends a response and closes the stream if there no errors' do
|
| + req = Object.new
|
| + expect(@call).to receive(:remote_read).once.and_return(req)
|
| + expect(@call).to receive(:remote_send).once.with(@ok_response)
|
| + expect(@call).to receive(:output_metadata).and_return(fake_md)
|
| + expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
|
| + **fake_md)
|
| + this_desc.run_server_method(@call, method(:fake_reqresp))
|
| + end
|
| + end
|
| +
|
| + describe 'for client streamers' do
|
| + before(:each) do
|
| + @call = double('active_call')
|
| + allow(@call).to receive(:multi_req_view).and_return(@call)
|
| + end
|
| +
|
| + it 'sends the specified status if BadStatus is raised' do
|
| + expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
|
| + {})
|
| + @client_streamer.run_server_method(@call, method(:bad_status_alt))
|
| + end
|
| +
|
| + it 'sends status UNKNOWN if other StandardErrors are raised' do
|
| + expect(@call).to receive(:send_status) .once.with(UNKNOWN, @no_reason,
|
| + false, {})
|
| + @client_streamer.run_server_method(@call, method(:other_error_alt))
|
| + end
|
| +
|
| + it 'absorbs CallError with no further action' do
|
| + expect(@call).to receive(:remote_send).once.and_raise(CallError)
|
| + blk = proc do
|
| + @client_streamer.run_server_method(@call, method(:fake_clstream))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| +
|
| + it 'sends a response and closes the stream if there no errors' do
|
| + expect(@call).to receive(:remote_send).once.with(@ok_response)
|
| + expect(@call).to receive(:output_metadata).and_return(fake_md)
|
| + expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
|
| + **fake_md)
|
| + @client_streamer.run_server_method(@call, method(:fake_clstream))
|
| + end
|
| + end
|
| +
|
| + describe 'for server streaming' do
|
| + let(:this_desc) { @request_response }
|
| + before(:each) do
|
| + @call = double('active_call')
|
| + allow(@call).to receive(:single_req_view).and_return(@call)
|
| + end
|
| +
|
| + it_behaves_like 'it handles errors'
|
| +
|
| + it 'sends a response and closes the stream if there no errors' do
|
| + req = Object.new
|
| + expect(@call).to receive(:remote_read).once.and_return(req)
|
| + expect(@call).to receive(:remote_send).twice.with(@ok_response)
|
| + expect(@call).to receive(:output_metadata).and_return(fake_md)
|
| + expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
|
| + **fake_md)
|
| + @server_streamer.run_server_method(@call, method(:fake_svstream))
|
| + end
|
| + end
|
| +
|
| + describe 'for bidi streamers' do
|
| + before(:each) do
|
| + @call = double('active_call')
|
| + enq_th, rwl_th = double('enqueue_th'), ('read_write_loop_th')
|
| + allow(enq_th).to receive(:join)
|
| + allow(rwl_th).to receive(:join)
|
| + end
|
| +
|
| + it 'sends the specified status if BadStatus is raised' do
|
| + e = GRPC::BadStatus.new(@bs_code, 'NOK')
|
| + expect(@call).to receive(:run_server_bidi).and_raise(e)
|
| + expect(@call).to receive(:send_status).once.with(@bs_code, 'NOK', false,
|
| + {})
|
| + @bidi_streamer.run_server_method(@call, method(:bad_status_alt))
|
| + end
|
| +
|
| + it 'sends status UNKNOWN if other StandardErrors are raised' do
|
| + expect(@call).to receive(:run_server_bidi).and_raise(StandardError)
|
| + expect(@call).to receive(:send_status).once.with(UNKNOWN, @no_reason,
|
| + false, {})
|
| + @bidi_streamer.run_server_method(@call, method(:other_error_alt))
|
| + end
|
| +
|
| + it 'closes the stream if there no errors' do
|
| + expect(@call).to receive(:run_server_bidi)
|
| + expect(@call).to receive(:output_metadata).and_return(fake_md)
|
| + expect(@call).to receive(:send_status).once.with(OK, 'OK', true,
|
| + **fake_md)
|
| + @bidi_streamer.run_server_method(@call, method(:fake_bidistream))
|
| + end
|
| + end
|
| + end
|
| +
|
| + describe '#assert_arity_matches' do
|
| + def no_arg
|
| + end
|
| +
|
| + def fake_clstream(_arg)
|
| + end
|
| +
|
| + def fake_svstream(_arg1, _arg2)
|
| + end
|
| +
|
| + it 'raises when a request_response does not have 2 args' do
|
| + [:fake_clstream, :no_arg].each do |mth|
|
| + blk = proc do
|
| + @request_response.assert_arity_matches(method(mth))
|
| + end
|
| + expect(&blk).to raise_error
|
| + end
|
| + end
|
| +
|
| + it 'passes when a request_response has 2 args' do
|
| + blk = proc do
|
| + @request_response.assert_arity_matches(method(:fake_svstream))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| +
|
| + it 'raises when a server_streamer does not have 2 args' do
|
| + [:fake_clstream, :no_arg].each do |mth|
|
| + blk = proc do
|
| + @server_streamer.assert_arity_matches(method(mth))
|
| + end
|
| + expect(&blk).to raise_error
|
| + end
|
| + end
|
| +
|
| + it 'passes when a server_streamer has 2 args' do
|
| + blk = proc do
|
| + @server_streamer.assert_arity_matches(method(:fake_svstream))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| +
|
| + it 'raises when a client streamer does not have 1 arg' do
|
| + [:fake_svstream, :no_arg].each do |mth|
|
| + blk = proc do
|
| + @client_streamer.assert_arity_matches(method(mth))
|
| + end
|
| + expect(&blk).to raise_error
|
| + end
|
| + end
|
| +
|
| + it 'passes when a client_streamer has 1 arg' do
|
| + blk = proc do
|
| + @client_streamer.assert_arity_matches(method(:fake_clstream))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| +
|
| + it 'raises when a bidi streamer does not have 1 arg' do
|
| + [:fake_svstream, :no_arg].each do |mth|
|
| + blk = proc do
|
| + @bidi_streamer.assert_arity_matches(method(mth))
|
| + end
|
| + expect(&blk).to raise_error
|
| + end
|
| + end
|
| +
|
| + it 'passes when a bidi streamer has 1 arg' do
|
| + blk = proc do
|
| + @bidi_streamer.assert_arity_matches(method(:fake_clstream))
|
| + end
|
| + expect(&blk).to_not raise_error
|
| + end
|
| + end
|
| +
|
| + describe '#request_response?' do
|
| + it 'is true only input and output are both not Streams' do
|
| + expect(@request_response.request_response?).to be(true)
|
| + expect(@client_streamer.request_response?).to be(false)
|
| + expect(@bidi_streamer.request_response?).to be(false)
|
| + expect(@server_streamer.request_response?).to be(false)
|
| + end
|
| + end
|
| +
|
| + describe '#client_streamer?' do
|
| + it 'is true only when input is a Stream and output is not a Stream' do
|
| + expect(@client_streamer.client_streamer?).to be(true)
|
| + expect(@request_response.client_streamer?).to be(false)
|
| + expect(@server_streamer.client_streamer?).to be(false)
|
| + expect(@bidi_streamer.client_streamer?).to be(false)
|
| + end
|
| + end
|
| +
|
| + describe '#server_streamer?' do
|
| + it 'is true only when output is a Stream and input is not a Stream' do
|
| + expect(@server_streamer.server_streamer?).to be(true)
|
| + expect(@client_streamer.server_streamer?).to be(false)
|
| + expect(@request_response.server_streamer?).to be(false)
|
| + expect(@bidi_streamer.server_streamer?).to be(false)
|
| + end
|
| + end
|
| +
|
| + describe '#bidi_streamer?' do
|
| + it 'is true only when output is a Stream and input is a Stream' do
|
| + expect(@bidi_streamer.bidi_streamer?).to be(true)
|
| + expect(@server_streamer.bidi_streamer?).to be(false)
|
| + expect(@client_streamer.bidi_streamer?).to be(false)
|
| + expect(@request_response.bidi_streamer?).to be(false)
|
| + end
|
| + end
|
| +
|
| + def fake_reqresp(_req, _call)
|
| + @ok_response
|
| + end
|
| +
|
| + def fake_clstream(_call)
|
| + @ok_response
|
| + end
|
| +
|
| + def fake_svstream(_req, _call)
|
| + [@ok_response, @ok_response]
|
| + end
|
| +
|
| + def fake_bidistream(an_array)
|
| + an_array
|
| + end
|
| +
|
| + def bad_status(_req, _call)
|
| + fail GRPC::BadStatus.new(@bs_code, 'NOK')
|
| + end
|
| +
|
| + def other_error(_req, _call)
|
| + fail(ArgumentError, 'other error')
|
| + end
|
| +
|
| + def bad_status_alt(_call)
|
| + fail GRPC::BadStatus.new(@bs_code, 'NOK')
|
| + end
|
| +
|
| + def other_error_alt(_call)
|
| + fail(ArgumentError, 'other error')
|
| + end
|
| +end
|
|
|