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,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
|