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.

Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/etc/roots.pem +5114 -0
  3. data/grpc_c.32.ruby +0 -0
  4. data/grpc_c.64.ruby +0 -0
  5. data/src/ruby/bin/apis/google/protobuf/empty.rb +44 -0
  6. data/src/ruby/bin/apis/pubsub_demo.rb +256 -0
  7. data/src/ruby/bin/apis/tech/pubsub/proto/pubsub.rb +174 -0
  8. data/src/ruby/bin/apis/tech/pubsub/proto/pubsub_services.rb +103 -0
  9. data/src/ruby/bin/grpc_ruby_interop_client +33 -0
  10. data/src/ruby/bin/grpc_ruby_interop_server +33 -0
  11. data/src/ruby/bin/interop/interop_client.rb +51 -0
  12. data/src/ruby/bin/interop/interop_server.rb +50 -0
  13. data/src/ruby/bin/math.rb +32 -0
  14. data/src/ruby/bin/math_client.rb +147 -0
  15. data/src/ruby/bin/math_server.rb +206 -0
  16. data/src/ruby/bin/math_services.rb +27 -0
  17. data/src/ruby/bin/noproto_client.rb +108 -0
  18. data/src/ruby/bin/noproto_server.rb +112 -0
  19. data/src/ruby/ext/grpc/extconf.rb +129 -0
  20. data/src/ruby/ext/grpc/rb_byte_buffer.c +70 -0
  21. data/src/ruby/ext/grpc/rb_byte_buffer.h +47 -0
  22. data/src/ruby/ext/grpc/rb_call.c +908 -0
  23. data/src/ruby/ext/grpc/rb_call.h +66 -0
  24. data/src/ruby/ext/grpc/rb_call_credentials.c +319 -0
  25. data/src/ruby/ext/grpc/rb_call_credentials.h +46 -0
  26. data/src/ruby/ext/grpc/rb_channel.c +432 -0
  27. data/src/ruby/ext/grpc/rb_channel.h +47 -0
  28. data/src/ruby/ext/grpc/rb_channel_args.c +169 -0
  29. data/src/ruby/ext/grpc/rb_channel_args.h +53 -0
  30. data/src/ruby/ext/grpc/rb_channel_credentials.c +268 -0
  31. data/src/ruby/ext/grpc/rb_channel_credentials.h +47 -0
  32. data/src/ruby/ext/grpc/rb_completion_queue.c +183 -0
  33. data/src/ruby/ext/grpc/rb_completion_queue.h +55 -0
  34. data/src/ruby/ext/grpc/rb_event_thread.c +158 -0
  35. data/src/ruby/ext/grpc/rb_event_thread.h +37 -0
  36. data/src/ruby/ext/grpc/rb_grpc.c +336 -0
  37. data/src/ruby/ext/grpc/rb_grpc.h +85 -0
  38. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +560 -0
  39. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +843 -0
  40. data/src/ruby/ext/grpc/rb_loader.c +72 -0
  41. data/src/ruby/ext/grpc/rb_loader.h +40 -0
  42. data/src/ruby/ext/grpc/rb_server.c +400 -0
  43. data/src/ruby/ext/grpc/rb_server.h +47 -0
  44. data/src/ruby/ext/grpc/rb_server_credentials.c +284 -0
  45. data/src/ruby/ext/grpc/rb_server_credentials.h +47 -0
  46. data/src/ruby/lib/grpc.rb +44 -0
  47. data/src/ruby/lib/grpc/2.0/grpc_c.bundle +0 -0
  48. data/src/ruby/lib/grpc/2.1/grpc_c.bundle +0 -0
  49. data/src/ruby/lib/grpc/2.2/grpc_c.bundle +0 -0
  50. data/src/ruby/lib/grpc/2.3/grpc_c.bundle +0 -0
  51. data/src/ruby/lib/grpc/core/time_consts.rb +71 -0
  52. data/src/ruby/lib/grpc/errors.rb +62 -0
  53. data/src/ruby/lib/grpc/generic/active_call.rb +488 -0
  54. data/src/ruby/lib/grpc/generic/bidi_call.rb +218 -0
  55. data/src/ruby/lib/grpc/generic/client_stub.rb +471 -0
  56. data/src/ruby/lib/grpc/generic/rpc_desc.rb +147 -0
  57. data/src/ruby/lib/grpc/generic/rpc_server.rb +504 -0
  58. data/src/ruby/lib/grpc/generic/service.rb +234 -0
  59. data/src/ruby/lib/grpc/grpc.rb +34 -0
  60. data/src/ruby/lib/grpc/logconfig.rb +59 -0
  61. data/src/ruby/lib/grpc/notifier.rb +60 -0
  62. data/src/ruby/lib/grpc/version.rb +33 -0
  63. data/src/ruby/pb/README.md +42 -0
  64. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  65. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  66. data/src/ruby/pb/grpc/health/v1alpha/health.rb +29 -0
  67. data/src/ruby/pb/grpc/health/v1alpha/health_services.rb +28 -0
  68. data/src/ruby/pb/test/client.rb +469 -0
  69. data/src/ruby/pb/test/proto/empty.rb +15 -0
  70. data/src/ruby/pb/test/proto/messages.rb +80 -0
  71. data/src/ruby/pb/test/proto/test.rb +14 -0
  72. data/src/ruby/pb/test/proto/test_services.rb +64 -0
  73. data/src/ruby/pb/test/server.rb +253 -0
  74. data/src/ruby/spec/call_credentials_spec.rb +57 -0
  75. data/src/ruby/spec/call_spec.rb +163 -0
  76. data/src/ruby/spec/channel_credentials_spec.rb +97 -0
  77. data/src/ruby/spec/channel_spec.rb +177 -0
  78. data/src/ruby/spec/client_server_spec.rb +475 -0
  79. data/src/ruby/spec/completion_queue_spec.rb +42 -0
  80. data/src/ruby/spec/generic/active_call_spec.rb +373 -0
  81. data/src/ruby/spec/generic/client_stub_spec.rb +476 -0
  82. data/src/ruby/spec/generic/rpc_desc_spec.rb +331 -0
  83. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +138 -0
  84. data/src/ruby/spec/generic/rpc_server_spec.rb +576 -0
  85. data/src/ruby/spec/generic/service_spec.rb +345 -0
  86. data/src/ruby/spec/pb/health/checker_spec.rb +232 -0
  87. data/src/ruby/spec/server_credentials_spec.rb +94 -0
  88. data/src/ruby/spec/server_spec.rb +209 -0
  89. data/src/ruby/spec/spec_helper.rb +69 -0
  90. data/src/ruby/spec/testdata/README +1 -0
  91. data/src/ruby/spec/testdata/ca.pem +15 -0
  92. data/src/ruby/spec/testdata/server1.key +16 -0
  93. data/src/ruby/spec/testdata/server1.pem +16 -0
  94. data/src/ruby/spec/time_consts_spec.rb +89 -0
  95. 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