rpc_server_spec.rb 20 KB

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