client_server_spec.rb 15 KB

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