client_server_spec.rb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. # Copyright 2015 gRPC authors.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. require 'grpc'
  15. include GRPC::Core
  16. shared_context 'setup: tags' do
  17. let(:sent_message) { 'sent message' }
  18. let(:reply_text) { 'the reply' }
  19. def deadline
  20. Time.now + 5
  21. end
  22. def server_allows_client_to_proceed(metadata = {})
  23. recvd_rpc = @server.request_call
  24. expect(recvd_rpc).to_not eq nil
  25. server_call = recvd_rpc.call
  26. ops = { CallOps::SEND_INITIAL_METADATA => metadata }
  27. svr_batch = server_call.run_batch(ops)
  28. expect(svr_batch.send_metadata).to be true
  29. server_call
  30. end
  31. def new_client_call
  32. @ch.create_call(nil, nil, '/method', nil, deadline)
  33. end
  34. end
  35. shared_examples 'basic GRPC message delivery is OK' do
  36. include GRPC::Core
  37. include_context 'setup: tags'
  38. context 'the test channel' do
  39. it 'should have a target' do
  40. expect(@ch.target).to be_a(String)
  41. end
  42. end
  43. context 'a client call' do
  44. it 'should have a peer' do
  45. expect(new_client_call.peer).to be_a(String)
  46. end
  47. end
  48. it 'calls have peer info' do
  49. call = new_client_call
  50. expect(call.peer).to be_a(String)
  51. end
  52. it 'servers receive requests from clients and can respond' do
  53. call = new_client_call
  54. server_call = nil
  55. server_thread = Thread.new do
  56. server_call = server_allows_client_to_proceed
  57. end
  58. client_ops = {
  59. CallOps::SEND_INITIAL_METADATA => {},
  60. CallOps::SEND_MESSAGE => sent_message
  61. }
  62. batch_result = call.run_batch(client_ops)
  63. expect(batch_result.send_metadata).to be true
  64. expect(batch_result.send_message).to be true
  65. # confirm the server can read the inbound message
  66. server_thread.join
  67. server_ops = {
  68. CallOps::RECV_MESSAGE => nil
  69. }
  70. svr_batch = server_call.run_batch(server_ops)
  71. expect(svr_batch.message).to eq(sent_message)
  72. end
  73. it 'responses written by servers are received by the client' do
  74. call = new_client_call
  75. server_call = nil
  76. server_thread = Thread.new do
  77. server_call = server_allows_client_to_proceed
  78. end
  79. client_ops = {
  80. CallOps::SEND_INITIAL_METADATA => {},
  81. CallOps::SEND_MESSAGE => sent_message
  82. }
  83. batch_result = call.run_batch(client_ops)
  84. expect(batch_result.send_metadata).to be true
  85. expect(batch_result.send_message).to be true
  86. # confirm the server can read the inbound message
  87. server_thread.join
  88. server_ops = {
  89. CallOps::RECV_MESSAGE => nil,
  90. CallOps::SEND_MESSAGE => reply_text
  91. }
  92. svr_batch = server_call.run_batch(server_ops)
  93. expect(svr_batch.message).to eq(sent_message)
  94. expect(svr_batch.send_message).to be true
  95. end
  96. it 'compressed messages can be sent and received' do
  97. call = new_client_call
  98. server_call = nil
  99. long_request_str = '0' * 2000
  100. long_response_str = '1' * 2000
  101. md = { 'grpc-internal-encoding-request' => 'gzip' }
  102. server_thread = Thread.new do
  103. server_call = server_allows_client_to_proceed(md)
  104. end
  105. client_ops = {
  106. CallOps::SEND_INITIAL_METADATA => md,
  107. CallOps::SEND_MESSAGE => long_request_str
  108. }
  109. batch_result = call.run_batch(client_ops)
  110. expect(batch_result.send_metadata).to be true
  111. expect(batch_result.send_message).to be true
  112. # confirm the server can read the inbound message
  113. server_thread.join
  114. server_ops = {
  115. CallOps::RECV_MESSAGE => nil,
  116. CallOps::SEND_MESSAGE => long_response_str
  117. }
  118. svr_batch = server_call.run_batch(server_ops)
  119. expect(svr_batch.message).to eq(long_request_str)
  120. expect(svr_batch.send_message).to be true
  121. client_ops = {
  122. CallOps::SEND_CLOSE_FROM_CLIENT => nil,
  123. CallOps::RECV_INITIAL_METADATA => nil,
  124. CallOps::RECV_MESSAGE => nil
  125. }
  126. batch_result = call.run_batch(client_ops)
  127. expect(batch_result.send_close).to be true
  128. expect(batch_result.message).to eq long_response_str
  129. end
  130. it 'servers can ignore a client write and send a status' do
  131. call = new_client_call
  132. server_call = nil
  133. server_thread = Thread.new do
  134. server_call = server_allows_client_to_proceed
  135. end
  136. client_ops = {
  137. CallOps::SEND_INITIAL_METADATA => {},
  138. CallOps::SEND_MESSAGE => sent_message
  139. }
  140. batch_result = call.run_batch(client_ops)
  141. expect(batch_result.send_metadata).to be true
  142. expect(batch_result.send_message).to be true
  143. # confirm the server can read the inbound message
  144. the_status = Struct::Status.new(StatusCodes::OK, 'OK')
  145. server_thread.join
  146. server_ops = {
  147. CallOps::SEND_STATUS_FROM_SERVER => the_status
  148. }
  149. svr_batch = server_call.run_batch(server_ops)
  150. expect(svr_batch.message).to eq nil
  151. expect(svr_batch.send_status).to be true
  152. end
  153. it 'completes calls by sending status to client and server' do
  154. call = new_client_call
  155. server_call = nil
  156. server_thread = Thread.new do
  157. server_call = server_allows_client_to_proceed
  158. end
  159. client_ops = {
  160. CallOps::SEND_INITIAL_METADATA => {},
  161. CallOps::SEND_MESSAGE => sent_message
  162. }
  163. batch_result = call.run_batch(client_ops)
  164. expect(batch_result.send_metadata).to be true
  165. expect(batch_result.send_message).to be true
  166. # confirm the server can read the inbound message and respond
  167. the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
  168. server_thread.join
  169. server_ops = {
  170. CallOps::RECV_MESSAGE => nil,
  171. CallOps::SEND_MESSAGE => reply_text,
  172. CallOps::SEND_STATUS_FROM_SERVER => the_status
  173. }
  174. svr_batch = server_call.run_batch(server_ops)
  175. expect(svr_batch.message).to eq sent_message
  176. expect(svr_batch.send_status).to be true
  177. expect(svr_batch.send_message).to be true
  178. # confirm the client can receive the server response and status.
  179. client_ops = {
  180. CallOps::SEND_CLOSE_FROM_CLIENT => nil,
  181. CallOps::RECV_INITIAL_METADATA => nil,
  182. CallOps::RECV_MESSAGE => nil,
  183. CallOps::RECV_STATUS_ON_CLIENT => nil
  184. }
  185. batch_result = call.run_batch(client_ops)
  186. expect(batch_result.send_close).to be true
  187. expect(batch_result.message).to eq reply_text
  188. expect(batch_result.status).to eq the_status
  189. # confirm the server can receive the client close.
  190. server_ops = {
  191. CallOps::RECV_CLOSE_ON_SERVER => nil
  192. }
  193. svr_batch = server_call.run_batch(server_ops)
  194. expect(svr_batch.send_close).to be true
  195. end
  196. def client_cancel_test(cancel_proc, expected_code,
  197. expected_details)
  198. call = new_client_call
  199. server_call = nil
  200. server_thread = Thread.new do
  201. server_call = server_allows_client_to_proceed
  202. end
  203. client_ops = {
  204. CallOps::SEND_INITIAL_METADATA => {},
  205. CallOps::RECV_INITIAL_METADATA => nil
  206. }
  207. batch_result = call.run_batch(client_ops)
  208. expect(batch_result.send_metadata).to be true
  209. expect(batch_result.metadata).to eq({})
  210. cancel_proc.call(call)
  211. server_thread.join
  212. server_ops = {
  213. CallOps::RECV_CLOSE_ON_SERVER => nil
  214. }
  215. svr_batch = server_call.run_batch(server_ops)
  216. expect(svr_batch.send_close).to be true
  217. client_ops = {
  218. CallOps::RECV_STATUS_ON_CLIENT => {}
  219. }
  220. batch_result = call.run_batch(client_ops)
  221. expect(batch_result.status.code).to be expected_code
  222. expect(batch_result.status.details).to eq expected_details
  223. end
  224. it 'clients can cancel a call on the server' do
  225. expected_code = StatusCodes::CANCELLED
  226. expected_details = 'Cancelled'
  227. cancel_proc = proc { |call| call.cancel }
  228. client_cancel_test(cancel_proc, expected_code, expected_details)
  229. end
  230. it 'cancel_with_status unknown status' do
  231. code = StatusCodes::UNKNOWN
  232. details = 'test unknown reason'
  233. cancel_proc = proc { |call| call.cancel_with_status(code, details) }
  234. client_cancel_test(cancel_proc, code, details)
  235. end
  236. it 'cancel_with_status unknown status' do
  237. code = StatusCodes::FAILED_PRECONDITION
  238. details = 'test failed precondition reason'
  239. cancel_proc = proc { |call| call.cancel_with_status(code, details) }
  240. client_cancel_test(cancel_proc, code, details)
  241. end
  242. end
  243. shared_examples 'GRPC metadata delivery works OK' do
  244. include_context 'setup: tags'
  245. describe 'from client => server' do
  246. before(:example) do
  247. n = 7 # arbitrary number of metadata
  248. diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
  249. diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
  250. null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
  251. null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
  252. same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
  253. same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
  254. symbol_key = { a_key: 'a val' }
  255. @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
  256. @bad_keys = []
  257. @bad_keys << { Object.new => 'a value' }
  258. @bad_keys << { 1 => 'a value' }
  259. end
  260. it 'raises an exception if a metadata key is invalid' do
  261. @bad_keys.each do |md|
  262. call = new_client_call
  263. client_ops = {
  264. CallOps::SEND_INITIAL_METADATA => md
  265. }
  266. blk = proc do
  267. call.run_batch(client_ops)
  268. end
  269. expect(&blk).to raise_error
  270. end
  271. end
  272. it 'sends all the metadata pairs when keys and values are valid' do
  273. @valid_metadata.each do |md|
  274. recvd_rpc = nil
  275. rcv_thread = Thread.new do
  276. recvd_rpc = @server.request_call
  277. end
  278. call = new_client_call
  279. client_ops = {
  280. CallOps::SEND_INITIAL_METADATA => md
  281. }
  282. batch_result = call.run_batch(client_ops)
  283. expect(batch_result.send_metadata).to be true
  284. # confirm the server can receive the client metadata
  285. rcv_thread.join
  286. expect(recvd_rpc).to_not eq nil
  287. recvd_md = recvd_rpc.metadata
  288. replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
  289. expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
  290. end
  291. end
  292. end
  293. describe 'from server => client' do
  294. before(:example) do
  295. n = 7 # arbitrary number of metadata
  296. diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
  297. diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
  298. null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
  299. null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
  300. same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
  301. same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
  302. symbol_key = { a_key: 'a val' }
  303. @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
  304. @bad_keys = []
  305. @bad_keys << { Object.new => 'a value' }
  306. @bad_keys << { 1 => 'a value' }
  307. end
  308. it 'raises an exception if a metadata key is invalid' do
  309. @bad_keys.each do |md|
  310. recvd_rpc = nil
  311. rcv_thread = Thread.new do
  312. recvd_rpc = @server.request_call
  313. end
  314. call = new_client_call
  315. # client signals that it's done sending metadata to allow server to
  316. # respond
  317. client_ops = {
  318. CallOps::SEND_INITIAL_METADATA => nil
  319. }
  320. call.run_batch(client_ops)
  321. # server gets the invocation
  322. rcv_thread.join
  323. expect(recvd_rpc).to_not eq nil
  324. server_ops = {
  325. CallOps::SEND_INITIAL_METADATA => md
  326. }
  327. blk = proc do
  328. recvd_rpc.call.run_batch(server_ops)
  329. end
  330. expect(&blk).to raise_error
  331. end
  332. end
  333. it 'sends an empty hash if no metadata is added' do
  334. recvd_rpc = nil
  335. rcv_thread = Thread.new do
  336. recvd_rpc = @server.request_call
  337. end
  338. call = new_client_call
  339. # client signals that it's done sending metadata to allow server to
  340. # respond
  341. client_ops = {
  342. CallOps::SEND_INITIAL_METADATA => nil
  343. }
  344. call.run_batch(client_ops)
  345. # server gets the invocation but sends no metadata back
  346. rcv_thread.join
  347. expect(recvd_rpc).to_not eq nil
  348. server_call = recvd_rpc.call
  349. server_ops = {
  350. CallOps::SEND_INITIAL_METADATA => nil
  351. }
  352. server_call.run_batch(server_ops)
  353. # client receives nothing as expected
  354. client_ops = {
  355. CallOps::RECV_INITIAL_METADATA => nil
  356. }
  357. batch_result = call.run_batch(client_ops)
  358. expect(batch_result.metadata).to eq({})
  359. end
  360. it 'sends all the pairs when keys and values are valid' do
  361. @valid_metadata.each do |md|
  362. recvd_rpc = nil
  363. rcv_thread = Thread.new do
  364. recvd_rpc = @server.request_call
  365. end
  366. call = new_client_call
  367. # client signals that it's done sending metadata to allow server to
  368. # respond
  369. client_ops = {
  370. CallOps::SEND_INITIAL_METADATA => nil
  371. }
  372. call.run_batch(client_ops)
  373. # server gets the invocation but sends no metadata back
  374. rcv_thread.join
  375. expect(recvd_rpc).to_not eq nil
  376. server_call = recvd_rpc.call
  377. server_ops = {
  378. CallOps::SEND_INITIAL_METADATA => md
  379. }
  380. server_call.run_batch(server_ops)
  381. # client receives nothing as expected
  382. client_ops = {
  383. CallOps::RECV_INITIAL_METADATA => nil
  384. }
  385. batch_result = call.run_batch(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. describe 'the http client/server' do
  393. before(:example) do
  394. server_host = '0.0.0.0:0'
  395. @server = GRPC::Core::Server.new(nil)
  396. server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
  397. @server.start
  398. @ch = Channel.new("0.0.0.0:#{server_port}", nil, :this_channel_is_insecure)
  399. end
  400. after(:example) do
  401. @ch.close
  402. @server.close(deadline)
  403. end
  404. it_behaves_like 'basic GRPC message delivery is OK' do
  405. end
  406. it_behaves_like 'GRPC metadata delivery works OK' do
  407. end
  408. end
  409. describe 'the secure http client/server' do
  410. include_context 'setup: tags'
  411. def load_test_certs
  412. test_root = File.join(File.dirname(__FILE__), 'testdata')
  413. files = ['ca.pem', 'server1.key', 'server1.pem']
  414. files.map { |f| File.open(File.join(test_root, f)).read }
  415. end
  416. before(:example) do
  417. certs = load_test_certs
  418. server_host = '0.0.0.0:0'
  419. server_creds = GRPC::Core::ServerCredentials.new(
  420. nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
  421. @server = GRPC::Core::Server.new(nil)
  422. server_port = @server.add_http2_port(server_host, server_creds)
  423. @server.start
  424. args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
  425. @ch = Channel.new("0.0.0.0:#{server_port}", args,
  426. GRPC::Core::ChannelCredentials.new(certs[0], nil, nil))
  427. end
  428. after(:example) do
  429. @server.close(deadline)
  430. end
  431. it_behaves_like 'basic GRPC message delivery is OK' do
  432. end
  433. it_behaves_like 'GRPC metadata delivery works OK' do
  434. end
  435. def credentials_update_test(creds_update_md)
  436. auth_proc = proc { creds_update_md }
  437. call_creds = GRPC::Core::CallCredentials.new(auth_proc)
  438. initial_md_key = 'k2'
  439. initial_md_val = 'v2'
  440. initial_md = {}
  441. initial_md[initial_md_key] = initial_md_val
  442. expected_md = creds_update_md.clone
  443. fail 'bad test param' unless expected_md[initial_md_key].nil?
  444. expected_md[initial_md_key] = initial_md_val
  445. recvd_rpc = nil
  446. rcv_thread = Thread.new do
  447. recvd_rpc = @server.request_call
  448. end
  449. call = new_client_call
  450. call.set_credentials! call_creds
  451. client_ops = {
  452. CallOps::SEND_INITIAL_METADATA => initial_md
  453. }
  454. batch_result = call.run_batch(client_ops)
  455. expect(batch_result.send_metadata).to be true
  456. # confirm the server can receive the client metadata
  457. rcv_thread.join
  458. expect(recvd_rpc).to_not eq nil
  459. recvd_md = recvd_rpc.metadata
  460. replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
  461. expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
  462. end
  463. it 'modifies metadata with CallCredentials' do
  464. credentials_update_test('k1' => 'updated-v1')
  465. end
  466. it 'modifies large metadata with CallCredentials' do
  467. val_array = %w(
  468. '00000000000000000000000000000000000000000000000000000000000000',
  469. '11111111111111111111111111111111111111111111111111111111111111',
  470. )
  471. md = {
  472. k3: val_array,
  473. k4: '0000000000000000000000000000000000000000000000000000000000',
  474. keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey5: 'v1'
  475. }
  476. credentials_update_test(md)
  477. end
  478. end