|  | @@ -30,7 +30,6 @@
 | 
	
		
			
				|  |  |  require 'grpc'
 | 
	
		
			
				|  |  |  require 'spec_helper'
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -include GRPC::Core::CompletionType
 | 
	
		
			
				|  |  |  include GRPC::Core
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def load_test_certs
 | 
	
	
		
			
				|  | @@ -40,6 +39,8 @@ def load_test_certs
 | 
	
		
			
				|  |  |  end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  shared_context 'setup: tags' do
 | 
	
		
			
				|  |  | +  let(:sent_message) { 'sent message' }
 | 
	
		
			
				|  |  | +  let(:reply_text) { 'the reply' }
 | 
	
		
			
				|  |  |    before(:example) do
 | 
	
		
			
				|  |  |      @server_finished_tag = Object.new
 | 
	
		
			
				|  |  |      @client_finished_tag = Object.new
 | 
	
	
		
			
				|  | @@ -52,153 +53,136 @@ shared_context 'setup: tags' do
 | 
	
		
			
				|  |  |      Time.now + 2
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  def expect_next_event_on(queue, type, tag)
 | 
	
		
			
				|  |  | -    ev = queue.pluck(tag, deadline)
 | 
	
		
			
				|  |  | -    if type.nil?
 | 
	
		
			
				|  |  | -      expect(ev).to be_nil
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -      expect(ev).to_not be_nil
 | 
	
		
			
				|  |  | -      expect(ev.type).to be(type)
 | 
	
		
			
				|  |  | -    end
 | 
	
		
			
				|  |  | -    ev
 | 
	
		
			
				|  |  | -  end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    def server_allows_client_to_proceed
 | 
	
		
			
				|  |  | -    @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -    ev = @server_queue.pluck(@server_tag, deadline)
 | 
	
		
			
				|  |  | -    expect(ev).not_to be_nil
 | 
	
		
			
				|  |  | -    expect(ev.type).to be(SERVER_RPC_NEW)
 | 
	
		
			
				|  |  | -    server_call = ev.call
 | 
	
		
			
				|  |  | -    server_call.server_accept(@server_queue, @server_finished_tag)
 | 
	
		
			
				|  |  | -    server_call.server_end_initial_metadata
 | 
	
		
			
				|  |  | +    recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
 | 
	
		
			
				|  |  | +    expect(recvd_rpc).to_not eq nil
 | 
	
		
			
				|  |  | +    server_call = recvd_rpc.call
 | 
	
		
			
				|  |  | +    ops = { CallOps::SEND_INITIAL_METADATA => {} }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline, ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_metadata).to be true
 | 
	
		
			
				|  |  |      server_call
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  def server_responds_with(server_call, reply_text)
 | 
	
		
			
				|  |  | -    reply = ByteBuffer.new(reply_text)
 | 
	
		
			
				|  |  | -    server_call.start_read(@server_tag)
 | 
	
		
			
				|  |  | -    ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
 | 
	
		
			
				|  |  | -    expect(ev.type).to be(READ)
 | 
	
		
			
				|  |  | -    server_call.start_write(reply, @server_tag)
 | 
	
		
			
				|  |  | -    ev = @server_queue.pluck(@server_tag, TimeConsts::INFINITE_FUTURE)
 | 
	
		
			
				|  |  | -    expect(ev).not_to be_nil
 | 
	
		
			
				|  |  | -    expect(ev.type).to be(WRITE_ACCEPTED)
 | 
	
		
			
				|  |  | -  end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  def client_sends(call, sent = 'a message')
 | 
	
		
			
				|  |  | -    req = ByteBuffer.new(sent)
 | 
	
		
			
				|  |  | -    call.start_write(req, @tag)
 | 
	
		
			
				|  |  | -    ev = @client_queue.pluck(@tag, TimeConsts::INFINITE_FUTURE)
 | 
	
		
			
				|  |  | -    expect(ev).not_to be_nil
 | 
	
		
			
				|  |  | -    expect(ev.type).to be(WRITE_ACCEPTED)
 | 
	
		
			
				|  |  | -    sent
 | 
	
		
			
				|  |  | -  end
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    def new_client_call
 | 
	
		
			
				|  |  | -    @ch.create_call('/method', 'foo.test.google.fr', deadline)
 | 
	
		
			
				|  |  | +    @ch.create_call(@client_queue, '/method', 'foo.test.google.fr', deadline)
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  shared_examples 'basic GRPC message delivery is OK' do
 | 
	
		
			
				|  |  | +  include GRPC::Core
 | 
	
		
			
				|  |  |    include_context 'setup: tags'
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  it 'servers receive requests from clients and start responding' do
 | 
	
		
			
				|  |  | -    reply = ByteBuffer.new('the server payload')
 | 
	
		
			
				|  |  | +  it 'servers receive requests from clients and can respond' do
 | 
	
		
			
				|  |  |      call = new_client_call
 | 
	
		
			
				|  |  | -    call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # check the server rpc new was received
 | 
	
		
			
				|  |  | -    # @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -    # ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # accept the call
 | 
	
		
			
				|  |  | -    # server_call = ev.call
 | 
	
		
			
				|  |  | -    # server_call.server_accept(@server_queue, @server_finished_tag)
 | 
	
		
			
				|  |  | -    # server_call.server_end_initial_metadata
 | 
	
		
			
				|  |  | -    server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # client sends a message
 | 
	
		
			
				|  |  | -    msg = client_sends(call)
 | 
	
		
			
				|  |  | +    client_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_INITIAL_METADATA => {},
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => sent_message
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                  client_ops)
 | 
	
		
			
				|  |  | +    expect(batch_result.send_metadata).to be true
 | 
	
		
			
				|  |  | +    expect(batch_result.send_message).to be true
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # confirm the server can read the inbound message
 | 
	
		
			
				|  |  | -    server_call.start_read(@server_tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@server_queue, READ, @server_tag)
 | 
	
		
			
				|  |  | -    expect(ev.result.to_s).to eq(msg)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    #  the server response
 | 
	
		
			
				|  |  | -    server_call.start_write(reply, @server_tag)
 | 
	
		
			
				|  |  | -    expect_next_event_on(@server_queue, WRITE_ACCEPTED, @server_tag)
 | 
	
		
			
				|  |  | +    server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | +    server_ops = {
 | 
	
		
			
				|  |  | +      CallOps::RECV_MESSAGE => nil
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                      server_ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.message).to eq(sent_message)
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    it 'responses written by servers are received by the client' do
 | 
	
		
			
				|  |  |      call = new_client_call
 | 
	
		
			
				|  |  | -    call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -    server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | -    client_sends(call)
 | 
	
		
			
				|  |  | -    server_responds_with(server_call, 'server_response')
 | 
	
		
			
				|  |  | +    client_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_INITIAL_METADATA => {},
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => sent_message
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                  client_ops)
 | 
	
		
			
				|  |  | +    expect(batch_result.send_metadata).to be true
 | 
	
		
			
				|  |  | +    expect(batch_result.send_message).to be true
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    call.start_read(@tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@client_queue, READ, @tag)
 | 
	
		
			
				|  |  | -    expect(ev.result.to_s).to eq('server_response')
 | 
	
		
			
				|  |  | +    # confirm the server can read the inbound message
 | 
	
		
			
				|  |  | +    server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | +    server_ops = {
 | 
	
		
			
				|  |  | +      CallOps::RECV_MESSAGE => nil,
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => reply_text
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                      server_ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.message).to eq(sent_message)
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_message).to be true
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    it 'servers can ignore a client write and send a status' do
 | 
	
		
			
				|  |  |      call = new_client_call
 | 
	
		
			
				|  |  | -    call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # check the server rpc new was received
 | 
	
		
			
				|  |  | -    @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | -    expect(ev.tag).to be(@server_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # accept the call - need to do this to sent status.
 | 
	
		
			
				|  |  | -    server_call = ev.call
 | 
	
		
			
				|  |  | -    server_call.server_accept(@server_queue, @server_finished_tag)
 | 
	
		
			
				|  |  | -    server_call.server_end_initial_metadata
 | 
	
		
			
				|  |  | -    server_call.start_write_status(StatusCodes::NOT_FOUND, 'not found',
 | 
	
		
			
				|  |  | -                                   @server_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # Client sends some data
 | 
	
		
			
				|  |  | -    client_sends(call)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # client gets an empty response for the read, preceeded by some metadata.
 | 
	
		
			
				|  |  | -    call.start_read(@tag)
 | 
	
		
			
				|  |  | -    expect_next_event_on(@client_queue, CLIENT_METADATA_READ,
 | 
	
		
			
				|  |  | -                         @client_metadata_tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@client_queue, READ, @tag)
 | 
	
		
			
				|  |  | -    expect(ev.tag).to be(@tag)
 | 
	
		
			
				|  |  | -    expect(ev.result.to_s).to eq('')
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # finally, after client sends writes_done, they get the finished.
 | 
	
		
			
				|  |  | -    call.writes_done(@tag)
 | 
	
		
			
				|  |  | -    expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag)
 | 
	
		
			
				|  |  | -    expect(ev.result.code).to eq(StatusCodes::NOT_FOUND)
 | 
	
		
			
				|  |  | +    client_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_INITIAL_METADATA => {},
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => sent_message
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                  client_ops)
 | 
	
		
			
				|  |  | +    expect(batch_result.send_metadata).to be true
 | 
	
		
			
				|  |  | +    expect(batch_result.send_message).to be true
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # confirm the server can read the inbound message
 | 
	
		
			
				|  |  | +    the_status = Struct::Status.new(StatusCodes::OK, 'OK')
 | 
	
		
			
				|  |  | +    server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | +    server_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_STATUS_FROM_SERVER => the_status
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                      server_ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.message).to eq nil
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_status).to be true
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    it 'completes calls by sending status to client and server' do
 | 
	
		
			
				|  |  |      call = new_client_call
 | 
	
		
			
				|  |  | -    call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | +    client_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_INITIAL_METADATA => {},
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => sent_message
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                  client_ops)
 | 
	
		
			
				|  |  | +    expect(batch_result.send_metadata).to be true
 | 
	
		
			
				|  |  | +    expect(batch_result.send_message).to be true
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # confirm the server can read the inbound message and respond
 | 
	
		
			
				|  |  | +    the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
 | 
	
		
			
				|  |  |      server_call = server_allows_client_to_proceed
 | 
	
		
			
				|  |  | -    client_sends(call)
 | 
	
		
			
				|  |  | -    server_responds_with(server_call, 'server_response')
 | 
	
		
			
				|  |  | -    server_call.start_write_status(10_101, 'status code is 10101', @server_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # first the client says writes are done
 | 
	
		
			
				|  |  | -    call.start_read(@tag)
 | 
	
		
			
				|  |  | -    expect_next_event_on(@client_queue, READ, @tag)
 | 
	
		
			
				|  |  | -    call.writes_done(@tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # but nothing happens until the server sends a status
 | 
	
		
			
				|  |  | -    expect_next_event_on(@server_queue, FINISH_ACCEPTED, @server_tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@server_queue, FINISHED, @server_finished_tag)
 | 
	
		
			
				|  |  | -    expect(ev.result).to be_a(Struct::Status)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    # client gets FINISHED
 | 
	
		
			
				|  |  | -    expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag)
 | 
	
		
			
				|  |  | -    ev = expect_next_event_on(@client_queue, FINISHED, @client_finished_tag)
 | 
	
		
			
				|  |  | -    expect(ev.result.details).to eq('status code is 10101')
 | 
	
		
			
				|  |  | -    expect(ev.result.code).to eq(10_101)
 | 
	
		
			
				|  |  | +    server_ops = {
 | 
	
		
			
				|  |  | +      CallOps::RECV_MESSAGE => nil,
 | 
	
		
			
				|  |  | +      CallOps::SEND_MESSAGE => reply_text,
 | 
	
		
			
				|  |  | +      CallOps::SEND_STATUS_FROM_SERVER => the_status
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                      server_ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.message).to eq sent_message
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_status).to be true
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_message).to be true
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # confirm the client can receive the server response and status.
 | 
	
		
			
				|  |  | +    client_ops = {
 | 
	
		
			
				|  |  | +      CallOps::SEND_CLOSE_FROM_CLIENT => nil,
 | 
	
		
			
				|  |  | +      CallOps::RECV_MESSAGE => nil,
 | 
	
		
			
				|  |  | +      CallOps::RECV_STATUS_ON_CLIENT => nil
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                  client_ops)
 | 
	
		
			
				|  |  | +    expect(batch_result.send_close).to be true
 | 
	
		
			
				|  |  | +    expect(batch_result.message).to eq reply_text
 | 
	
		
			
				|  |  | +    expect(batch_result.status).to eq the_status
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # confirm the server can receive the client close.
 | 
	
		
			
				|  |  | +    server_ops = {
 | 
	
		
			
				|  |  | +      CallOps::RECV_CLOSE_ON_SERVER => nil
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                      server_ops)
 | 
	
		
			
				|  |  | +    expect(svr_batch.send_close).to be true
 | 
	
		
			
				|  |  |    end
 | 
	
		
			
				|  |  |  end
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -224,25 +208,33 @@ shared_examples 'GRPC metadata delivery works OK' do
 | 
	
		
			
				|  |  |      it 'raises an exception if a metadata key is invalid' do
 | 
	
		
			
				|  |  |        @bad_keys.each do |md|
 | 
	
		
			
				|  |  |          call = new_client_call
 | 
	
		
			
				|  |  | -        expect { call.add_metadata(md) }.to raise_error
 | 
	
		
			
				|  |  | +        client_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => md
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        blk = proc do
 | 
	
		
			
				|  |  | +          call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                         client_ops)
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +        expect(&blk).to raise_error
 | 
	
		
			
				|  |  |        end
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      it 'sends all the metadata pairs when keys and values are valid' do
 | 
	
		
			
				|  |  |        @valid_metadata.each do |md|
 | 
	
		
			
				|  |  |          call = new_client_call
 | 
	
		
			
				|  |  | -        call.add_metadata(md)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        # Client begins a call OK
 | 
	
		
			
				|  |  | -        call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        # ... server has all metadata available even though the client did not
 | 
	
		
			
				|  |  | -        # send a write
 | 
	
		
			
				|  |  | -        @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -        ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | +        client_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => md
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                      client_ops)
 | 
	
		
			
				|  |  | +        expect(batch_result.send_metadata).to be true
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # confirm the server can receive the client metadata
 | 
	
		
			
				|  |  | +        recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
 | 
	
		
			
				|  |  | +        expect(recvd_rpc).to_not eq nil
 | 
	
		
			
				|  |  | +        recvd_md = recvd_rpc.metadata
 | 
	
		
			
				|  |  |          replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
 | 
	
		
			
				|  |  | -        result = ev.result.metadata
 | 
	
		
			
				|  |  | -        expect(result.merge(replace_symbols)).to eq(result)
 | 
	
		
			
				|  |  | +        expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
 | 
	
		
			
				|  |  |        end
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |    end
 | 
	
	
		
			
				|  | @@ -266,55 +258,81 @@ shared_examples 'GRPC metadata delivery works OK' do
 | 
	
		
			
				|  |  |      it 'raises an exception if a metadata key is invalid' do
 | 
	
		
			
				|  |  |        @bad_keys.each do |md|
 | 
	
		
			
				|  |  |          call = new_client_call
 | 
	
		
			
				|  |  | -        call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | +        # client signals that it's done sending metadata to allow server to
 | 
	
		
			
				|  |  | +        # respond
 | 
	
		
			
				|  |  | +        client_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        call.run_batch(@client_queue, @client_tag, deadline, client_ops)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          # server gets the invocation
 | 
	
		
			
				|  |  | -        @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -        ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | -        expect { ev.call.add_metadata(md) }.to raise_error
 | 
	
		
			
				|  |  | +        recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
 | 
	
		
			
				|  |  | +        expect(recvd_rpc).to_not eq nil
 | 
	
		
			
				|  |  | +        server_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => md
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        blk = proc do
 | 
	
		
			
				|  |  | +          recvd_rpc.call.run_batch(@server_queue, @server_tag, deadline,
 | 
	
		
			
				|  |  | +                                   server_ops)
 | 
	
		
			
				|  |  | +        end
 | 
	
		
			
				|  |  | +        expect(&blk).to raise_error
 | 
	
		
			
				|  |  |        end
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    it 'sends a hash that contains the status when no metadata is added' do
 | 
	
		
			
				|  |  | +    it 'sends an empty hash if no metadata is added' do
 | 
	
		
			
				|  |  |        call = new_client_call
 | 
	
		
			
				|  |  | -      call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      # server gets the invocation
 | 
	
		
			
				|  |  | -      @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -      ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | -      server_call = ev.call
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      # ... server accepts the call without adding metadata
 | 
	
		
			
				|  |  | -      server_call.server_accept(@server_queue, @server_finished_tag)
 | 
	
		
			
				|  |  | -      server_call.server_end_initial_metadata
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      # there is the HTTP status metadata, though there should not be any
 | 
	
		
			
				|  |  | -      # TODO: update this with the bug number to be resolved
 | 
	
		
			
				|  |  | -      ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ,
 | 
	
		
			
				|  |  | -                                @client_metadata_tag)
 | 
	
		
			
				|  |  | -      expect(ev.result).to eq({})
 | 
	
		
			
				|  |  | +      # client signals that it's done sending metadata to allow server to
 | 
	
		
			
				|  |  | +      # respond
 | 
	
		
			
				|  |  | +      client_ops = {
 | 
	
		
			
				|  |  | +        CallOps::SEND_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      call.run_batch(@client_queue, @client_tag, deadline, client_ops)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      # server gets the invocation but sends no metadata back
 | 
	
		
			
				|  |  | +      recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
 | 
	
		
			
				|  |  | +      expect(recvd_rpc).to_not eq nil
 | 
	
		
			
				|  |  | +      server_call = recvd_rpc.call
 | 
	
		
			
				|  |  | +      server_ops = {
 | 
	
		
			
				|  |  | +        CallOps::SEND_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      # client receives nothing as expected
 | 
	
		
			
				|  |  | +      client_ops = {
 | 
	
		
			
				|  |  | +        CallOps::RECV_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                    client_ops)
 | 
	
		
			
				|  |  | +      expect(batch_result.metadata).to eq({})
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      it 'sends all the pairs when keys and values are valid' do
 | 
	
		
			
				|  |  |        @valid_metadata.each do |md|
 | 
	
		
			
				|  |  |          call = new_client_call
 | 
	
		
			
				|  |  | -        call.invoke(@client_queue, @client_metadata_tag, @client_finished_tag)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        # server gets the invocation
 | 
	
		
			
				|  |  | -        @server.request_call(@server_tag)
 | 
	
		
			
				|  |  | -        ev = expect_next_event_on(@server_queue, SERVER_RPC_NEW, @server_tag)
 | 
	
		
			
				|  |  | -        server_call = ev.call
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        # ... server adds metadata and accepts the call
 | 
	
		
			
				|  |  | -        server_call.add_metadata(md)
 | 
	
		
			
				|  |  | -        server_call.server_accept(@server_queue, @server_finished_tag)
 | 
	
		
			
				|  |  | -        server_call.server_end_initial_metadata
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        # Now the client can read the metadata
 | 
	
		
			
				|  |  | -        ev = expect_next_event_on(@client_queue, CLIENT_METADATA_READ,
 | 
	
		
			
				|  |  | -                                  @client_metadata_tag)
 | 
	
		
			
				|  |  | +        # client signals that it's done sending metadata to allow server to
 | 
	
		
			
				|  |  | +        # respond
 | 
	
		
			
				|  |  | +        client_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        call.run_batch(@client_queue, @client_tag, deadline, client_ops)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # server gets the invocation but sends no metadata back
 | 
	
		
			
				|  |  | +        recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
 | 
	
		
			
				|  |  | +        expect(recvd_rpc).to_not eq nil
 | 
	
		
			
				|  |  | +        server_call = recvd_rpc.call
 | 
	
		
			
				|  |  | +        server_ops = {
 | 
	
		
			
				|  |  | +          CallOps::SEND_INITIAL_METADATA => md
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # client receives nothing as expected
 | 
	
		
			
				|  |  | +        client_ops = {
 | 
	
		
			
				|  |  | +          CallOps::RECV_INITIAL_METADATA => nil
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        batch_result = call.run_batch(@client_queue, @client_tag, deadline,
 | 
	
		
			
				|  |  | +                                      client_ops)
 | 
	
		
			
				|  |  |          replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
 | 
	
		
			
				|  |  | -        expect(ev.result).to eq(replace_symbols)
 | 
	
		
			
				|  |  | +        expect(batch_result.metadata).to eq(replace_symbols)
 | 
	
		
			
				|  |  |        end
 | 
	
		
			
				|  |  |      end
 | 
	
		
			
				|  |  |    end
 |