rpc_server_spec.rb 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  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 'spec_helper'
  15. def load_test_certs
  16. test_root = File.join(File.dirname(File.dirname(__FILE__)), 'testdata')
  17. files = ['ca.pem', 'server1.key', 'server1.pem']
  18. files.map { |f| File.open(File.join(test_root, f)).read }
  19. end
  20. def check_md(wanted_md, received_md)
  21. wanted_md.zip(received_md).each do |w, r|
  22. w.each do |key, value|
  23. expect(r[key]).to eq(value)
  24. end
  25. end
  26. end
  27. # A test service with no methods.
  28. class EmptyService
  29. include GRPC::GenericService
  30. end
  31. # A test service without an implementation.
  32. class NoRpcImplementation
  33. include GRPC::GenericService
  34. rpc :an_rpc, EchoMsg, EchoMsg
  35. end
  36. # A test service with an implementation that fails with BadStatus
  37. class FailingService
  38. include GRPC::GenericService
  39. rpc :an_rpc, EchoMsg, EchoMsg
  40. attr_reader :details, :code, :md
  41. def initialize(_default_var = 'ignored')
  42. @details = 'app error'
  43. @code = 101
  44. @md = { 'failed_method' => 'an_rpc' }
  45. end
  46. def an_rpc(_req, _call)
  47. fail GRPC::BadStatus.new(@code, @details, @md)
  48. end
  49. end
  50. FailingStub = FailingService.rpc_stub_class
  51. # A slow test service.
  52. class SlowService
  53. include GRPC::GenericService
  54. rpc :an_rpc, EchoMsg, EchoMsg
  55. attr_reader :received_md, :delay
  56. def initialize(_default_var = 'ignored')
  57. @delay = 0.25
  58. @received_md = []
  59. end
  60. def an_rpc(req, call)
  61. GRPC.logger.info("starting a slow #{@delay} rpc")
  62. sleep @delay
  63. @received_md << call.metadata unless call.metadata.nil?
  64. req # send back the req as the response
  65. end
  66. end
  67. SlowStub = SlowService.rpc_stub_class
  68. # A test service that allows a synchronized RPC cancellation
  69. class SynchronizedCancellationService
  70. include GRPC::GenericService
  71. rpc :an_rpc, EchoMsg, EchoMsg
  72. attr_reader :received_md, :delay
  73. # notify_request_received and wait_until_rpc_cancelled are
  74. # callbacks to synchronously allow the client to proceed with
  75. # cancellation (after the unary request has been received),
  76. # and to synchronously wait until the client has cancelled the
  77. # current RPC.
  78. def initialize(notify_request_received, wait_until_rpc_cancelled)
  79. @notify_request_received = notify_request_received
  80. @wait_until_rpc_cancelled = wait_until_rpc_cancelled
  81. end
  82. def an_rpc(req, _call)
  83. GRPC.logger.info('starting a synchronusly cancelled rpc')
  84. @notify_request_received.call(req)
  85. @wait_until_rpc_cancelled.call
  86. req # send back the req as the response
  87. end
  88. end
  89. SynchronizedCancellationStub = SynchronizedCancellationService.rpc_stub_class
  90. # a test service that hangs onto call objects
  91. # and uses them after the server-side call has been
  92. # finished
  93. class CheckCallAfterFinishedService
  94. include GRPC::GenericService
  95. rpc :an_rpc, EchoMsg, EchoMsg
  96. rpc :a_client_streaming_rpc, stream(EchoMsg), EchoMsg
  97. rpc :a_server_streaming_rpc, EchoMsg, stream(EchoMsg)
  98. rpc :a_bidi_rpc, stream(EchoMsg), stream(EchoMsg)
  99. attr_reader :server_side_call
  100. def an_rpc(req, call)
  101. fail 'shouldnt reuse service' unless @server_side_call.nil?
  102. @server_side_call = call
  103. req
  104. end
  105. def a_client_streaming_rpc(call)
  106. fail 'shouldnt reuse service' unless @server_side_call.nil?
  107. @server_side_call = call
  108. # iterate through requests so call can complete
  109. call.each_remote_read.each { |r| GRPC.logger.info(r) }
  110. EchoMsg.new
  111. end
  112. def a_server_streaming_rpc(_, call)
  113. fail 'shouldnt reuse service' unless @server_side_call.nil?
  114. @server_side_call = call
  115. [EchoMsg.new, EchoMsg.new]
  116. end
  117. def a_bidi_rpc(requests, call)
  118. fail 'shouldnt reuse service' unless @server_side_call.nil?
  119. @server_side_call = call
  120. requests.each { |r| GRPC.logger.info(r) }
  121. [EchoMsg.new, EchoMsg.new]
  122. end
  123. end
  124. CheckCallAfterFinishedServiceStub = CheckCallAfterFinishedService.rpc_stub_class
  125. # A service with a bidi streaming method.
  126. class BidiService
  127. include GRPC::GenericService
  128. rpc :server_sends_bad_input, stream(EchoMsg), stream(EchoMsg)
  129. def server_sends_bad_input(_, _)
  130. 'bad response. (not an enumerable, client sees an error)'
  131. end
  132. end
  133. BidiStub = BidiService.rpc_stub_class
  134. describe GRPC::RpcServer do
  135. RpcServer = GRPC::RpcServer
  136. StatusCodes = GRPC::Core::StatusCodes
  137. before(:each) do
  138. @method = 'an_rpc_method'
  139. @pass = 0
  140. @fail = 1
  141. @noop = proc { |x| x }
  142. end
  143. describe '#new' do
  144. it 'can be created with just some args' do
  145. opts = { server_args: { a_channel_arg: 'an_arg' } }
  146. blk = proc do
  147. new_rpc_server_for_testing(**opts)
  148. end
  149. expect(&blk).not_to raise_error
  150. end
  151. it 'cannot be created with invalid ServerCredentials' do
  152. blk = proc do
  153. opts = {
  154. server_args: { a_channel_arg: 'an_arg' },
  155. creds: Object.new
  156. }
  157. new_rpc_server_for_testing(**opts)
  158. end
  159. expect(&blk).to raise_error
  160. end
  161. end
  162. describe '#stopped?' do
  163. before(:each) do
  164. opts = { server_args: { a_channel_arg: 'an_arg' }, poll_period: 1.5 }
  165. @srv = new_rpc_server_for_testing(**opts)
  166. @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  167. end
  168. it 'starts out false' do
  169. expect(@srv.stopped?).to be(false)
  170. end
  171. it 'stays false after the server starts running', server: true do
  172. @srv.handle(EchoService)
  173. t = Thread.new { @srv.run }
  174. @srv.wait_till_running
  175. expect(@srv.stopped?).to be(false)
  176. @srv.stop
  177. t.join
  178. end
  179. it 'is true after a running server is stopped', server: true do
  180. @srv.handle(EchoService)
  181. t = Thread.new { @srv.run }
  182. @srv.wait_till_running
  183. @srv.stop
  184. t.join
  185. expect(@srv.stopped?).to be(true)
  186. end
  187. end
  188. describe '#running?' do
  189. it 'starts out false' do
  190. opts = {
  191. server_args: { a_channel_arg: 'an_arg' }
  192. }
  193. r = new_rpc_server_for_testing(**opts)
  194. expect(r.running?).to be(false)
  195. end
  196. it 'is false if run is called with no services registered', server: true do
  197. opts = {
  198. server_args: { a_channel_arg: 'an_arg' },
  199. poll_period: 2
  200. }
  201. r = new_rpc_server_for_testing(**opts)
  202. r.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  203. expect { r.run }.to raise_error(RuntimeError)
  204. end
  205. it 'is true after run is called with a registered service' do
  206. opts = {
  207. server_args: { a_channel_arg: 'an_arg' },
  208. poll_period: 2.5
  209. }
  210. r = new_rpc_server_for_testing(**opts)
  211. r.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  212. r.handle(EchoService)
  213. t = Thread.new { r.run }
  214. r.wait_till_running
  215. expect(r.running?).to be(true)
  216. r.stop
  217. t.join
  218. end
  219. end
  220. describe '#handle' do
  221. before(:each) do
  222. @opts = { server_args: { a_channel_arg: 'an_arg' }, poll_period: 1 }
  223. @srv = new_rpc_server_for_testing(**@opts)
  224. @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  225. end
  226. it 'raises if #run has already been called' do
  227. @srv.handle(EchoService)
  228. t = Thread.new { @srv.run }
  229. @srv.wait_till_running
  230. expect { @srv.handle(EchoService) }.to raise_error
  231. @srv.stop
  232. t.join
  233. end
  234. it 'raises if the server has been run and stopped' do
  235. @srv.handle(EchoService)
  236. t = Thread.new { @srv.run }
  237. @srv.wait_till_running
  238. @srv.stop
  239. t.join
  240. expect { @srv.handle(EchoService) }.to raise_error
  241. end
  242. it 'raises if the service does not include GenericService ' do
  243. expect { @srv.handle(Object) }.to raise_error
  244. end
  245. it 'raises if the service does not declare any rpc methods' do
  246. expect { @srv.handle(EmptyService) }.to raise_error
  247. end
  248. it 'raises if a handler method is already registered' do
  249. @srv.handle(EchoService)
  250. expect { r.handle(EchoService) }.to raise_error
  251. end
  252. end
  253. describe '#run' do
  254. let(:client_opts) { { channel_override: @ch } }
  255. let(:marshal) { EchoService.rpc_descs[:an_rpc].marshal_proc }
  256. let(:unmarshal) { EchoService.rpc_descs[:an_rpc].unmarshal_proc(:output) }
  257. context 'with no connect_metadata' do
  258. before(:each) do
  259. server_opts = {
  260. poll_period: 1
  261. }
  262. @srv = new_rpc_server_for_testing(**server_opts)
  263. server_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  264. @host = "localhost:#{server_port}"
  265. @ch = GRPC::Core::Channel.new(@host, nil, :this_channel_is_insecure)
  266. end
  267. it 'should return NOT_FOUND status on unknown methods', server: true do
  268. @srv.handle(EchoService)
  269. t = Thread.new { @srv.run }
  270. @srv.wait_till_running
  271. req = EchoMsg.new
  272. blk = proc do
  273. stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure,
  274. **client_opts)
  275. stub.request_response('/unknown', req, marshal, unmarshal)
  276. end
  277. expect(&blk).to raise_error GRPC::BadStatus
  278. @srv.stop
  279. t.join
  280. end
  281. it 'should return UNIMPLEMENTED on unimplemented methods', server: true do
  282. @srv.handle(NoRpcImplementation)
  283. t = Thread.new { @srv.run }
  284. @srv.wait_till_running
  285. req = EchoMsg.new
  286. blk = proc do
  287. stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure,
  288. **client_opts)
  289. stub.request_response('/an_rpc', req, marshal, unmarshal)
  290. end
  291. expect(&blk).to raise_error do |error|
  292. expect(error).to be_a(GRPC::BadStatus)
  293. expect(error.code).to be(GRPC::Core::StatusCodes::UNIMPLEMENTED)
  294. end
  295. @srv.stop
  296. t.join
  297. end
  298. it 'should handle multiple sequential requests', server: true do
  299. @srv.handle(EchoService)
  300. t = Thread.new { @srv.run }
  301. @srv.wait_till_running
  302. req = EchoMsg.new
  303. n = 5 # arbitrary
  304. stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
  305. n.times { expect(stub.an_rpc(req)).to be_a(EchoMsg) }
  306. @srv.stop
  307. t.join
  308. end
  309. it 'should receive metadata sent as rpc keyword args', server: true do
  310. service = EchoService.new
  311. @srv.handle(service)
  312. t = Thread.new { @srv.run }
  313. @srv.wait_till_running
  314. req = EchoMsg.new
  315. stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
  316. expect(stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }))
  317. .to be_a(EchoMsg)
  318. wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
  319. check_md(wanted_md, service.received_md)
  320. @srv.stop
  321. t.join
  322. end
  323. it 'should receive metadata if a deadline is specified', server: true do
  324. service = SlowService.new
  325. @srv.handle(service)
  326. t = Thread.new { @srv.run }
  327. @srv.wait_till_running
  328. req = EchoMsg.new
  329. stub = SlowStub.new(@host, :this_channel_is_insecure, **client_opts)
  330. timeout = service.delay + 1.0
  331. deadline = GRPC::Core::TimeConsts.from_relative_time(timeout)
  332. resp = stub.an_rpc(req,
  333. deadline: deadline,
  334. metadata: { k1: 'v1', k2: 'v2' })
  335. expect(resp).to be_a(EchoMsg)
  336. wanted_md = [{ 'k1' => 'v1', 'k2' => 'v2' }]
  337. check_md(wanted_md, service.received_md)
  338. @srv.stop
  339. t.join
  340. end
  341. it 'should handle cancellation correctly', server: true do
  342. request_received = false
  343. request_received_mu = Mutex.new
  344. request_received_cv = ConditionVariable.new
  345. notify_request_received = proc do |req|
  346. request_received_mu.synchronize do
  347. fail 'req is nil' if req.nil?
  348. expect(req.is_a?(EchoMsg)).to be true
  349. fail 'test bug - already set' if request_received
  350. request_received = true
  351. request_received_cv.signal
  352. end
  353. end
  354. rpc_cancelled = false
  355. rpc_cancelled_mu = Mutex.new
  356. rpc_cancelled_cv = ConditionVariable.new
  357. wait_until_rpc_cancelled = proc do
  358. rpc_cancelled_mu.synchronize do
  359. loop do
  360. break if rpc_cancelled
  361. rpc_cancelled_cv.wait(rpc_cancelled_mu)
  362. end
  363. end
  364. end
  365. service = SynchronizedCancellationService.new(notify_request_received,
  366. wait_until_rpc_cancelled)
  367. @srv.handle(service)
  368. srv_thd = Thread.new { @srv.run }
  369. @srv.wait_till_running
  370. req = EchoMsg.new
  371. stub = SynchronizedCancellationStub.new(@host,
  372. :this_channel_is_insecure,
  373. **client_opts)
  374. op = stub.an_rpc(req, return_op: true)
  375. client_thd = Thread.new do
  376. expect { op.execute }.to raise_error GRPC::Cancelled
  377. end
  378. request_received_mu.synchronize do
  379. loop do
  380. break if request_received
  381. request_received_cv.wait(request_received_mu)
  382. end
  383. end
  384. op.cancel
  385. rpc_cancelled_mu.synchronize do
  386. fail 'test bug - already set' if rpc_cancelled
  387. rpc_cancelled = true
  388. rpc_cancelled_cv.signal
  389. end
  390. client_thd.join
  391. @srv.stop
  392. srv_thd.join
  393. end
  394. it 'should handle multiple parallel requests', server: true do
  395. @srv.handle(EchoService)
  396. t = Thread.new { @srv.run }
  397. @srv.wait_till_running
  398. req, q = EchoMsg.new, Queue.new
  399. n = 5 # arbitrary
  400. threads = [t]
  401. n.times do
  402. threads << Thread.new do
  403. stub = EchoStub.new(@host, :this_channel_is_insecure, **client_opts)
  404. q << stub.an_rpc(req)
  405. end
  406. end
  407. n.times { expect(q.pop).to be_a(EchoMsg) }
  408. @srv.stop
  409. threads.each(&:join)
  410. end
  411. it 'should return RESOURCE_EXHAUSTED on too many jobs', server: true do
  412. opts = {
  413. server_args: { a_channel_arg: 'an_arg' },
  414. pool_size: 2,
  415. poll_period: 1,
  416. max_waiting_requests: 1
  417. }
  418. alt_srv = new_rpc_server_for_testing(**opts)
  419. alt_srv.handle(SlowService)
  420. alt_port = alt_srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  421. alt_host = "0.0.0.0:#{alt_port}"
  422. t = Thread.new { alt_srv.run }
  423. alt_srv.wait_till_running
  424. req = EchoMsg.new
  425. n = 20 # arbitrary, use as many to ensure the server pool is exceeded
  426. threads = []
  427. one_failed_as_unavailable = false
  428. n.times do
  429. threads << Thread.new do
  430. stub = SlowStub.new(alt_host, :this_channel_is_insecure)
  431. begin
  432. stub.an_rpc(req)
  433. rescue GRPC::ResourceExhausted
  434. one_failed_as_unavailable = true
  435. end
  436. end
  437. end
  438. threads.each(&:join)
  439. alt_srv.stop
  440. t.join
  441. expect(one_failed_as_unavailable).to be(true)
  442. end
  443. it 'should send a status UNKNOWN with a relevant message when the' \
  444. 'servers response stream is not an enumerable' do
  445. @srv.handle(BidiService)
  446. t = Thread.new { @srv.run }
  447. @srv.wait_till_running
  448. stub = BidiStub.new(@host, :this_channel_is_insecure, **client_opts)
  449. responses = stub.server_sends_bad_input([])
  450. exception = nil
  451. begin
  452. responses.each { |r| r }
  453. rescue GRPC::Unknown => e
  454. exception = e
  455. end
  456. # Erroneous responses sent from the server handler should cause an
  457. # exception on the client with relevant info.
  458. expected_details = 'NoMethodError: undefined method `each\' for '\
  459. '"bad response. (not an enumerable, client sees an error)"'
  460. expect(exception.inspect.include?(expected_details)).to be true
  461. @srv.stop
  462. t.join
  463. end
  464. end
  465. context 'with connect metadata' do
  466. let(:test_md_proc) do
  467. proc do |mth, md|
  468. res = md.clone
  469. res['method'] = mth
  470. res['connect_k1'] = 'connect_v1'
  471. res
  472. end
  473. end
  474. before(:each) do
  475. server_opts = {
  476. poll_period: 1,
  477. connect_md_proc: test_md_proc
  478. }
  479. @srv = new_rpc_server_for_testing(**server_opts)
  480. alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  481. @alt_host = "0.0.0.0:#{alt_port}"
  482. end
  483. it 'should send connect metadata to the client', server: true do
  484. service = EchoService.new
  485. @srv.handle(service)
  486. t = Thread.new { @srv.run }
  487. @srv.wait_till_running
  488. req = EchoMsg.new
  489. stub = EchoStub.new(@alt_host, :this_channel_is_insecure)
  490. op = stub.an_rpc(req, metadata: { k1: 'v1', k2: 'v2' }, return_op: true)
  491. expect(op.metadata).to be nil
  492. expect(op.execute).to be_a(EchoMsg)
  493. wanted_md = {
  494. 'k1' => 'v1',
  495. 'k2' => 'v2',
  496. 'method' => '/EchoService/an_rpc',
  497. 'connect_k1' => 'connect_v1'
  498. }
  499. wanted_md.each do |key, value|
  500. GRPC.logger.info("key: #{key}")
  501. expect(op.metadata[key]).to eq(value)
  502. end
  503. @srv.stop
  504. t.join
  505. end
  506. end
  507. context 'with trailing metadata' do
  508. before(:each) do
  509. server_opts = {
  510. poll_period: 1
  511. }
  512. @srv = new_rpc_server_for_testing(**server_opts)
  513. alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  514. @alt_host = "0.0.0.0:#{alt_port}"
  515. end
  516. it 'should be added to BadStatus when requests fail', server: true do
  517. service = FailingService.new
  518. @srv.handle(service)
  519. t = Thread.new { @srv.run }
  520. @srv.wait_till_running
  521. req = EchoMsg.new
  522. stub = FailingStub.new(@alt_host, :this_channel_is_insecure)
  523. blk = proc { stub.an_rpc(req) }
  524. # confirm it raise the expected error
  525. expect(&blk).to raise_error GRPC::BadStatus
  526. # call again and confirm exception contained the trailing metadata.
  527. begin
  528. blk.call
  529. rescue GRPC::BadStatus => e
  530. expect(e.code).to eq(service.code)
  531. expect(e.details).to eq(service.details)
  532. expect(e.metadata).to eq(service.md)
  533. end
  534. @srv.stop
  535. t.join
  536. end
  537. it 'should be received by the client', server: true do
  538. wanted_trailers = { 'k1' => 'out_v1', 'k2' => 'out_v2' }
  539. service = EchoService.new(k1: 'out_v1', k2: 'out_v2')
  540. @srv.handle(service)
  541. t = Thread.new { @srv.run }
  542. @srv.wait_till_running
  543. req = EchoMsg.new
  544. stub = EchoStub.new(@alt_host, :this_channel_is_insecure)
  545. op = stub.an_rpc(req, return_op: true, metadata: { k1: 'v1', k2: 'v2' })
  546. expect(op.metadata).to be nil
  547. expect(op.execute).to be_a(EchoMsg)
  548. expect(op.trailing_metadata).to eq(wanted_trailers)
  549. @srv.stop
  550. t.join
  551. end
  552. end
  553. context 'when call objects are used after calls have completed' do
  554. before(:each) do
  555. server_opts = {
  556. poll_period: 1
  557. }
  558. @srv = new_rpc_server_for_testing(**server_opts)
  559. alt_port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
  560. @alt_host = "0.0.0.0:#{alt_port}"
  561. @service = CheckCallAfterFinishedService.new
  562. @srv.handle(@service)
  563. @srv_thd = Thread.new { @srv.run }
  564. @srv.wait_till_running
  565. end
  566. # check that the server-side call is still in a usable state even
  567. # after it has finished
  568. def check_single_req_view_of_finished_call(call)
  569. common_check_of_finished_server_call(call)
  570. expect(call.peer).to be_a(String)
  571. expect(call.peer_cert).to be(nil)
  572. end
  573. def check_multi_req_view_of_finished_call(call)
  574. common_check_of_finished_server_call(call)
  575. expect do
  576. call.each_remote_read.each { |r| p r }
  577. end.to raise_error(GRPC::Core::CallError)
  578. end
  579. def common_check_of_finished_server_call(call)
  580. expect do
  581. call.merge_metadata_to_send({})
  582. end.to raise_error(RuntimeError)
  583. expect do
  584. call.send_initial_metadata
  585. end.to_not raise_error
  586. expect(call.cancelled?).to be(false)
  587. expect(call.metadata).to be_a(Hash)
  588. expect(call.metadata['user-agent']).to be_a(String)
  589. expect(call.metadata_sent).to be(true)
  590. expect(call.output_metadata).to eq({})
  591. expect(call.metadata_to_send).to eq({})
  592. expect(call.deadline.is_a?(Time)).to be(true)
  593. end
  594. it 'should not crash when call used after an unary call is finished' do
  595. req = EchoMsg.new
  596. stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
  597. :this_channel_is_insecure)
  598. resp = stub.an_rpc(req)
  599. expect(resp).to be_a(EchoMsg)
  600. @srv.stop
  601. @srv_thd.join
  602. check_single_req_view_of_finished_call(@service.server_side_call)
  603. end
  604. it 'should not crash when call used after client streaming finished' do
  605. requests = [EchoMsg.new, EchoMsg.new]
  606. stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
  607. :this_channel_is_insecure)
  608. resp = stub.a_client_streaming_rpc(requests)
  609. expect(resp).to be_a(EchoMsg)
  610. @srv.stop
  611. @srv_thd.join
  612. check_multi_req_view_of_finished_call(@service.server_side_call)
  613. end
  614. it 'should not crash when call used after server streaming finished' do
  615. req = EchoMsg.new
  616. stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
  617. :this_channel_is_insecure)
  618. responses = stub.a_server_streaming_rpc(req)
  619. responses.each do |r|
  620. expect(r).to be_a(EchoMsg)
  621. end
  622. @srv.stop
  623. @srv_thd.join
  624. check_single_req_view_of_finished_call(@service.server_side_call)
  625. end
  626. it 'should not crash when call used after a bidi call is finished' do
  627. requests = [EchoMsg.new, EchoMsg.new]
  628. stub = CheckCallAfterFinishedServiceStub.new(@alt_host,
  629. :this_channel_is_insecure)
  630. responses = stub.a_bidi_rpc(requests)
  631. responses.each do |r|
  632. expect(r).to be_a(EchoMsg)
  633. end
  634. @srv.stop
  635. @srv_thd.join
  636. check_multi_req_view_of_finished_call(@service.server_side_call)
  637. end
  638. end
  639. end
  640. end