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,42 @@
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
+ describe GRPC::Core::CompletionQueue do
33
+ before(:example) do
34
+ @cq = GRPC::Core::CompletionQueue.new
35
+ end
36
+
37
+ describe '#new' do
38
+ it 'is constructed successufully' do
39
+ expect { GRPC::Core::CompletionQueue.new }.not_to raise_error
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,373 @@
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
+ include GRPC::Core::StatusCodes
33
+
34
+ describe GRPC::ActiveCall do
35
+ ActiveCall = GRPC::ActiveCall
36
+ Call = GRPC::Core::Call
37
+ CallOps = GRPC::Core::CallOps
38
+ WriteFlags = GRPC::Core::WriteFlags
39
+
40
+ before(:each) do
41
+ @pass_through = proc { |x| x }
42
+ @server_tag = Object.new
43
+ @tag = Object.new
44
+
45
+ @client_queue = GRPC::Core::CompletionQueue.new
46
+ @server_queue = GRPC::Core::CompletionQueue.new
47
+ host = '0.0.0.0:0'
48
+ @server = GRPC::Core::Server.new(@server_queue, nil)
49
+ server_port = @server.add_http2_port(host, :this_port_is_insecure)
50
+ @server.start
51
+ @ch = GRPC::Core::Channel.new("0.0.0.0:#{server_port}", nil,
52
+ :this_channel_is_insecure)
53
+ end
54
+
55
+ after(:each) do
56
+ @server.close(@server_queue, deadline)
57
+ end
58
+
59
+ describe 'restricted view methods' do
60
+ before(:each) do
61
+ call = make_test_call
62
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
63
+ @client_call = ActiveCall.new(call, @client_queue, @pass_through,
64
+ @pass_through, deadline,
65
+ metadata_tag: md_tag)
66
+ end
67
+
68
+ describe '#multi_req_view' do
69
+ it 'exposes a fixed subset of the ActiveCall methods' do
70
+ want = %w(cancelled, deadline, each_remote_read, metadata, shutdown)
71
+ v = @client_call.multi_req_view
72
+ want.each do |w|
73
+ expect(v.methods.include?(w))
74
+ end
75
+ end
76
+ end
77
+
78
+ describe '#single_req_view' do
79
+ it 'exposes a fixed subset of the ActiveCall methods' do
80
+ want = %w(cancelled, deadline, metadata, shutdown)
81
+ v = @client_call.single_req_view
82
+ want.each do |w|
83
+ expect(v.methods.include?(w))
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ describe '#remote_send' do
90
+ it 'allows a client to send a payload to the server' do
91
+ call = make_test_call
92
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
93
+ @client_call = ActiveCall.new(call, @client_queue, @pass_through,
94
+ @pass_through, deadline,
95
+ metadata_tag: md_tag)
96
+ msg = 'message is a string'
97
+ @client_call.remote_send(msg)
98
+
99
+ # check that server rpc new was received
100
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
101
+ expect(recvd_rpc).to_not eq nil
102
+ recvd_call = recvd_rpc.call
103
+
104
+ # Accept the call, and verify that the server reads the response ok.
105
+ server_ops = {
106
+ CallOps::SEND_INITIAL_METADATA => {}
107
+ }
108
+ recvd_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
109
+ server_call = ActiveCall.new(recvd_call, @server_queue, @pass_through,
110
+ @pass_through, deadline)
111
+ expect(server_call.remote_read).to eq(msg)
112
+ end
113
+
114
+ it 'marshals the payload using the marshal func' do
115
+ call = make_test_call
116
+ ActiveCall.client_invoke(call, @client_queue)
117
+ marshal = proc { |x| 'marshalled:' + x }
118
+ client_call = ActiveCall.new(call, @client_queue, marshal,
119
+ @pass_through, deadline)
120
+ msg = 'message is a string'
121
+ client_call.remote_send(msg)
122
+
123
+ # confirm that the message was marshalled
124
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
125
+ recvd_call = recvd_rpc.call
126
+ server_ops = {
127
+ CallOps::SEND_INITIAL_METADATA => nil
128
+ }
129
+ recvd_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
130
+ server_call = ActiveCall.new(recvd_call, @server_queue, @pass_through,
131
+ @pass_through, deadline)
132
+ expect(server_call.remote_read).to eq('marshalled:' + msg)
133
+ end
134
+
135
+ TEST_WRITE_FLAGS = [WriteFlags::BUFFER_HINT, WriteFlags::NO_COMPRESS]
136
+ TEST_WRITE_FLAGS.each do |f|
137
+ it "successfully makes calls with write_flag set to #{f}" do
138
+ call = make_test_call
139
+ ActiveCall.client_invoke(call, @client_queue)
140
+ marshal = proc { |x| 'marshalled:' + x }
141
+ client_call = ActiveCall.new(call, @client_queue, marshal,
142
+ @pass_through, deadline)
143
+ msg = 'message is a string'
144
+ client_call.write_flag = f
145
+ client_call.remote_send(msg)
146
+
147
+ # confirm that the message was marshalled
148
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
149
+ recvd_call = recvd_rpc.call
150
+ server_ops = {
151
+ CallOps::SEND_INITIAL_METADATA => nil
152
+ }
153
+ recvd_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
154
+ server_call = ActiveCall.new(recvd_call, @server_queue, @pass_through,
155
+ @pass_through, deadline)
156
+ expect(server_call.remote_read).to eq('marshalled:' + msg)
157
+ end
158
+ end
159
+ end
160
+
161
+ describe '#client_invoke' do
162
+ it 'sends keywords as metadata to the server when the are present' do
163
+ call = make_test_call
164
+ ActiveCall.client_invoke(call, @client_queue, k1: 'v1', k2: 'v2')
165
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
166
+ recvd_call = recvd_rpc.call
167
+ expect(recvd_call).to_not be_nil
168
+ expect(recvd_rpc.metadata).to_not be_nil
169
+ expect(recvd_rpc.metadata['k1']).to eq('v1')
170
+ expect(recvd_rpc.metadata['k2']).to eq('v2')
171
+ end
172
+ end
173
+
174
+ describe '#remote_read' do
175
+ it 'reads the response sent by a server' do
176
+ call = make_test_call
177
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
178
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
179
+ @pass_through, deadline,
180
+ metadata_tag: md_tag)
181
+ msg = 'message is a string'
182
+ client_call.remote_send(msg)
183
+ server_call = expect_server_to_receive(msg)
184
+ server_call.remote_send('server_response')
185
+ expect(client_call.remote_read).to eq('server_response')
186
+ end
187
+
188
+ it 'saves no metadata when the server adds no metadata' do
189
+ call = make_test_call
190
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
191
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
192
+ @pass_through, deadline,
193
+ metadata_tag: md_tag)
194
+ msg = 'message is a string'
195
+ client_call.remote_send(msg)
196
+ server_call = expect_server_to_receive(msg)
197
+ server_call.remote_send('ignore me')
198
+ expect(client_call.metadata).to be_nil
199
+ client_call.remote_read
200
+ expect(client_call.metadata).to eq({})
201
+ end
202
+
203
+ it 'saves metadata add by the server' do
204
+ call = make_test_call
205
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
206
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
207
+ @pass_through, deadline,
208
+ metadata_tag: md_tag)
209
+ msg = 'message is a string'
210
+ client_call.remote_send(msg)
211
+ server_call = expect_server_to_receive(msg, k1: 'v1', k2: 'v2')
212
+ server_call.remote_send('ignore me')
213
+ expect(client_call.metadata).to be_nil
214
+ client_call.remote_read
215
+ expected = { 'k1' => 'v1', 'k2' => 'v2' }
216
+ expect(client_call.metadata).to eq(expected)
217
+ end
218
+
219
+ it 'get a nil msg before a status when an OK status is sent' do
220
+ call = make_test_call
221
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
222
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
223
+ @pass_through, deadline,
224
+ metadata_tag: md_tag)
225
+ msg = 'message is a string'
226
+ client_call.remote_send(msg)
227
+ client_call.writes_done(false)
228
+ server_call = expect_server_to_receive(msg)
229
+ server_call.remote_send('server_response')
230
+ server_call.send_status(OK, 'OK')
231
+ expect(client_call.remote_read).to eq('server_response')
232
+ res = client_call.remote_read
233
+ expect(res).to be_nil
234
+ end
235
+
236
+ it 'unmarshals the response using the unmarshal func' do
237
+ call = make_test_call
238
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
239
+ unmarshal = proc { |x| 'unmarshalled:' + x }
240
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
241
+ unmarshal, deadline,
242
+ metadata_tag: md_tag)
243
+
244
+ # confirm the client receives the unmarshalled message
245
+ msg = 'message is a string'
246
+ client_call.remote_send(msg)
247
+ server_call = expect_server_to_receive(msg)
248
+ server_call.remote_send('server_response')
249
+ expect(client_call.remote_read).to eq('unmarshalled:server_response')
250
+ end
251
+ end
252
+
253
+ describe '#each_remote_read' do
254
+ it 'creates an Enumerator' do
255
+ call = make_test_call
256
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
257
+ @pass_through, deadline)
258
+ expect(client_call.each_remote_read).to be_a(Enumerator)
259
+ end
260
+
261
+ it 'the returns an enumerator that can read n responses' do
262
+ call = make_test_call
263
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
264
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
265
+ @pass_through, deadline,
266
+ metadata_tag: md_tag)
267
+ msg = 'message is a string'
268
+ reply = 'server_response'
269
+ client_call.remote_send(msg)
270
+ server_call = expect_server_to_receive(msg)
271
+ e = client_call.each_remote_read
272
+ n = 3 # arbitrary value > 1
273
+ n.times do
274
+ server_call.remote_send(reply)
275
+ expect(e.next).to eq(reply)
276
+ end
277
+ end
278
+
279
+ it 'the returns an enumerator that stops after an OK Status' do
280
+ call = make_test_call
281
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
282
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
283
+ @pass_through, deadline,
284
+ metadata_tag: md_tag)
285
+ msg = 'message is a string'
286
+ reply = 'server_response'
287
+ client_call.remote_send(msg)
288
+ client_call.writes_done(false)
289
+ server_call = expect_server_to_receive(msg)
290
+ e = client_call.each_remote_read
291
+ n = 3 # arbitrary value > 1
292
+ n.times do
293
+ server_call.remote_send(reply)
294
+ expect(e.next).to eq(reply)
295
+ end
296
+ server_call.send_status(OK, 'OK')
297
+ expect { e.next }.to raise_error(StopIteration)
298
+ end
299
+ end
300
+
301
+ describe '#writes_done' do
302
+ it 'finishes ok if the server sends a status response' do
303
+ call = make_test_call
304
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
305
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
306
+ @pass_through, deadline,
307
+ metadata_tag: md_tag)
308
+ msg = 'message is a string'
309
+ client_call.remote_send(msg)
310
+ expect { client_call.writes_done(false) }.to_not raise_error
311
+ server_call = expect_server_to_receive(msg)
312
+ server_call.remote_send('server_response')
313
+ expect(client_call.remote_read).to eq('server_response')
314
+ server_call.send_status(OK, 'status code is OK')
315
+ expect { client_call.finished }.to_not raise_error
316
+ end
317
+
318
+ it 'finishes ok if the server sends an early status response' do
319
+ call = make_test_call
320
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
321
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
322
+ @pass_through, deadline,
323
+ metadata_tag: md_tag)
324
+ msg = 'message is a string'
325
+ client_call.remote_send(msg)
326
+ server_call = expect_server_to_receive(msg)
327
+ server_call.remote_send('server_response')
328
+ server_call.send_status(OK, 'status code is OK')
329
+ expect(client_call.remote_read).to eq('server_response')
330
+ expect { client_call.writes_done(false) }.to_not raise_error
331
+ expect { client_call.finished }.to_not raise_error
332
+ end
333
+
334
+ it 'finishes ok if writes_done is true' do
335
+ call = make_test_call
336
+ md_tag = ActiveCall.client_invoke(call, @client_queue)
337
+ client_call = ActiveCall.new(call, @client_queue, @pass_through,
338
+ @pass_through, deadline,
339
+ metadata_tag: md_tag)
340
+ msg = 'message is a string'
341
+ client_call.remote_send(msg)
342
+ server_call = expect_server_to_receive(msg)
343
+ server_call.remote_send('server_response')
344
+ server_call.send_status(OK, 'status code is OK')
345
+ expect(client_call.remote_read).to eq('server_response')
346
+ expect { client_call.writes_done(true) }.to_not raise_error
347
+ end
348
+ end
349
+
350
+ def expect_server_to_receive(sent_text, **kw)
351
+ c = expect_server_to_be_invoked(**kw)
352
+ expect(c.remote_read).to eq(sent_text)
353
+ c
354
+ end
355
+
356
+ def expect_server_to_be_invoked(**kw)
357
+ recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
358
+ expect(recvd_rpc).to_not eq nil
359
+ recvd_call = recvd_rpc.call
360
+ recvd_call.run_batch(@server_queue, @server_tag, deadline,
361
+ CallOps::SEND_INITIAL_METADATA => kw)
362
+ ActiveCall.new(recvd_call, @server_queue, @pass_through,
363
+ @pass_through, deadline)
364
+ end
365
+
366
+ def make_test_call
367
+ @ch.create_call(@client_queue, nil, nil, '/method', nil, deadline)
368
+ end
369
+
370
+ def deadline
371
+ Time.now + 2 # in 2 seconds; arbitrary
372
+ end
373
+ end
@@ -0,0 +1,476 @@
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 wakey_thread(&blk)
33
+ n = GRPC::Notifier.new
34
+ t = Thread.new do
35
+ blk.call(n)
36
+ end
37
+ n.wait
38
+ t
39
+ end
40
+
41
+ def load_test_certs
42
+ test_root = File.join(File.dirname(File.dirname(__FILE__)), 'testdata')
43
+ files = ['ca.pem', 'server1.key', 'server1.pem']
44
+ files.map { |f| File.open(File.join(test_root, f)).read }
45
+ end
46
+
47
+ include GRPC::Core::StatusCodes
48
+ include GRPC::Core::TimeConsts
49
+ include GRPC::Core::CallOps
50
+
51
+ describe 'ClientStub' do
52
+ let(:noop) { proc { |x| x } }
53
+
54
+ before(:each) do
55
+ Thread.abort_on_exception = true
56
+ @server = nil
57
+ @server_queue = nil
58
+ @method = 'an_rpc_method'
59
+ @pass = OK
60
+ @fail = INTERNAL
61
+ @cq = GRPC::Core::CompletionQueue.new
62
+ end
63
+
64
+ after(:each) do
65
+ @server.close(@server_queue) unless @server_queue.nil?
66
+ end
67
+
68
+ describe '#new' do
69
+ let(:fake_host) { 'localhost:0' }
70
+ it 'can be created from a host and args' do
71
+ opts = { a_channel_arg: 'an_arg' }
72
+ blk = proc do
73
+ GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
74
+ end
75
+ expect(&blk).not_to raise_error
76
+ end
77
+
78
+ it 'can be created with a default deadline' do
79
+ opts = { a_channel_arg: 'an_arg', deadline: 5 }
80
+ blk = proc do
81
+ GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
82
+ end
83
+ expect(&blk).not_to raise_error
84
+ end
85
+
86
+ it 'can be created with an channel override' do
87
+ opts = { a_channel_arg: 'an_arg', channel_override: @ch }
88
+ blk = proc do
89
+ GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
90
+ end
91
+ expect(&blk).not_to raise_error
92
+ end
93
+
94
+ it 'cannot be created with a bad channel override' do
95
+ blk = proc do
96
+ opts = { a_channel_arg: 'an_arg', channel_override: Object.new }
97
+ GRPC::ClientStub.new(fake_host, @cq, :this_channel_is_insecure, **opts)
98
+ end
99
+ expect(&blk).to raise_error
100
+ end
101
+
102
+ it 'cannot be created with bad credentials' do
103
+ blk = proc do
104
+ opts = { a_channel_arg: 'an_arg' }
105
+ GRPC::ClientStub.new(fake_host, @cq, Object.new, **opts)
106
+ end
107
+ expect(&blk).to raise_error
108
+ end
109
+
110
+ it 'can be created with test test credentials' do
111
+ certs = load_test_certs
112
+ blk = proc do
113
+ opts = {
114
+ GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr',
115
+ a_channel_arg: 'an_arg'
116
+ }
117
+ creds = GRPC::Core::ChannelCredentials.new(certs[0], nil, nil)
118
+ GRPC::ClientStub.new(fake_host, @cq, creds, **opts)
119
+ end
120
+ expect(&blk).to_not raise_error
121
+ end
122
+ end
123
+
124
+ describe '#request_response' do
125
+ before(:each) do
126
+ @sent_msg, @resp = 'a_msg', 'a_reply'
127
+ end
128
+
129
+ shared_examples 'request response' do
130
+ it 'should send a request to/receive a reply from a server' do
131
+ server_port = create_test_server
132
+ th = run_request_response(@sent_msg, @resp, @pass)
133
+ stub = GRPC::ClientStub.new("localhost:#{server_port}", @cq,
134
+ :this_channel_is_insecure)
135
+ expect(get_response(stub)).to eq(@resp)
136
+ th.join
137
+ end
138
+
139
+ it 'should send metadata to the server ok' do
140
+ server_port = create_test_server
141
+ host = "localhost:#{server_port}"
142
+ th = run_request_response(@sent_msg, @resp, @pass,
143
+ k1: 'v1', k2: 'v2')
144
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
145
+ expect(get_response(stub)).to eq(@resp)
146
+ th.join
147
+ end
148
+
149
+ it 'should send a request when configured using an override channel' do
150
+ server_port = create_test_server
151
+ alt_host = "localhost:#{server_port}"
152
+ th = run_request_response(@sent_msg, @resp, @pass)
153
+ ch = GRPC::Core::Channel.new(alt_host, nil, :this_channel_is_insecure)
154
+ stub = GRPC::ClientStub.new('ignored-host', @cq,
155
+ :this_channel_is_insecure,
156
+ channel_override: ch)
157
+ expect(get_response(stub)).to eq(@resp)
158
+ th.join
159
+ end
160
+
161
+ it 'should raise an error if the status is not OK' do
162
+ server_port = create_test_server
163
+ host = "localhost:#{server_port}"
164
+ th = run_request_response(@sent_msg, @resp, @fail)
165
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
166
+ blk = proc { get_response(stub) }
167
+ expect(&blk).to raise_error(GRPC::BadStatus)
168
+ th.join
169
+ end
170
+ end
171
+
172
+ describe 'without a call operation' do
173
+ def get_response(stub)
174
+ stub.request_response(@method, @sent_msg, noop, noop,
175
+ k1: 'v1', k2: 'v2')
176
+ end
177
+
178
+ it_behaves_like 'request response'
179
+ end
180
+
181
+ describe 'via a call operation' do
182
+ def get_response(stub)
183
+ op = stub.request_response(@method, @sent_msg, noop, noop,
184
+ return_op: true, k1: 'v1', k2: 'v2')
185
+ expect(op).to be_a(GRPC::ActiveCall::Operation)
186
+ op.execute
187
+ end
188
+
189
+ it_behaves_like 'request response'
190
+ end
191
+ end
192
+
193
+ describe '#client_streamer' do
194
+ shared_examples 'client streaming' do
195
+ before(:each) do
196
+ @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
197
+ @resp = 'a_reply'
198
+ end
199
+
200
+ it 'should send requests to/receive a reply from a server' do
201
+ server_port = create_test_server
202
+ host = "localhost:#{server_port}"
203
+ th = run_client_streamer(@sent_msgs, @resp, @pass)
204
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
205
+ expect(get_response(stub)).to eq(@resp)
206
+ th.join
207
+ end
208
+
209
+ it 'should send metadata to the server ok' do
210
+ server_port = create_test_server
211
+ host = "localhost:#{server_port}"
212
+ th = run_client_streamer(@sent_msgs, @resp, @pass,
213
+ k1: 'v1', k2: 'v2')
214
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
215
+ expect(get_response(stub)).to eq(@resp)
216
+ th.join
217
+ end
218
+
219
+ it 'should raise an error if the status is not ok' do
220
+ server_port = create_test_server
221
+ host = "localhost:#{server_port}"
222
+ th = run_client_streamer(@sent_msgs, @resp, @fail)
223
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
224
+ blk = proc { get_response(stub) }
225
+ expect(&blk).to raise_error(GRPC::BadStatus)
226
+ th.join
227
+ end
228
+ end
229
+
230
+ describe 'without a call operation' do
231
+ def get_response(stub)
232
+ stub.client_streamer(@method, @sent_msgs, noop, noop,
233
+ k1: 'v1', k2: 'v2')
234
+ end
235
+
236
+ it_behaves_like 'client streaming'
237
+ end
238
+
239
+ describe 'via a call operation' do
240
+ def get_response(stub)
241
+ op = stub.client_streamer(@method, @sent_msgs, noop, noop,
242
+ return_op: true, k1: 'v1', k2: 'v2')
243
+ expect(op).to be_a(GRPC::ActiveCall::Operation)
244
+ op.execute
245
+ end
246
+
247
+ it_behaves_like 'client streaming'
248
+ end
249
+ end
250
+
251
+ describe '#server_streamer' do
252
+ shared_examples 'server streaming' do
253
+ before(:each) do
254
+ @sent_msg = 'a_msg'
255
+ @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
256
+ end
257
+
258
+ it 'should send a request to/receive replies from a server' do
259
+ server_port = create_test_server
260
+ host = "localhost:#{server_port}"
261
+ th = run_server_streamer(@sent_msg, @replys, @pass)
262
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
263
+ expect(get_responses(stub).collect { |r| r }).to eq(@replys)
264
+ th.join
265
+ end
266
+
267
+ it 'should raise an error if the status is not ok' do
268
+ server_port = create_test_server
269
+ host = "localhost:#{server_port}"
270
+ th = run_server_streamer(@sent_msg, @replys, @fail)
271
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
272
+ e = get_responses(stub)
273
+ expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
274
+ th.join
275
+ end
276
+
277
+ it 'should send metadata to the server ok' do
278
+ server_port = create_test_server
279
+ host = "localhost:#{server_port}"
280
+ th = run_server_streamer(@sent_msg, @replys, @fail,
281
+ k1: 'v1', k2: 'v2')
282
+ stub = GRPC::ClientStub.new(host, @cq, :this_channel_is_insecure)
283
+ e = get_responses(stub)
284
+ expect { e.collect { |r| r } }.to raise_error(GRPC::BadStatus)
285
+ th.join
286
+ end
287
+ end
288
+
289
+ describe 'without a call operation' do
290
+ def get_responses(stub)
291
+ e = stub.server_streamer(@method, @sent_msg, noop, noop,
292
+ k1: 'v1', k2: 'v2')
293
+ expect(e).to be_a(Enumerator)
294
+ e
295
+ end
296
+
297
+ it_behaves_like 'server streaming'
298
+ end
299
+
300
+ describe 'via a call operation' do
301
+ def get_responses(stub)
302
+ op = stub.server_streamer(@method, @sent_msg, noop, noop,
303
+ return_op: true, k1: 'v1', k2: 'v2')
304
+ expect(op).to be_a(GRPC::ActiveCall::Operation)
305
+ e = op.execute
306
+ expect(e).to be_a(Enumerator)
307
+ e
308
+ end
309
+
310
+ it_behaves_like 'server streaming'
311
+ end
312
+ end
313
+
314
+ describe '#bidi_streamer' do
315
+ shared_examples 'bidi streaming' do
316
+ before(:each) do
317
+ @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
318
+ @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
319
+ server_port = create_test_server
320
+ @host = "localhost:#{server_port}"
321
+ end
322
+
323
+ it 'supports sending all the requests first', bidi: true do
324
+ th = run_bidi_streamer_handle_inputs_first(@sent_msgs, @replys,
325
+ @pass)
326
+ stub = GRPC::ClientStub.new(@host, @cq, :this_channel_is_insecure)
327
+ e = get_responses(stub)
328
+ expect(e.collect { |r| r }).to eq(@replys)
329
+ th.join
330
+ end
331
+
332
+ it 'supports client-initiated ping pong', bidi: true do
333
+ th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, true)
334
+ stub = GRPC::ClientStub.new(@host, @cq, :this_channel_is_insecure)
335
+ e = get_responses(stub)
336
+ expect(e.collect { |r| r }).to eq(@sent_msgs)
337
+ th.join
338
+ end
339
+
340
+ it 'supports a server-initiated ping pong', bidi: true do
341
+ th = run_bidi_streamer_echo_ping_pong(@sent_msgs, @pass, false)
342
+ stub = GRPC::ClientStub.new(@host, @cq, :this_channel_is_insecure)
343
+ e = get_responses(stub)
344
+ expect(e.collect { |r| r }).to eq(@sent_msgs)
345
+ th.join
346
+ end
347
+ end
348
+
349
+ describe 'without a call operation' do
350
+ def get_responses(stub)
351
+ e = stub.bidi_streamer(@method, @sent_msgs, noop, noop)
352
+ expect(e).to be_a(Enumerator)
353
+ e
354
+ end
355
+
356
+ it_behaves_like 'bidi streaming'
357
+ end
358
+
359
+ describe 'via a call operation' do
360
+ def get_responses(stub)
361
+ op = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
362
+ return_op: true)
363
+ expect(op).to be_a(GRPC::ActiveCall::Operation)
364
+ e = op.execute
365
+ expect(e).to be_a(Enumerator)
366
+ e
367
+ end
368
+
369
+ it_behaves_like 'bidi streaming'
370
+ end
371
+
372
+ describe 'without enough time to run' do
373
+ before(:each) do
374
+ @sent_msgs = Array.new(3) { |i| 'msg_' + (i + 1).to_s }
375
+ @replys = Array.new(3) { |i| 'reply_' + (i + 1).to_s }
376
+ server_port = create_test_server
377
+ @host = "localhost:#{server_port}"
378
+ end
379
+
380
+ it 'should fail with DeadlineExceeded', bidi: true do
381
+ @server.start
382
+ stub = GRPC::ClientStub.new(@host, @cq, :this_channel_is_insecure)
383
+ blk = proc do
384
+ e = stub.bidi_streamer(@method, @sent_msgs, noop, noop,
385
+ timeout: 0.001)
386
+ e.collect { |r| r }
387
+ end
388
+ expect(&blk).to raise_error GRPC::BadStatus, /Deadline Exceeded/
389
+ end
390
+ end
391
+ end
392
+
393
+ def run_server_streamer(expected_input, replys, status, **kw)
394
+ wanted_metadata = kw.clone
395
+ wakey_thread do |notifier|
396
+ c = expect_server_to_be_invoked(notifier)
397
+ wanted_metadata.each do |k, v|
398
+ expect(c.metadata[k.to_s]).to eq(v)
399
+ end
400
+ expect(c.remote_read).to eq(expected_input)
401
+ replys.each { |r| c.remote_send(r) }
402
+ c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
403
+ end
404
+ end
405
+
406
+ def run_bidi_streamer_handle_inputs_first(expected_inputs, replys,
407
+ status)
408
+ wakey_thread do |notifier|
409
+ c = expect_server_to_be_invoked(notifier)
410
+ expected_inputs.each { |i| expect(c.remote_read).to eq(i) }
411
+ replys.each { |r| c.remote_send(r) }
412
+ c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
413
+ end
414
+ end
415
+
416
+ def run_bidi_streamer_echo_ping_pong(expected_inputs, status, client_starts)
417
+ wakey_thread do |notifier|
418
+ c = expect_server_to_be_invoked(notifier)
419
+ expected_inputs.each do |i|
420
+ if client_starts
421
+ expect(c.remote_read).to eq(i)
422
+ c.remote_send(i)
423
+ else
424
+ c.remote_send(i)
425
+ expect(c.remote_read).to eq(i)
426
+ end
427
+ end
428
+ c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
429
+ end
430
+ end
431
+
432
+ def run_client_streamer(expected_inputs, resp, status, **kw)
433
+ wanted_metadata = kw.clone
434
+ wakey_thread do |notifier|
435
+ c = expect_server_to_be_invoked(notifier)
436
+ expected_inputs.each { |i| expect(c.remote_read).to eq(i) }
437
+ wanted_metadata.each do |k, v|
438
+ expect(c.metadata[k.to_s]).to eq(v)
439
+ end
440
+ c.remote_send(resp)
441
+ c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
442
+ end
443
+ end
444
+
445
+ def run_request_response(expected_input, resp, status, **kw)
446
+ wanted_metadata = kw.clone
447
+ wakey_thread do |notifier|
448
+ c = expect_server_to_be_invoked(notifier)
449
+ expect(c.remote_read).to eq(expected_input)
450
+ wanted_metadata.each do |k, v|
451
+ expect(c.metadata[k.to_s]).to eq(v)
452
+ end
453
+ c.remote_send(resp)
454
+ c.send_status(status, status == @pass ? 'OK' : 'NOK', true)
455
+ end
456
+ end
457
+
458
+ def create_test_server
459
+ @server_queue = GRPC::Core::CompletionQueue.new
460
+ @server = GRPC::Core::Server.new(@server_queue, nil)
461
+ @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
462
+ end
463
+
464
+ def expect_server_to_be_invoked(notifier)
465
+ @server.start
466
+ notifier.notify(nil)
467
+ server_tag = Object.new
468
+ recvd_rpc = @server.request_call(@server_queue, server_tag,
469
+ INFINITE_FUTURE)
470
+ recvd_call = recvd_rpc.call
471
+ recvd_call.metadata = recvd_rpc.metadata
472
+ recvd_call.run_batch(@server_queue, server_tag, Time.now + 2,
473
+ SEND_INITIAL_METADATA => nil)
474
+ GRPC::ActiveCall.new(recvd_call, @server_queue, noop, noop, INFINITE_FUTURE)
475
+ end
476
+ end