grpc 0.13.0.pre1.1-universal-darwin
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grpc might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/etc/roots.pem +5114 -0
- data/grpc_c.32.ruby +0 -0
- data/grpc_c.64.ruby +0 -0
- data/src/ruby/bin/apis/google/protobuf/empty.rb +44 -0
- data/src/ruby/bin/apis/pubsub_demo.rb +256 -0
- data/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
- data/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
- data/src/ruby/bin/grpc_ruby_interop_client +33 -0
- data/src/ruby/bin/grpc_ruby_interop_server +33 -0
- data/src/ruby/bin/interop/interop_client.rb +51 -0
- data/src/ruby/bin/interop/interop_server.rb +50 -0
- data/src/ruby/bin/math.rb +32 -0
- data/src/ruby/bin/math_client.rb +147 -0
- data/src/ruby/bin/math_server.rb +206 -0
- data/src/ruby/bin/math_services.rb +27 -0
- data/src/ruby/bin/noproto_client.rb +108 -0
- data/src/ruby/bin/noproto_server.rb +112 -0
- data/src/ruby/ext/grpc/extconf.rb +129 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.c +70 -0
- data/src/ruby/ext/grpc/rb_byte_buffer.h +47 -0
- data/src/ruby/ext/grpc/rb_call.c +908 -0
- data/src/ruby/ext/grpc/rb_call.h +66 -0
- data/src/ruby/ext/grpc/rb_call_credentials.c +319 -0
- data/src/ruby/ext/grpc/rb_call_credentials.h +46 -0
- data/src/ruby/ext/grpc/rb_channel.c +432 -0
- data/src/ruby/ext/grpc/rb_channel.h +47 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +169 -0
- data/src/ruby/ext/grpc/rb_channel_args.h +53 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.c +268 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.h +47 -0
- data/src/ruby/ext/grpc/rb_completion_queue.c +183 -0
- data/src/ruby/ext/grpc/rb_completion_queue.h +55 -0
- data/src/ruby/ext/grpc/rb_event_thread.c +158 -0
- data/src/ruby/ext/grpc/rb_event_thread.h +37 -0
- data/src/ruby/ext/grpc/rb_grpc.c +336 -0
- data/src/ruby/ext/grpc/rb_grpc.h +85 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +560 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +843 -0
- data/src/ruby/ext/grpc/rb_loader.c +72 -0
- data/src/ruby/ext/grpc/rb_loader.h +40 -0
- data/src/ruby/ext/grpc/rb_server.c +400 -0
- data/src/ruby/ext/grpc/rb_server.h +47 -0
- data/src/ruby/ext/grpc/rb_server_credentials.c +284 -0
- data/src/ruby/ext/grpc/rb_server_credentials.h +47 -0
- data/src/ruby/lib/grpc.rb +44 -0
- data/src/ruby/lib/grpc/2.0/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.1/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.2/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/2.3/grpc_c.bundle +0 -0
- data/src/ruby/lib/grpc/core/time_consts.rb +71 -0
- data/src/ruby/lib/grpc/errors.rb +62 -0
- data/src/ruby/lib/grpc/generic/active_call.rb +488 -0
- data/src/ruby/lib/grpc/generic/bidi_call.rb +218 -0
- data/src/ruby/lib/grpc/generic/client_stub.rb +471 -0
- data/src/ruby/lib/grpc/generic/rpc_desc.rb +147 -0
- data/src/ruby/lib/grpc/generic/rpc_server.rb +504 -0
- data/src/ruby/lib/grpc/generic/service.rb +234 -0
- data/src/ruby/lib/grpc/grpc.rb +34 -0
- data/src/ruby/lib/grpc/logconfig.rb +59 -0
- data/src/ruby/lib/grpc/notifier.rb +60 -0
- data/src/ruby/lib/grpc/version.rb +33 -0
- data/src/ruby/pb/README.md +42 -0
- data/src/ruby/pb/generate_proto_ruby.sh +51 -0
- data/src/ruby/pb/grpc/health/checker.rb +75 -0
- data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
- data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
- data/src/ruby/pb/test/client.rb +469 -0
- data/src/ruby/pb/test/proto/empty.rb +15 -0
- data/src/ruby/pb/test/proto/messages.rb +80 -0
- data/src/ruby/pb/test/proto/test.rb +14 -0
- data/src/ruby/pb/test/proto/test_services.rb +64 -0
- data/src/ruby/pb/test/server.rb +253 -0
- data/src/ruby/spec/call_credentials_spec.rb +57 -0
- data/src/ruby/spec/call_spec.rb +163 -0
- data/src/ruby/spec/channel_credentials_spec.rb +97 -0
- data/src/ruby/spec/channel_spec.rb +177 -0
- data/src/ruby/spec/client_server_spec.rb +475 -0
- data/src/ruby/spec/completion_queue_spec.rb +42 -0
- data/src/ruby/spec/generic/active_call_spec.rb +373 -0
- data/src/ruby/spec/generic/client_stub_spec.rb +476 -0
- data/src/ruby/spec/generic/rpc_desc_spec.rb +331 -0
- data/src/ruby/spec/generic/rpc_server_pool_spec.rb +138 -0
- data/src/ruby/spec/generic/rpc_server_spec.rb +576 -0
- data/src/ruby/spec/generic/service_spec.rb +345 -0
- data/src/ruby/spec/pb/health/checker_spec.rb +232 -0
- data/src/ruby/spec/server_credentials_spec.rb +94 -0
- data/src/ruby/spec/server_spec.rb +209 -0
- data/src/ruby/spec/spec_helper.rb +69 -0
- data/src/ruby/spec/testdata/README +1 -0
- data/src/ruby/spec/testdata/ca.pem +15 -0
- data/src/ruby/spec/testdata/server1.key +16 -0
- data/src/ruby/spec/testdata/server1.pem +16 -0
- data/src/ruby/spec/time_consts_spec.rb +89 -0
- metadata +319 -0
@@ -0,0 +1,576 @@
|
|
1
|
+
# Copyright 2015, 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
|
+
|
32
|
+
def load_test_certs
|
33
|
+
test_root = File.join(File.dirname(File.dirname(__FILE__)), 'testdata')
|
34
|
+
files = ['ca.pem', 'server1.key', 'server1.pem']
|
35
|
+
files.map { |f| File.open(File.join(test_root, f)).read }
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_md(wanted_md, received_md)
|
39
|
+
wanted_md.zip(received_md).each do |w, r|
|
40
|
+
w.each do |key, value|
|
41
|
+
expect(r[key]).to eq(value)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# A test message
|
47
|
+
class EchoMsg
|
48
|
+
def self.marshal(_o)
|
49
|
+
''
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.unmarshal(_o)
|
53
|
+
EchoMsg.new
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# A test service with no methods.
|
58
|
+
class EmptyService
|
59
|
+
include GRPC::GenericService
|
60
|
+
end
|
61
|
+
|
62
|
+
# A test service without an implementation.
|
63
|
+
class NoRpcImplementation
|
64
|
+
include GRPC::GenericService
|
65
|
+
rpc :an_rpc, EchoMsg, EchoMsg
|
66
|
+
end
|
67
|
+
|
68
|
+
# A test service with an echo implementation.
|
69
|
+
class EchoService
|
70
|
+
include GRPC::GenericService
|
71
|
+
rpc :an_rpc, EchoMsg, EchoMsg
|
72
|
+
attr_reader :received_md
|
73
|
+
|
74
|
+
def initialize(**kw)
|
75
|
+
@trailing_metadata = kw
|
76
|
+
@received_md = []
|
77
|
+
end
|
78
|
+
|
79
|
+
def an_rpc(req, call)
|
80
|
+
GRPC.logger.info('echo service received a request')
|
81
|
+
call.output_metadata.update(@trailing_metadata)
|
82
|
+
@received_md << call.metadata unless call.metadata.nil?
|
83
|
+
req
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
EchoStub = EchoService.rpc_stub_class
|
88
|
+
|
89
|
+
# A test service with an implementation that fails with BadStatus
|
90
|
+
class FailingService
|
91
|
+
include GRPC::GenericService
|
92
|
+
rpc :an_rpc, EchoMsg, EchoMsg
|
93
|
+
attr_reader :details, :code, :md
|
94
|
+
|
95
|
+
def initialize(_default_var = 'ignored')
|
96
|
+
@details = 'app error'
|
97
|
+
@code = 101
|
98
|
+
@md = { failed_method: 'an_rpc' }
|
99
|
+
end
|
100
|
+
|
101
|
+
def an_rpc(_req, _call)
|
102
|
+
fail GRPC::BadStatus.new(@code, @details, **@md)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
FailingStub = FailingService.rpc_stub_class
|
107
|
+
|
108
|
+
# A slow test service.
|
109
|
+
class SlowService
|
110
|
+
include GRPC::GenericService
|
111
|
+
rpc :an_rpc, EchoMsg, EchoMsg
|
112
|
+
attr_reader :received_md, :delay
|
113
|
+
|
114
|
+
def initialize(_default_var = 'ignored')
|
115
|
+
@delay = 0.25
|
116
|
+
@received_md = []
|
117
|
+
end
|
118
|
+
|
119
|
+
def an_rpc(req, call)
|
120
|
+
GRPC.logger.info("starting a slow #{@delay} rpc")
|
121
|
+
sleep @delay
|
122
|
+
@received_md << call.metadata unless call.metadata.nil?
|
123
|
+
req # send back the req as the response
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
SlowStub = SlowService.rpc_stub_class
|
128
|
+
|
129
|
+
describe GRPC::RpcServer do
|
130
|
+
RpcServer = GRPC::RpcServer
|
131
|
+
StatusCodes = GRPC::Core::StatusCodes
|
132
|
+
|
133
|
+
before(:each) do
|
134
|
+
@method = 'an_rpc_method'
|
135
|
+
@pass = 0
|
136
|
+
@fail = 1
|
137
|
+
@noop = proc { |x| x }
|
138
|
+
|
139
|
+
@server_queue = GRPC::Core::CompletionQueue.new
|
140
|
+
server_host = '0.0.0.0:0'
|
141
|
+
@server = GRPC::Core::Server.new(@server_queue, nil)
|
142
|
+
server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
|
143
|
+
@host = "localhost:#{server_port}"
|
144
|
+
@ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
|
145
|
+
end
|
146
|
+
|
147
|
+
describe '#new' do
|
148
|
+
it 'can be created with just some args' do
|
149
|
+
opts = { a_channel_arg: 'an_arg' }
|
150
|
+
blk = proc do
|
151
|
+
RpcServer.new(**opts)
|
152
|
+
end
|
153
|
+
expect(&blk).not_to raise_error
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'can be created with a default deadline' do
|
157
|
+
opts = { a_channel_arg: 'an_arg', deadline: 5 }
|
158
|
+
blk = proc do
|
159
|
+
RpcServer.new(**opts)
|
160
|
+
end
|
161
|
+
expect(&blk).not_to raise_error
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'can be created with a completion queue override' do
|
165
|
+
opts = {
|
166
|
+
a_channel_arg: 'an_arg',
|
167
|
+
completion_queue_override: @server_queue
|
168
|
+
}
|
169
|
+
blk = proc do
|
170
|
+
RpcServer.new(**opts)
|
171
|
+
end
|
172
|
+
expect(&blk).not_to raise_error
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'cannot be created with a bad completion queue override' do
|
176
|
+
blk = proc do
|
177
|
+
opts = {
|
178
|
+
a_channel_arg: 'an_arg',
|
179
|
+
completion_queue_override: Object.new
|
180
|
+
}
|
181
|
+
RpcServer.new(**opts)
|
182
|
+
end
|
183
|
+
expect(&blk).to raise_error
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'cannot be created with invalid ServerCredentials' do
|
187
|
+
blk = proc do
|
188
|
+
opts = {
|
189
|
+
a_channel_arg: 'an_arg',
|
190
|
+
creds: Object.new
|
191
|
+
}
|
192
|
+
RpcServer.new(**opts)
|
193
|
+
end
|
194
|
+
expect(&blk).to raise_error
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'can be created with a server override' do
|
198
|
+
opts = { a_channel_arg: 'an_arg', server_override: @server }
|
199
|
+
blk = proc do
|
200
|
+
RpcServer.new(**opts)
|
201
|
+
end
|
202
|
+
expect(&blk).not_to raise_error
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'cannot be created with a bad server override' do
|
206
|
+
blk = proc do
|
207
|
+
opts = {
|
208
|
+
a_channel_arg: 'an_arg',
|
209
|
+
server_override: Object.new
|
210
|
+
}
|
211
|
+
RpcServer.new(**opts)
|
212
|
+
end
|
213
|
+
expect(&blk).to raise_error
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#stopped?' do
|
218
|
+
before(:each) do
|
219
|
+
opts = { a_channel_arg: 'an_arg', poll_period: 1.5 }
|
220
|
+
@srv = RpcServer.new(**opts)
|
221
|
+
end
|
222
|
+
|
223
|
+
after(:each) do
|
224
|
+
@srv.stop
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'starts out false' do
|
228
|
+
expect(@srv.stopped?).to be(false)
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'stays false after a #stop is called before #run' do
|
232
|
+
@srv.stop
|
233
|
+
expect(@srv.stopped?).to be(false)
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'stays false after the server starts running', server: true do
|
237
|
+
@srv.handle(EchoService)
|
238
|
+
t = Thread.new { @srv.run }
|
239
|
+
@srv.wait_till_running
|
240
|
+
expect(@srv.stopped?).to be(false)
|
241
|
+
@srv.stop
|
242
|
+
t.join
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'is true after a running server is stopped', server: true do
|
246
|
+
@srv.handle(EchoService)
|
247
|
+
t = Thread.new { @srv.run }
|
248
|
+
@srv.wait_till_running
|
249
|
+
@srv.stop
|
250
|
+
expect(@srv.stopped?).to be(true)
|
251
|
+
t.join
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe '#running?' do
|
256
|
+
it 'starts out false' do
|
257
|
+
opts = { a_channel_arg: 'an_arg', server_override: @server }
|
258
|
+
r = RpcServer.new(**opts)
|
259
|
+
expect(r.running?).to be(false)
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'is false if run is called with no services registered', server: true do
|
263
|
+
opts = {
|
264
|
+
a_channel_arg: 'an_arg',
|
265
|
+
poll_period: 2,
|
266
|
+
server_override: @server
|
267
|
+
}
|
268
|
+
r = RpcServer.new(**opts)
|
269
|
+
r.run
|
270
|
+
expect(r.running?).to be(false)
|
271
|
+
r.stop
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'is true after run is called with a registered service' do
|
275
|
+
opts = {
|
276
|
+
a_channel_arg: 'an_arg',
|
277
|
+
poll_period: 2.5,
|
278
|
+
server_override: @server
|
279
|
+
}
|
280
|
+
r = RpcServer.new(**opts)
|
281
|
+
r.handle(EchoService)
|
282
|
+
t = Thread.new { r.run }
|
283
|
+
r.wait_till_running
|
284
|
+
expect(r.running?).to be(true)
|
285
|
+
r.stop
|
286
|
+
t.join
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
describe '#handle' do
|
291
|
+
before(:each) do
|
292
|
+
@opts = { a_channel_arg: 'an_arg', poll_period: 1 }
|
293
|
+
@srv = RpcServer.new(**@opts)
|
294
|
+
end
|
295
|
+
|
296
|
+
after(:each) do
|
297
|
+
@srv.stop
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'raises if #run has already been called' do
|
301
|
+
@srv.handle(EchoService)
|
302
|
+
t = Thread.new { @srv.run }
|
303
|
+
@srv.wait_till_running
|
304
|
+
expect { @srv.handle(EchoService) }.to raise_error
|
305
|
+
@srv.stop
|
306
|
+
t.join
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'raises if the server has been run and stopped' do
|
310
|
+
@srv.handle(EchoService)
|
311
|
+
t = Thread.new { @srv.run }
|
312
|
+
@srv.wait_till_running
|
313
|
+
@srv.stop
|
314
|
+
t.join
|
315
|
+
expect { @srv.handle(EchoService) }.to raise_error
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'raises if the service does not include GenericService ' do
|
319
|
+
expect { @srv.handle(Object) }.to raise_error
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'raises if the service does not declare any rpc methods' do
|
323
|
+
expect { @srv.handle(EmptyService) }.to raise_error
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'raises if the service does not define its rpc methods' do
|
327
|
+
expect { @srv.handle(NoRpcImplementation) }.to raise_error
|
328
|
+
end
|
329
|
+
|
330
|
+
it 'raises if a handler method is already registered' do
|
331
|
+
@srv.handle(EchoService)
|
332
|
+
expect { r.handle(EchoService) }.to raise_error
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe '#run' do
|
337
|
+
let(:client_opts) { { channel_override: @ch } }
|
338
|
+
let(:marshal) { EchoService.rpc_descs[:an_rpc].marshal_proc }
|
339
|
+
let(:unmarshal) { EchoService.rpc_descs[:an_rpc].unmarshal_proc(:output) }
|
340
|
+
|
341
|
+
context 'with no connect_metadata' do
|
342
|
+
before(:each) do
|
343
|
+
server_opts = {
|
344
|
+
server_override: @server,
|
345
|
+
completion_queue_override: @server_queue,
|
346
|
+
poll_period: 1
|
347
|
+
}
|
348
|
+
@srv = RpcServer.new(**server_opts)
|
349
|
+
end
|
350
|
+
|
351
|
+
it 'should return NOT_FOUND status on unknown methods', server: true do
|
352
|
+
@srv.handle(EchoService)
|
353
|
+
t = Thread.new { @srv.run }
|
354
|
+
@srv.wait_till_running
|
355
|
+
req = EchoMsg.new
|
356
|
+
blk = proc do
|
357
|
+
cq = GRPC::Core::CompletionQueue.new
|
358
|
+
stub = GRPC::ClientStub.new(@host, cq, :this_channel_is_insecure,
|
359
|
+
**client_opts)
|
360
|
+
stub.request_response('/unknown', req, marshal, unmarshal)
|
361
|
+
end
|
362
|
+
expect(&blk).to raise_error GRPC::BadStatus
|
363
|
+
@srv.stop
|
364
|
+
t.join
|
365
|
+
end
|
366
|
+
|
367
|
+
it 'should handle multiple sequential requests', server: true do
|
368
|
+
@srv.handle(EchoService)
|
369
|
+
t = Thread.new { @srv.run }
|
370
|
+
@srv.wait_till_running
|
371
|
+
req = EchoMsg.new
|
372
|
+
n = 5 # arbitrary
|
373
|
+
stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
|
374
|
+
n.times { expect(stub.an_rpc(req)).to be_a(EchoMsg) }
|
375
|
+
@srv.stop
|
376
|
+
t.join
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'should receive metadata sent as rpc keyword args', server: true do
|
380
|
+
service = EchoService.new
|
381
|
+
@srv.handle(service)
|
382
|
+
t = Thread.new { @srv.run }
|
383
|
+
@srv.wait_till_running
|
384
|
+
req = EchoMsg.new
|
385
|
+
stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
|
386
|
+
expect(stub.an_rpc(req, k1: 'v1', k2: 'v2')).to be_a(EchoMsg)
|
387
|
+
wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
|
388
|
+
check_md(wanted_md, service.received_md)
|
389
|
+
@srv.stop
|
390
|
+
t.join
|
391
|
+
end
|
392
|
+
|
393
|
+
it 'should receive metadata if a deadline is specified', server: true do
|
394
|
+
service = SlowService.new
|
395
|
+
@srv.handle(service)
|
396
|
+
t = Thread.new { @srv.run }
|
397
|
+
@srv.wait_till_running
|
398
|
+
req = EchoMsg.new
|
399
|
+
stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
|
400
|
+
timeout = service.delay + 1.0 # wait for long enough
|
401
|
+
resp = stub.an_rpc(req, timeout: timeout, k1: 'v1', k2: 'v2')
|
402
|
+
expect(resp).to be_a(EchoMsg)
|
403
|
+
wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
|
404
|
+
check_md(wanted_md, service.received_md)
|
405
|
+
@srv.stop
|
406
|
+
t.join
|
407
|
+
end
|
408
|
+
|
409
|
+
it 'should handle cancellation correctly', server: true do
|
410
|
+
service = SlowService.new
|
411
|
+
@srv.handle(service)
|
412
|
+
t = Thread.new { @srv.run }
|
413
|
+
@srv.wait_till_running
|
414
|
+
req = EchoMsg.new
|
415
|
+
stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
|
416
|
+
op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
|
417
|
+
Thread.new do # cancel the call
|
418
|
+
sleep 0.1
|
419
|
+
op.cancel
|
420
|
+
end
|
421
|
+
expect { op.execute }.to raise_error GRPC::Cancelled
|
422
|
+
@srv.stop
|
423
|
+
t.join
|
424
|
+
end
|
425
|
+
|
426
|
+
it 'should handle multiple parallel requests', server: true do
|
427
|
+
@srv.handle(EchoService)
|
428
|
+
t = Thread.new { @srv.run }
|
429
|
+
@srv.wait_till_running
|
430
|
+
req, q = EchoMsg.new, Queue.new
|
431
|
+
n = 5 # arbitrary
|
432
|
+
threads = [t]
|
433
|
+
n.times do
|
434
|
+
threads << Thread.new do
|
435
|
+
stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
|
436
|
+
q << stub.an_rpc(req)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
n.times { expect(q.pop).to be_a(EchoMsg) }
|
440
|
+
@srv.stop
|
441
|
+
threads.each(&:join)
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'should return UNAVAILABLE on too many jobs', server: true do
|
445
|
+
opts = {
|
446
|
+
a_channel_arg: 'an_arg',
|
447
|
+
server_override: @server,
|
448
|
+
completion_queue_override: @server_queue,
|
449
|
+
pool_size: 1,
|
450
|
+
poll_period: 1,
|
451
|
+
max_waiting_requests: 0
|
452
|
+
}
|
453
|
+
alt_srv = RpcServer.new(**opts)
|
454
|
+
alt_srv.handle(SlowService)
|
455
|
+
t = Thread.new { alt_srv.run }
|
456
|
+
alt_srv.wait_till_running
|
457
|
+
req = EchoMsg.new
|
458
|
+
n = 5 # arbitrary, use as many to ensure the server pool is exceeded
|
459
|
+
threads = []
|
460
|
+
one_failed_as_unavailable = false
|
461
|
+
n.times do
|
462
|
+
threads << Thread.new do
|
463
|
+
stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
|
464
|
+
begin
|
465
|
+
stub.an_rpc(req)
|
466
|
+
rescue GRPC::BadStatus => e
|
467
|
+
one_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
threads.each(&:join)
|
472
|
+
alt_srv.stop
|
473
|
+
t.join
|
474
|
+
expect(one_failed_as_unavailable).to be(true)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'with connect metadata' do
|
479
|
+
let(:test_md_proc) do
|
480
|
+
proc do |mth, md|
|
481
|
+
res = md.clone
|
482
|
+
res['method'] = mth
|
483
|
+
res['connect_k1'] = 'connect_v1'
|
484
|
+
res
|
485
|
+
end
|
486
|
+
end
|
487
|
+
before(:each) do
|
488
|
+
server_opts = {
|
489
|
+
server_override: @server,
|
490
|
+
completion_queue_override: @server_queue,
|
491
|
+
poll_period: 1,
|
492
|
+
connect_md_proc: test_md_proc
|
493
|
+
}
|
494
|
+
@srv = RpcServer.new(**server_opts)
|
495
|
+
end
|
496
|
+
|
497
|
+
it 'should send connect metadata to the client', server: true do
|
498
|
+
service = EchoService.new
|
499
|
+
@srv.handle(service)
|
500
|
+
t = Thread.new { @srv.run }
|
501
|
+
@srv.wait_till_running
|
502
|
+
req = EchoMsg.new
|
503
|
+
stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
|
504
|
+
op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
|
505
|
+
expect(op.metadata).to be nil
|
506
|
+
expect(op.execute).to be_a(EchoMsg)
|
507
|
+
wanted_md = {
|
508
|
+
'k1' => 'v1',
|
509
|
+
'k2' => 'v2',
|
510
|
+
'method' => '/EchoService/an_rpc',
|
511
|
+
'connect_k1' => 'connect_v1'
|
512
|
+
}
|
513
|
+
wanted_md.each do |key, value|
|
514
|
+
expect(op.metadata[key]).to eq(value)
|
515
|
+
end
|
516
|
+
@srv.stop
|
517
|
+
t.join
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
context 'with trailing metadata' do
|
522
|
+
before(:each) do
|
523
|
+
server_opts = {
|
524
|
+
server_override: @server,
|
525
|
+
completion_queue_override: @server_queue,
|
526
|
+
poll_period: 1
|
527
|
+
}
|
528
|
+
@srv = RpcServer.new(**server_opts)
|
529
|
+
end
|
530
|
+
|
531
|
+
after(:each) do
|
532
|
+
@srv.stop
|
533
|
+
end
|
534
|
+
|
535
|
+
it 'should be added to BadStatus when requests fail', server: true do
|
536
|
+
service = FailingService.new
|
537
|
+
@srv.handle(service)
|
538
|
+
t = Thread.new { @srv.run }
|
539
|
+
@srv.wait_till_running
|
540
|
+
req = EchoMsg.new
|
541
|
+
stub = FailingStub.new(@host, :this_channel_is_insecure, **client_opts)
|
542
|
+
blk = proc { stub.an_rpc(req) }
|
543
|
+
|
544
|
+
# confirm it raise the expected error
|
545
|
+
expect(&blk).to raise_error GRPC::BadStatus
|
546
|
+
|
547
|
+
# call again and confirm exception contained the trailing metadata.
|
548
|
+
begin
|
549
|
+
blk.call
|
550
|
+
rescue GRPC::BadStatus => e
|
551
|
+
expect(e.code).to eq(service.code)
|
552
|
+
expect(e.details).to eq(service.details)
|
553
|
+
expect(e.metadata).to eq(service.md)
|
554
|
+
end
|
555
|
+
@srv.stop
|
556
|
+
t.join
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'should be received by the client', server: true do
|
560
|
+
wanted_trailers = { 'k1' => 'out_v1', 'k2' => 'out_v2' }
|
561
|
+
service = EchoService.new(k1: 'out_v1', k2: 'out_v2')
|
562
|
+
@srv.handle(service)
|
563
|
+
t = Thread.new { @srv.run }
|
564
|
+
@srv.wait_till_running
|
565
|
+
req = EchoMsg.new
|
566
|
+
stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
|
567
|
+
op = stub.an_rpc(req, k1: 'v1', k2: 'v2', return_op: true)
|
568
|
+
expect(op.metadata).to be nil
|
569
|
+
expect(op.execute).to be_a(EchoMsg)
|
570
|
+
expect(op.metadata).to eq(wanted_trailers)
|
571
|
+
@srv.stop
|
572
|
+
t.join
|
573
|
+
end
|
574
|
+
end
|
575
|
+
end
|
576
|
+
end
|