nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 1 | # Copyright 2014, Google Inc. |
| 2 | # All rights reserved. |
| 3 | # |
| 4 | # Redistribution and use in source and binary forms, with or without |
| 5 | # modification, are permitted provided that the following conditions are |
| 6 | # met: |
| 7 | # |
| 8 | # * Redistributions of source code must retain the above copyright |
| 9 | # notice, this list of conditions and the following disclaimer. |
| 10 | # * Redistributions in binary form must reproduce the above |
| 11 | # copyright notice, this list of conditions and the following disclaimer |
| 12 | # in the documentation and/or other materials provided with the |
| 13 | # distribution. |
| 14 | # * Neither the name of Google Inc. nor the names of its |
| 15 | # contributors may be used to endorse or promote products derived from |
| 16 | # this software without specific prior written permission. |
| 17 | # |
| 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | |
| 30 | require 'grpc' |
| 31 | require 'port_picker' |
| 32 | |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 33 | include GRPC::Core::StatusCodes |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 34 | |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 35 | describe GRPC::Core::RpcErrors do |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 36 | |
| 37 | before(:each) do |
| 38 | @known_types = { |
| 39 | :OK => 0, |
| 40 | :ERROR => 1, |
| 41 | :NOT_ON_SERVER => 2, |
| 42 | :NOT_ON_CLIENT => 3, |
| 43 | :ALREADY_INVOKED => 4, |
| 44 | :NOT_INVOKED => 5, |
| 45 | :ALREADY_FINISHED => 6, |
| 46 | :TOO_MANY_OPERATIONS => 7, |
| 47 | :INVALID_FLAGS => 8, |
| 48 | :ErrorMessages => { |
| 49 | 0=>'ok', |
| 50 | 1=>'unknown error', |
| 51 | 2=>'not available on a server', |
| 52 | 3=>'not available on a client', |
| 53 | 4=>'call is already invoked', |
| 54 | 5=>'call is not yet invoked', |
| 55 | 6=>'call is already finished', |
| 56 | 7=>'outstanding read or write present', |
| 57 | 8=>'a bad flag was given', |
| 58 | } |
| 59 | } |
| 60 | end |
| 61 | |
| 62 | it 'should have symbols for all the known error codes' do |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 63 | m = GRPC::Core::RpcErrors |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 64 | syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] } |
| 65 | expect(Hash[syms_and_codes]).to eq(@known_types) |
| 66 | end |
| 67 | |
| 68 | end |
| 69 | |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 70 | describe GRPC::Core::Call do |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 71 | |
| 72 | before(:each) do |
| 73 | @tag = Object.new |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 74 | @client_queue = GRPC::Core::CompletionQueue.new |
| 75 | @server_queue = GRPC::Core::CompletionQueue.new |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 76 | port = find_unused_tcp_port |
| 77 | host = "localhost:#{port}" |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 78 | @server = GRPC::Core::Server.new(@server_queue, nil) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 79 | @server.add_http2_port(host) |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 80 | @ch = GRPC::Core::Channel.new(host, nil) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 81 | end |
| 82 | |
| 83 | after(:each) do |
| 84 | @server.close |
| 85 | end |
| 86 | |
| 87 | describe '#start_read' do |
| 88 | it 'should fail if called immediately' do |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 89 | expect { make_test_call.start_read(@tag) }.to raise_error GRPC::Core::CallError |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 90 | end |
| 91 | end |
| 92 | |
| 93 | describe '#start_write' do |
| 94 | it 'should fail if called immediately' do |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 95 | bytes = GRPC::Core::ByteBuffer.new('test string') |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 96 | expect { make_test_call.start_write(bytes, @tag) } |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 97 | .to raise_error GRPC::Core::CallError |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 98 | end |
| 99 | end |
| 100 | |
| 101 | describe '#start_write_status' do |
| 102 | it 'should fail if called immediately' do |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 103 | sts = GRPC::Core::Status.new(153, 'test detail') |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 104 | expect { make_test_call.start_write_status(sts, @tag) } |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 105 | .to raise_error GRPC::Core::CallError |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 106 | end |
| 107 | end |
| 108 | |
| 109 | describe '#writes_done' do |
| 110 | it 'should fail if called immediately' do |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 111 | expect { make_test_call.writes_done(@tag) }.to raise_error GRPC::Core::CallError |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 112 | end |
| 113 | end |
| 114 | |
| 115 | describe '#add_metadata' do |
| 116 | it 'adds metadata to a call without fail' do |
| 117 | call = make_test_call |
| 118 | n = 37 |
| 119 | metadata = Hash[n.times.collect { |i| ["key%d" % i, "value%d" %i] } ] |
| 120 | expect { call.add_metadata(metadata) }.to_not raise_error |
| 121 | end |
| 122 | end |
| 123 | |
| 124 | describe '#start_invoke' do |
| 125 | it 'should cause the INVOKE_ACCEPTED event' do |
| 126 | call = make_test_call |
| 127 | expect(call.start_invoke(@client_queue, @tag, @tag, @tag)).to be_nil |
| 128 | ev = @client_queue.next(deadline) |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 129 | expect(ev.call).to be_a(GRPC::Core::Call) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 130 | expect(ev.tag).to be(@tag) |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 131 | expect(ev.type).to be(GRPC::Core::CompletionType::INVOKE_ACCEPTED) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 132 | expect(ev.call).to_not be(call) |
| 133 | end |
| 134 | end |
| 135 | |
| 136 | describe '#start_write' do |
| 137 | it 'should cause the WRITE_ACCEPTED event' do |
| 138 | call = make_test_call |
| 139 | call.start_invoke(@client_queue, @tag, @tag, @tag) |
| 140 | ev = @client_queue.next(deadline) |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 141 | expect(ev.type).to be(GRPC::Core::CompletionType::INVOKE_ACCEPTED) |
| 142 | expect(call.start_write(GRPC::Core::ByteBuffer.new('test_start_write'), |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 143 | @tag)).to be_nil |
| 144 | ev = @client_queue.next(deadline) |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 145 | expect(ev.call).to be_a(GRPC::Core::Call) |
| 146 | expect(ev.type).to be(GRPC::Core::CompletionType::WRITE_ACCEPTED) |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 147 | expect(ev.tag).to be(@tag) |
| 148 | end |
| 149 | end |
| 150 | |
| 151 | describe '#status' do |
| 152 | it 'can save the status and read it back' do |
| 153 | call = make_test_call |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame^] | 154 | sts = GRPC::Core::Status.new(OK, 'OK') |
nnoble | 097ef9b | 2014-12-01 17:06:10 -0800 | [diff] [blame] | 155 | expect { call.status = sts }.not_to raise_error |
| 156 | expect(call.status).to be(sts) |
| 157 | end |
| 158 | |
| 159 | it 'must be set to a status' do |
| 160 | call = make_test_call |
| 161 | bad_sts = Object.new |
| 162 | expect { call.status = bad_sts }.to raise_error(TypeError) |
| 163 | end |
| 164 | |
| 165 | it 'can be set to nil' do |
| 166 | call = make_test_call |
| 167 | expect { call.status = nil }.not_to raise_error |
| 168 | end |
| 169 | end |
| 170 | |
| 171 | describe '#metadata' do |
| 172 | it 'can save the metadata hash and read it back' do |
| 173 | call = make_test_call |
| 174 | md = {'k1' => 'v1', 'k2' => 'v2'} |
| 175 | expect { call.metadata = md }.not_to raise_error |
| 176 | expect(call.metadata).to be(md) |
| 177 | end |
| 178 | |
| 179 | it 'must be set with a hash' do |
| 180 | call = make_test_call |
| 181 | bad_md = Object.new |
| 182 | expect { call.metadata = bad_md }.to raise_error(TypeError) |
| 183 | end |
| 184 | |
| 185 | it 'can be set to nil' do |
| 186 | call = make_test_call |
| 187 | expect { call.metadata = nil }.not_to raise_error |
| 188 | end |
| 189 | end |
| 190 | |
| 191 | |
| 192 | def make_test_call |
| 193 | @ch.create_call('dummy_method', 'dummy_host', deadline) |
| 194 | end |
| 195 | |
| 196 | def deadline |
| 197 | Time.now + 2 # in 2 seconds; arbitrary |
| 198 | end |
| 199 | |
| 200 | end |