Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(109)

Side by Side Diff: third_party/grpc/src/ruby/spec/client_server_spec.rb

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015-2016, 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
33
34 shared_context 'setup: tags' do
35 let(:sent_message) { 'sent message' }
36 let(:reply_text) { 'the reply' }
37 before(:example) do
38 @client_tag = Object.new
39 @server_tag = Object.new
40 end
41
42 def deadline
43 Time.now + 5
44 end
45
46 def server_allows_client_to_proceed
47 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
48 expect(recvd_rpc).to_not eq nil
49 server_call = recvd_rpc.call
50 ops = { CallOps::SEND_INITIAL_METADATA => {} }
51 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline, ops)
52 expect(svr_batch.send_metadata).to be true
53 server_call
54 end
55
56 def new_client_call
57 @ch.create_call(@client_queue, nil, nil, '/method', nil, deadline)
58 end
59 end
60
61 shared_examples 'basic GRPC message delivery is OK' do
62 include GRPC::Core
63 include_context 'setup: tags'
64
65 context 'the test channel' do
66 it 'should have a target' do
67 expect(@ch.target).to be_a(String)
68 end
69 end
70
71 context 'a client call' do
72 it 'should have a peer' do
73 expect(new_client_call.peer).to be_a(String)
74 end
75 end
76
77 it 'calls have peer info' do
78 call = new_client_call
79 expect(call.peer).to be_a(String)
80 end
81
82 it 'servers receive requests from clients and can respond' do
83 call = new_client_call
84 server_call = nil
85
86 server_thread = Thread.new do
87 server_call = server_allows_client_to_proceed
88 end
89
90 client_ops = {
91 CallOps::SEND_INITIAL_METADATA => {},
92 CallOps::SEND_MESSAGE => sent_message
93 }
94 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
95 client_ops)
96 expect(batch_result.send_metadata).to be true
97 expect(batch_result.send_message).to be true
98
99 # confirm the server can read the inbound message
100 server_thread.join
101 server_ops = {
102 CallOps::RECV_MESSAGE => nil
103 }
104 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
105 server_ops)
106 expect(svr_batch.message).to eq(sent_message)
107 end
108
109 it 'responses written by servers are received by the client' do
110 call = new_client_call
111 server_call = nil
112
113 server_thread = Thread.new do
114 server_call = server_allows_client_to_proceed
115 end
116
117 client_ops = {
118 CallOps::SEND_INITIAL_METADATA => {},
119 CallOps::SEND_MESSAGE => sent_message
120 }
121 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
122 client_ops)
123 expect(batch_result.send_metadata).to be true
124 expect(batch_result.send_message).to be true
125
126 # confirm the server can read the inbound message
127 server_thread.join
128 server_ops = {
129 CallOps::RECV_MESSAGE => nil,
130 CallOps::SEND_MESSAGE => reply_text
131 }
132 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
133 server_ops)
134 expect(svr_batch.message).to eq(sent_message)
135 expect(svr_batch.send_message).to be true
136 end
137
138 it 'servers can ignore a client write and send a status' do
139 call = new_client_call
140 server_call = nil
141
142 server_thread = Thread.new do
143 server_call = server_allows_client_to_proceed
144 end
145
146 client_ops = {
147 CallOps::SEND_INITIAL_METADATA => {},
148 CallOps::SEND_MESSAGE => sent_message
149 }
150 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
151 client_ops)
152 expect(batch_result.send_metadata).to be true
153 expect(batch_result.send_message).to be true
154
155 # confirm the server can read the inbound message
156 the_status = Struct::Status.new(StatusCodes::OK, 'OK')
157 server_thread.join
158 server_ops = {
159 CallOps::SEND_STATUS_FROM_SERVER => the_status
160 }
161 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
162 server_ops)
163 expect(svr_batch.message).to eq nil
164 expect(svr_batch.send_status).to be true
165 end
166
167 it 'completes calls by sending status to client and server' do
168 call = new_client_call
169 server_call = nil
170
171 server_thread = Thread.new do
172 server_call = server_allows_client_to_proceed
173 end
174
175 client_ops = {
176 CallOps::SEND_INITIAL_METADATA => {},
177 CallOps::SEND_MESSAGE => sent_message
178 }
179 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
180 client_ops)
181 expect(batch_result.send_metadata).to be true
182 expect(batch_result.send_message).to be true
183
184 # confirm the server can read the inbound message and respond
185 the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
186 server_thread.join
187 server_ops = {
188 CallOps::RECV_MESSAGE => nil,
189 CallOps::SEND_MESSAGE => reply_text,
190 CallOps::SEND_STATUS_FROM_SERVER => the_status
191 }
192 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
193 server_ops)
194 expect(svr_batch.message).to eq sent_message
195 expect(svr_batch.send_status).to be true
196 expect(svr_batch.send_message).to be true
197
198 # confirm the client can receive the server response and status.
199 client_ops = {
200 CallOps::SEND_CLOSE_FROM_CLIENT => nil,
201 CallOps::RECV_INITIAL_METADATA => nil,
202 CallOps::RECV_MESSAGE => nil,
203 CallOps::RECV_STATUS_ON_CLIENT => nil
204 }
205 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
206 client_ops)
207 expect(batch_result.send_close).to be true
208 expect(batch_result.message).to eq reply_text
209 expect(batch_result.status).to eq the_status
210
211 # confirm the server can receive the client close.
212 server_ops = {
213 CallOps::RECV_CLOSE_ON_SERVER => nil
214 }
215 svr_batch = server_call.run_batch(@server_queue, @server_tag, deadline,
216 server_ops)
217 expect(svr_batch.send_close).to be true
218 end
219 end
220
221 shared_examples 'GRPC metadata delivery works OK' do
222 include_context 'setup: tags'
223
224 describe 'from client => server' do
225 before(:example) do
226 n = 7 # arbitrary number of metadata
227 diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
228 diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
229 null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
230 null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
231 same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
232 same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
233 symbol_key = { a_key: 'a val' }
234 @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
235 @bad_keys = []
236 @bad_keys << { Object.new => 'a value' }
237 @bad_keys << { 1 => 'a value' }
238 end
239
240 it 'raises an exception if a metadata key is invalid' do
241 @bad_keys.each do |md|
242 call = new_client_call
243 client_ops = {
244 CallOps::SEND_INITIAL_METADATA => md
245 }
246 blk = proc do
247 call.run_batch(@client_queue, @client_tag, deadline,
248 client_ops)
249 end
250 expect(&blk).to raise_error
251 end
252 end
253
254 it 'sends all the metadata pairs when keys and values are valid' do
255 @valid_metadata.each do |md|
256 recvd_rpc = nil
257 rcv_thread = Thread.new do
258 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
259 end
260
261 call = new_client_call
262 client_ops = {
263 CallOps::SEND_INITIAL_METADATA => md
264 }
265 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
266 client_ops)
267 expect(batch_result.send_metadata).to be true
268
269 # confirm the server can receive the client metadata
270 rcv_thread.join
271 expect(recvd_rpc).to_not eq nil
272 recvd_md = recvd_rpc.metadata
273 replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
274 expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
275 end
276 end
277 end
278
279 describe 'from server => client' do
280 before(:example) do
281 n = 7 # arbitrary number of metadata
282 diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
283 diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
284 null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
285 null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
286 same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
287 same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
288 symbol_key = { a_key: 'a val' }
289 @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
290 @bad_keys = []
291 @bad_keys << { Object.new => 'a value' }
292 @bad_keys << { 1 => 'a value' }
293 end
294
295 it 'raises an exception if a metadata key is invalid' do
296 @bad_keys.each do |md|
297 recvd_rpc = nil
298 rcv_thread = Thread.new do
299 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
300 end
301
302 call = new_client_call
303 # client signals that it's done sending metadata to allow server to
304 # respond
305 client_ops = {
306 CallOps::SEND_INITIAL_METADATA => nil
307 }
308 call.run_batch(@client_queue, @client_tag, deadline, client_ops)
309
310 # server gets the invocation
311 rcv_thread.join
312 expect(recvd_rpc).to_not eq nil
313 server_ops = {
314 CallOps::SEND_INITIAL_METADATA => md
315 }
316 blk = proc do
317 recvd_rpc.call.run_batch(@server_queue, @server_tag, deadline,
318 server_ops)
319 end
320 expect(&blk).to raise_error
321 end
322 end
323
324 it 'sends an empty hash if no metadata is added' do
325 recvd_rpc = nil
326 rcv_thread = Thread.new do
327 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
328 end
329
330 call = new_client_call
331 # client signals that it's done sending metadata to allow server to
332 # respond
333 client_ops = {
334 CallOps::SEND_INITIAL_METADATA => nil
335 }
336 call.run_batch(@client_queue, @client_tag, deadline, client_ops)
337
338 # server gets the invocation but sends no metadata back
339 rcv_thread.join
340 expect(recvd_rpc).to_not eq nil
341 server_call = recvd_rpc.call
342 server_ops = {
343 CallOps::SEND_INITIAL_METADATA => nil
344 }
345 server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
346
347 # client receives nothing as expected
348 client_ops = {
349 CallOps::RECV_INITIAL_METADATA => nil
350 }
351 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
352 client_ops)
353 expect(batch_result.metadata).to eq({})
354 end
355
356 it 'sends all the pairs when keys and values are valid' do
357 @valid_metadata.each do |md|
358 recvd_rpc = nil
359 rcv_thread = Thread.new do
360 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
361 end
362
363 call = new_client_call
364 # client signals that it's done sending metadata to allow server to
365 # respond
366 client_ops = {
367 CallOps::SEND_INITIAL_METADATA => nil
368 }
369 call.run_batch(@client_queue, @client_tag, deadline, client_ops)
370
371 # server gets the invocation but sends no metadata back
372 rcv_thread.join
373 expect(recvd_rpc).to_not eq nil
374 server_call = recvd_rpc.call
375 server_ops = {
376 CallOps::SEND_INITIAL_METADATA => md
377 }
378 server_call.run_batch(@server_queue, @server_tag, deadline, server_ops)
379
380 # client receives nothing as expected
381 client_ops = {
382 CallOps::RECV_INITIAL_METADATA => nil
383 }
384 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
385 client_ops)
386 replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
387 expect(batch_result.metadata).to eq(replace_symbols)
388 end
389 end
390 end
391 end
392
393 describe 'the http client/server' do
394 before(:example) do
395 server_host = '0.0.0.0:0'
396 @client_queue = GRPC::Core::CompletionQueue.new
397 @server_queue = GRPC::Core::CompletionQueue.new
398 @server = GRPC::Core::Server.new(@server_queue, nil)
399 server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
400 @server.start
401 @ch = Channel.new("0.0.0.0:#{server_port}", nil, :this_channel_is_insecure)
402 end
403
404 after(:example) do
405 @ch.close
406 @server.close(@server_queue, deadline)
407 end
408
409 it_behaves_like 'basic GRPC message delivery is OK' do
410 end
411
412 it_behaves_like 'GRPC metadata delivery works OK' do
413 end
414 end
415
416 describe 'the secure http client/server' do
417 include_context 'setup: tags'
418
419 def load_test_certs
420 test_root = File.join(File.dirname(__FILE__), 'testdata')
421 files = ['ca.pem', 'server1.key', 'server1.pem']
422 files.map { |f| File.open(File.join(test_root, f)).read }
423 end
424
425 before(:example) do
426 certs = load_test_certs
427 server_host = '0.0.0.0:0'
428 @client_queue = GRPC::Core::CompletionQueue.new
429 @server_queue = GRPC::Core::CompletionQueue.new
430 server_creds = GRPC::Core::ServerCredentials.new(
431 nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
432 @server = GRPC::Core::Server.new(@server_queue, nil)
433 server_port = @server.add_http2_port(server_host, server_creds)
434 @server.start
435 args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
436 @ch = Channel.new("0.0.0.0:#{server_port}", args,
437 GRPC::Core::ChannelCredentials.new(certs[0], nil, nil))
438 end
439
440 after(:example) do
441 @server.close(@server_queue, deadline)
442 end
443
444 it_behaves_like 'basic GRPC message delivery is OK' do
445 end
446
447 it_behaves_like 'GRPC metadata delivery works OK' do
448 end
449
450 it 'modifies metadata with CallCredentials' do
451 auth_proc = proc { { 'k1' => 'updated-v1' } }
452 call_creds = GRPC::Core::CallCredentials.new(auth_proc)
453 md = { 'k2' => 'v2' }
454 expected_md = { 'k1' => 'updated-v1', 'k2' => 'v2' }
455 recvd_rpc = nil
456 rcv_thread = Thread.new do
457 recvd_rpc = @server.request_call(@server_queue, @server_tag, deadline)
458 end
459
460 call = new_client_call
461 call.set_credentials! call_creds
462 client_ops = {
463 CallOps::SEND_INITIAL_METADATA => md
464 }
465 batch_result = call.run_batch(@client_queue, @client_tag, deadline,
466 client_ops)
467 expect(batch_result.send_metadata).to be true
468
469 # confirm the server can receive the client metadata
470 rcv_thread.join
471 expect(recvd_rpc).to_not eq nil
472 recvd_md = recvd_rpc.metadata
473 replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
474 expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
475 end
476 end
OLDNEW
« no previous file with comments | « third_party/grpc/src/ruby/spec/channel_spec.rb ('k') | third_party/grpc/src/ruby/spec/completion_queue_spec.rb » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698