grpc 1.60.0-aarch64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. checksums.yaml +7 -0
  2. data/etc/roots.pem +4337 -0
  3. data/grpc_c.32-msvcrt.ruby +0 -0
  4. data/grpc_c.64-msvcrt.ruby +0 -0
  5. data/grpc_c.64-ucrt.ruby +0 -0
  6. data/src/ruby/bin/math_client.rb +140 -0
  7. data/src/ruby/bin/math_pb.rb +40 -0
  8. data/src/ruby/bin/math_server.rb +191 -0
  9. data/src/ruby/bin/math_services_pb.rb +51 -0
  10. data/src/ruby/bin/noproto_client.rb +93 -0
  11. data/src/ruby/bin/noproto_server.rb +97 -0
  12. data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.clang +2 -0
  13. data/src/ruby/ext/grpc/ext-export-truffleruby-with-ruby-abi-version.gcc +7 -0
  14. data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.clang +2 -0
  15. data/src/ruby/ext/grpc/ext-export-with-ruby-abi-version.gcc +7 -0
  16. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  17. data/src/ruby/ext/grpc/ext-export.gcc +6 -0
  18. data/src/ruby/ext/grpc/extconf.rb +270 -0
  19. data/src/ruby/ext/grpc/rb_byte_buffer.c +65 -0
  20. data/src/ruby/ext/grpc/rb_byte_buffer.h +35 -0
  21. data/src/ruby/ext/grpc/rb_call.c +1075 -0
  22. data/src/ruby/ext/grpc/rb_call.h +57 -0
  23. data/src/ruby/ext/grpc/rb_call_credentials.c +340 -0
  24. data/src/ruby/ext/grpc/rb_call_credentials.h +31 -0
  25. data/src/ruby/ext/grpc/rb_channel.c +875 -0
  26. data/src/ruby/ext/grpc/rb_channel.h +35 -0
  27. data/src/ruby/ext/grpc/rb_channel_args.c +172 -0
  28. data/src/ruby/ext/grpc/rb_channel_args.h +42 -0
  29. data/src/ruby/ext/grpc/rb_channel_credentials.c +285 -0
  30. data/src/ruby/ext/grpc/rb_channel_credentials.h +37 -0
  31. data/src/ruby/ext/grpc/rb_completion_queue.c +101 -0
  32. data/src/ruby/ext/grpc/rb_completion_queue.h +36 -0
  33. data/src/ruby/ext/grpc/rb_compression_options.c +470 -0
  34. data/src/ruby/ext/grpc/rb_compression_options.h +29 -0
  35. data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
  36. data/src/ruby/ext/grpc/rb_event_thread.c +161 -0
  37. data/src/ruby/ext/grpc/rb_event_thread.h +22 -0
  38. data/src/ruby/ext/grpc/rb_grpc.c +496 -0
  39. data/src/ruby/ext/grpc/rb_grpc.h +83 -0
  40. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +603 -0
  41. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +910 -0
  42. data/src/ruby/ext/grpc/rb_loader.c +61 -0
  43. data/src/ruby/ext/grpc/rb_loader.h +25 -0
  44. data/src/ruby/ext/grpc/rb_server.c +405 -0
  45. data/src/ruby/ext/grpc/rb_server.h +32 -0
  46. data/src/ruby/ext/grpc/rb_server_credentials.c +258 -0
  47. data/src/ruby/ext/grpc/rb_server_credentials.h +37 -0
  48. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +217 -0
  49. data/src/ruby/ext/grpc/rb_xds_channel_credentials.h +37 -0
  50. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +169 -0
  51. data/src/ruby/ext/grpc/rb_xds_server_credentials.h +37 -0
  52. data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
  53. data/src/ruby/lib/grpc/3.0/grpc_c.so +0 -0
  54. data/src/ruby/lib/grpc/3.1/grpc_c.so +0 -0
  55. data/src/ruby/lib/grpc/3.2/grpc_c.so +0 -0
  56. data/src/ruby/lib/grpc/core/status_codes.rb +135 -0
  57. data/src/ruby/lib/grpc/core/time_consts.rb +56 -0
  58. data/src/ruby/lib/grpc/errors.rb +277 -0
  59. data/src/ruby/lib/grpc/generic/active_call.rb +670 -0
  60. data/src/ruby/lib/grpc/generic/bidi_call.rb +237 -0
  61. data/src/ruby/lib/grpc/generic/client_stub.rb +503 -0
  62. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  63. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  64. data/src/ruby/lib/grpc/generic/rpc_desc.rb +204 -0
  65. data/src/ruby/lib/grpc/generic/rpc_server.rb +551 -0
  66. data/src/ruby/lib/grpc/generic/service.rb +211 -0
  67. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +40 -0
  68. data/src/ruby/lib/grpc/grpc.rb +24 -0
  69. data/src/ruby/lib/grpc/logconfig.rb +44 -0
  70. data/src/ruby/lib/grpc/notifier.rb +45 -0
  71. data/src/ruby/lib/grpc/structs.rb +15 -0
  72. data/src/ruby/lib/grpc/version.rb +18 -0
  73. data/src/ruby/lib/grpc.rb +37 -0
  74. data/src/ruby/pb/README.md +42 -0
  75. data/src/ruby/pb/generate_proto_ruby.sh +46 -0
  76. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  77. data/src/ruby/pb/grpc/health/v1/health_pb.rb +42 -0
  78. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +62 -0
  79. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +44 -0
  80. data/src/ruby/pb/grpc/testing/metrics_pb.rb +28 -0
  81. data/src/ruby/pb/grpc/testing/metrics_services_pb.rb +49 -0
  82. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +38 -0
  83. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +71 -0
  84. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +40 -0
  85. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +174 -0
  86. data/src/ruby/pb/test/client.rb +785 -0
  87. data/src/ruby/pb/test/server.rb +252 -0
  88. data/src/ruby/pb/test/xds_client.rb +415 -0
  89. data/src/ruby/spec/call_credentials_spec.rb +42 -0
  90. data/src/ruby/spec/call_spec.rb +180 -0
  91. data/src/ruby/spec/channel_connection_spec.rb +126 -0
  92. data/src/ruby/spec/channel_credentials_spec.rb +124 -0
  93. data/src/ruby/spec/channel_spec.rb +207 -0
  94. data/src/ruby/spec/client_auth_spec.rb +152 -0
  95. data/src/ruby/spec/client_server_spec.rb +676 -0
  96. data/src/ruby/spec/compression_options_spec.rb +149 -0
  97. data/src/ruby/spec/debug_message_spec.rb +134 -0
  98. data/src/ruby/spec/error_sanity_spec.rb +49 -0
  99. data/src/ruby/spec/errors_spec.rb +142 -0
  100. data/src/ruby/spec/generic/active_call_spec.rb +692 -0
  101. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  102. data/src/ruby/spec/generic/client_stub_spec.rb +1083 -0
  103. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  104. data/src/ruby/spec/generic/rpc_desc_spec.rb +374 -0
  105. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +127 -0
  106. data/src/ruby/spec/generic/rpc_server_spec.rb +748 -0
  107. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  108. data/src/ruby/spec/generic/service_spec.rb +263 -0
  109. data/src/ruby/spec/google_rpc_status_utils_spec.rb +282 -0
  110. data/src/ruby/spec/pb/codegen/grpc/testing/package_options.proto +28 -0
  111. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
  112. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import2.proto +23 -0
  113. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +41 -0
  114. data/src/ruby/spec/pb/codegen/grpc/testing/same_package_service_name.proto +27 -0
  115. data/src/ruby/spec/pb/codegen/grpc/testing/same_ruby_package_service_name.proto +29 -0
  116. data/src/ruby/spec/pb/codegen/package_option_spec.rb +98 -0
  117. data/src/ruby/spec/pb/duplicate/codegen_spec.rb +57 -0
  118. data/src/ruby/spec/pb/health/checker_spec.rb +236 -0
  119. data/src/ruby/spec/server_credentials_spec.rb +104 -0
  120. data/src/ruby/spec/server_spec.rb +231 -0
  121. data/src/ruby/spec/spec_helper.rb +61 -0
  122. data/src/ruby/spec/support/helpers.rb +107 -0
  123. data/src/ruby/spec/support/services.rb +160 -0
  124. data/src/ruby/spec/testdata/README +1 -0
  125. data/src/ruby/spec/testdata/ca.pem +20 -0
  126. data/src/ruby/spec/testdata/client.key +28 -0
  127. data/src/ruby/spec/testdata/client.pem +20 -0
  128. data/src/ruby/spec/testdata/server1.key +28 -0
  129. data/src/ruby/spec/testdata/server1.pem +22 -0
  130. data/src/ruby/spec/time_consts_spec.rb +74 -0
  131. data/src/ruby/spec/user_agent_spec.rb +74 -0
  132. metadata +405 -0
@@ -0,0 +1,692 @@
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
+
15
+ require 'spec_helper'
16
+
17
+ include GRPC::Core::StatusCodes
18
+
19
+ describe GRPC::ActiveCall do
20
+ ActiveCall = GRPC::ActiveCall
21
+ Call = GRPC::Core::Call
22
+ CallOps = GRPC::Core::CallOps
23
+ WriteFlags = GRPC::Core::WriteFlags
24
+
25
+ def ok_status
26
+ Struct::Status.new(OK, 'OK')
27
+ end
28
+
29
+ def send_and_receive_close_and_status(client_call, server_call)
30
+ client_call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
31
+ server_call.run_batch(CallOps::RECV_CLOSE_ON_SERVER => nil,
32
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status)
33
+ client_call.run_batch(CallOps::RECV_STATUS_ON_CLIENT => nil)
34
+ end
35
+
36
+ def inner_call_of_active_call(active_call)
37
+ active_call.instance_variable_get(:@call)
38
+ end
39
+
40
+ before(:each) do
41
+ @pass_through = proc { |x| x }
42
+ host = '0.0.0.0:0'
43
+ @server = new_core_server_for_testing(nil)
44
+ server_port = @server.add_http2_port(host, :this_port_is_insecure)
45
+ @server.start
46
+ @received_rpcs_queue = Queue.new
47
+ @server_thread = Thread.new do
48
+ begin
49
+ received_rpc = @server.request_call
50
+ rescue GRPC::Core::CallError, StandardError => e
51
+ # enqueue the exception in this case as a way to indicate the error
52
+ received_rpc = e
53
+ end
54
+ @received_rpcs_queue.push(received_rpc)
55
+ end
56
+ @ch = GRPC::Core::Channel.new("0.0.0.0:#{server_port}", nil,
57
+ :this_channel_is_insecure)
58
+ end
59
+
60
+ after(:each) do
61
+ @server.shutdown_and_notify(deadline)
62
+ @server.close
63
+ @server_thread.join
64
+ end
65
+
66
+ describe 'restricted view methods' do
67
+ before(:each) do
68
+ @call = make_test_call
69
+ ActiveCall.client_invoke(@call)
70
+ @client_call = ActiveCall.new(@call, @pass_through,
71
+ @pass_through, deadline)
72
+ end
73
+
74
+ after(:each) do
75
+ # terminate the RPC that was started in before(:each)
76
+ recvd_rpc = @received_rpcs_queue.pop
77
+ recvd_call = recvd_rpc.call
78
+ recvd_call.run_batch(CallOps::SEND_INITIAL_METADATA => nil)
79
+ @call.run_batch(CallOps::RECV_INITIAL_METADATA => nil)
80
+ send_and_receive_close_and_status(@call, recvd_call)
81
+ end
82
+
83
+ describe '#multi_req_view' do
84
+ it 'exposes a fixed subset of the ActiveCall.methods' do
85
+ want = %w(cancelled?, deadline, each_remote_read, metadata, \
86
+ shutdown, peer, peer_cert, send_initial_metadata, \
87
+ initial_metadata_sent)
88
+ v = @client_call.multi_req_view
89
+ want.each do |w|
90
+ expect(v.methods.include?(w))
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '#single_req_view' do
96
+ it 'exposes a fixed subset of the ActiveCall.methods' do
97
+ want = %w(cancelled?, deadline, metadata, shutdown, \
98
+ send_initial_metadata, metadata_to_send, \
99
+ merge_metadata_to_send, initial_metadata_sent)
100
+ v = @client_call.single_req_view
101
+ want.each do |w|
102
+ expect(v.methods.include?(w))
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#interceptable' do
108
+ it 'exposes a fixed subset of the ActiveCall.methods' do
109
+ want = %w(deadline)
110
+ v = @client_call.interceptable
111
+ want.each do |w|
112
+ expect(v.methods.include?(w))
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#remote_send' do
119
+ it 'allows a client to send a payload to the server', test: true do
120
+ call = make_test_call
121
+ ActiveCall.client_invoke(call)
122
+ client_call = ActiveCall.new(call, @pass_through,
123
+ @pass_through, deadline)
124
+ msg = 'message is a string'
125
+ client_call.remote_send(msg)
126
+
127
+ # check that server rpc new was received
128
+ recvd_rpc = @received_rpcs_queue.pop
129
+ expect(recvd_rpc).to_not eq nil
130
+ recvd_call = recvd_rpc.call
131
+
132
+ # Accept the call, and verify that the server reads the response ok.
133
+ server_call = ActiveCall.new(recvd_call, @pass_through,
134
+ @pass_through, deadline,
135
+ metadata_received: true,
136
+ started: false)
137
+ expect(server_call.remote_read).to eq(msg)
138
+ # finish the call
139
+ server_call.send_initial_metadata
140
+ call.run_batch(CallOps::RECV_INITIAL_METADATA => nil)
141
+ send_and_receive_close_and_status(call, recvd_call)
142
+ end
143
+
144
+ it 'marshals the payload using the marshal func' do
145
+ call = make_test_call
146
+ ActiveCall.client_invoke(call)
147
+ marshal = proc { |x| 'marshalled:' + x }
148
+ client_call = ActiveCall.new(call, marshal, @pass_through, deadline)
149
+ msg = 'message is a string'
150
+ client_call.remote_send(msg)
151
+
152
+ # confirm that the message was marshalled
153
+ recvd_rpc = @received_rpcs_queue.pop
154
+ recvd_call = recvd_rpc.call
155
+ server_ops = {
156
+ CallOps::SEND_INITIAL_METADATA => nil
157
+ }
158
+ recvd_call.run_batch(server_ops)
159
+ server_call = ActiveCall.new(recvd_call, @pass_through,
160
+ @pass_through, deadline,
161
+ metadata_received: true)
162
+ expect(server_call.remote_read).to eq('marshalled:' + msg)
163
+ # finish the call
164
+ call.run_batch(CallOps::RECV_INITIAL_METADATA => nil)
165
+ send_and_receive_close_and_status(call, recvd_call)
166
+ end
167
+
168
+ TEST_WRITE_FLAGS = [WriteFlags::BUFFER_HINT, WriteFlags::NO_COMPRESS]
169
+ TEST_WRITE_FLAGS.each do |f|
170
+ it "successfully makes calls with write_flag set to #{f}" do
171
+ call = make_test_call
172
+ ActiveCall.client_invoke(call)
173
+ marshal = proc { |x| 'marshalled:' + x }
174
+ client_call = ActiveCall.new(call, marshal,
175
+ @pass_through, deadline)
176
+ msg = 'message is a string'
177
+ client_call.write_flag = f
178
+ client_call.remote_send(msg)
179
+ # flush the message in case writes are set to buffered
180
+ call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil) if f == 1
181
+
182
+ # confirm that the message was marshalled
183
+ recvd_rpc = @received_rpcs_queue.pop
184
+ recvd_call = recvd_rpc.call
185
+ server_ops = {
186
+ CallOps::SEND_INITIAL_METADATA => nil
187
+ }
188
+ recvd_call.run_batch(server_ops)
189
+ server_call = ActiveCall.new(recvd_call, @pass_through,
190
+ @pass_through, deadline,
191
+ metadata_received: true)
192
+ expect(server_call.remote_read).to eq('marshalled:' + msg)
193
+ # finish the call
194
+ server_call.send_status(OK, '', true)
195
+ client_call.receive_and_check_status
196
+ end
197
+ end
198
+ end
199
+
200
+ describe 'sending initial metadata', send_initial_metadata: true do
201
+ it 'sends metadata before sending a message if it hasnt been sent yet' do
202
+ call = make_test_call
203
+ @client_call = ActiveCall.new(
204
+ call,
205
+ @pass_through,
206
+ @pass_through,
207
+ deadline,
208
+ started: false)
209
+
210
+ metadata = { key: 'phony_val', other: 'other_val' }
211
+ expect(@client_call.metadata_sent).to eq(false)
212
+ @client_call.merge_metadata_to_send(metadata)
213
+
214
+ message = 'phony message'
215
+
216
+ expect(call).to(
217
+ receive(:run_batch)
218
+ .with(
219
+ hash_including(
220
+ CallOps::SEND_INITIAL_METADATA => metadata)).once)
221
+
222
+ expect(call).to(
223
+ receive(:run_batch).with(hash_including(
224
+ CallOps::SEND_MESSAGE => message)).once)
225
+ @client_call.remote_send(message)
226
+
227
+ expect(@client_call.metadata_sent).to eq(true)
228
+ end
229
+
230
+ it 'doesnt send metadata if it thinks its already been sent' do
231
+ call = make_test_call
232
+
233
+ @client_call = ActiveCall.new(call,
234
+ @pass_through,
235
+ @pass_through,
236
+ deadline)
237
+ expect(@client_call.metadata_sent).to eql(true)
238
+ expect(call).to(
239
+ receive(:run_batch).with(hash_including(
240
+ CallOps::SEND_INITIAL_METADATA)).never)
241
+
242
+ @client_call.remote_send('test message')
243
+ end
244
+
245
+ it 'sends metadata if it is explicitly sent and ok to do so' do
246
+ call = make_test_call
247
+
248
+ @client_call = ActiveCall.new(call,
249
+ @pass_through,
250
+ @pass_through,
251
+ deadline,
252
+ started: false)
253
+
254
+ expect(@client_call.metadata_sent).to eql(false)
255
+
256
+ metadata = { test_key: 'val' }
257
+ @client_call.merge_metadata_to_send(metadata)
258
+ expect(@client_call.metadata_to_send).to eq(metadata)
259
+
260
+ expect(call).to(
261
+ receive(:run_batch).with(hash_including(
262
+ CallOps::SEND_INITIAL_METADATA =>
263
+ metadata)).once)
264
+ @client_call.send_initial_metadata
265
+ end
266
+
267
+ it 'explicit sending does nothing if metadata has already been sent' do
268
+ call = make_test_call
269
+
270
+ @client_call = ActiveCall.new(call,
271
+ @pass_through,
272
+ @pass_through,
273
+ deadline)
274
+
275
+ expect(@client_call.metadata_sent).to eql(true)
276
+
277
+ blk = proc do
278
+ @client_call.send_initial_metadata
279
+ end
280
+
281
+ expect { blk.call }.to_not raise_error
282
+ end
283
+ end
284
+
285
+ describe '#merge_metadata_to_send', merge_metadata_to_send: true do
286
+ it 'adds to existing metadata when there is existing metadata to send' do
287
+ call = make_test_call
288
+ starting_metadata = {
289
+ k1: 'key1_val',
290
+ k2: 'key2_val',
291
+ k3: 'key3_val'
292
+ }
293
+
294
+ @client_call = ActiveCall.new(
295
+ call,
296
+ @pass_through, @pass_through,
297
+ deadline,
298
+ started: false,
299
+ metadata_to_send: starting_metadata)
300
+
301
+ expect(@client_call.metadata_to_send).to eq(starting_metadata)
302
+
303
+ @client_call.merge_metadata_to_send(
304
+ k3: 'key3_new_val',
305
+ k4: 'key4_val')
306
+
307
+ expected_md_to_send = {
308
+ k1: 'key1_val',
309
+ k2: 'key2_val',
310
+ k3: 'key3_new_val',
311
+ k4: 'key4_val' }
312
+
313
+ expect(@client_call.metadata_to_send).to eq(expected_md_to_send)
314
+
315
+ @client_call.merge_metadata_to_send(k5: 'key5_val')
316
+ expected_md_to_send.merge!(k5: 'key5_val')
317
+ expect(@client_call.metadata_to_send).to eq(expected_md_to_send)
318
+ end
319
+
320
+ it 'fails when initial metadata has already been sent' do
321
+ call = make_test_call
322
+ @client_call = ActiveCall.new(
323
+ call,
324
+ @pass_through,
325
+ @pass_through,
326
+ deadline,
327
+ started: true)
328
+
329
+ expect(@client_call.metadata_sent).to eq(true)
330
+
331
+ blk = proc do
332
+ @client_call.merge_metadata_to_send(k1: 'key1_val')
333
+ end
334
+
335
+ expect { blk.call }.to raise_error
336
+ end
337
+ end
338
+
339
+ describe '#client_invoke' do
340
+ it 'sends metadata to the server when present' do
341
+ call = make_test_call
342
+ metadata = { k1: 'v1', k2: 'v2' }
343
+ ActiveCall.client_invoke(call, metadata)
344
+ recvd_rpc = @received_rpcs_queue.pop
345
+ recvd_call = recvd_rpc.call
346
+ expect(recvd_call).to_not be_nil
347
+ expect(recvd_rpc.metadata).to_not be_nil
348
+ expect(recvd_rpc.metadata['k1']).to eq('v1')
349
+ expect(recvd_rpc.metadata['k2']).to eq('v2')
350
+ # finish the call
351
+ recvd_call.run_batch(CallOps::SEND_INITIAL_METADATA => {})
352
+ call.run_batch(CallOps::RECV_INITIAL_METADATA => nil)
353
+ send_and_receive_close_and_status(call, recvd_call)
354
+ end
355
+ end
356
+
357
+ describe '#send_status', send_status: true do
358
+ it 'works when no metadata or messages have been sent yet' do
359
+ call = make_test_call
360
+ ActiveCall.client_invoke(call)
361
+
362
+ recvd_rpc = @received_rpcs_queue.pop
363
+ server_call = ActiveCall.new(
364
+ recvd_rpc.call,
365
+ @pass_through,
366
+ @pass_through,
367
+ deadline,
368
+ started: false)
369
+
370
+ expect(server_call.metadata_sent).to eq(false)
371
+ blk = proc { server_call.send_status(OK) }
372
+ expect { blk.call }.to_not raise_error
373
+ end
374
+ end
375
+
376
+ describe '#remote_read', remote_read: true do
377
+ it 'reads the response sent by a server' do
378
+ call = make_test_call
379
+ ActiveCall.client_invoke(call)
380
+ client_call = ActiveCall.new(call, @pass_through,
381
+ @pass_through, deadline)
382
+ msg = 'message is a string'
383
+ client_call.remote_send(msg)
384
+ server_call = expect_server_to_receive(msg)
385
+ server_call.remote_send('server_response')
386
+ expect(client_call.remote_read).to eq('server_response')
387
+ send_and_receive_close_and_status(
388
+ call, inner_call_of_active_call(server_call))
389
+ end
390
+
391
+ it 'saves no metadata when the server adds no metadata' do
392
+ call = make_test_call
393
+ ActiveCall.client_invoke(call)
394
+ client_call = ActiveCall.new(call, @pass_through,
395
+ @pass_through, deadline)
396
+ msg = 'message is a string'
397
+ client_call.remote_send(msg)
398
+ server_call = expect_server_to_receive(msg)
399
+ server_call.remote_send('ignore me')
400
+ expect(client_call.metadata).to be_nil
401
+ client_call.remote_read
402
+ expect(client_call.metadata).to eq({})
403
+ send_and_receive_close_and_status(
404
+ call, inner_call_of_active_call(server_call))
405
+ end
406
+
407
+ it 'saves metadata add by the server' do
408
+ call = make_test_call
409
+ ActiveCall.client_invoke(call)
410
+ client_call = ActiveCall.new(call, @pass_through,
411
+ @pass_through, deadline)
412
+ msg = 'message is a string'
413
+ client_call.remote_send(msg)
414
+ server_call = expect_server_to_receive(msg, k1: 'v1', k2: 'v2')
415
+ server_call.remote_send('ignore me')
416
+ expect(client_call.metadata).to be_nil
417
+ client_call.remote_read
418
+ expected = { 'k1' => 'v1', 'k2' => 'v2' }
419
+ expect(client_call.metadata).to eq(expected)
420
+ send_and_receive_close_and_status(
421
+ call, inner_call_of_active_call(server_call))
422
+ end
423
+
424
+ it 'get a status from server when nothing else sent from server' do
425
+ client_call = make_test_call
426
+ ActiveCall.client_invoke(client_call)
427
+
428
+ recvd_rpc = @received_rpcs_queue.pop
429
+ recvd_call = recvd_rpc.call
430
+
431
+ server_call = ActiveCall.new(
432
+ recvd_call,
433
+ @pass_through,
434
+ @pass_through,
435
+ deadline,
436
+ started: false)
437
+
438
+ server_call.send_status(OK, 'OK')
439
+
440
+ # Check that we can receive initial metadata and a status
441
+ client_call.run_batch(
442
+ CallOps::RECV_INITIAL_METADATA => nil)
443
+ batch_result = client_call.run_batch(
444
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
445
+
446
+ expect(batch_result.status.code).to eq(OK)
447
+ end
448
+
449
+ it 'get a nil msg before a status when an OK status is sent' do
450
+ call = make_test_call
451
+ ActiveCall.client_invoke(call)
452
+ client_call = ActiveCall.new(call, @pass_through,
453
+ @pass_through, deadline)
454
+ msg = 'message is a string'
455
+ client_call.remote_send(msg)
456
+ call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
457
+ server_call = expect_server_to_receive(msg)
458
+ server_call.remote_send('server_response')
459
+ server_call.send_status(OK, 'OK')
460
+ expect(client_call.remote_read).to eq('server_response')
461
+ res = client_call.remote_read
462
+ expect(res).to be_nil
463
+ end
464
+
465
+ it 'unmarshals the response using the unmarshal func' do
466
+ call = make_test_call
467
+ ActiveCall.client_invoke(call)
468
+ unmarshal = proc { |x| 'unmarshalled:' + x }
469
+ client_call = ActiveCall.new(call, @pass_through,
470
+ unmarshal, deadline)
471
+
472
+ # confirm the client receives the unmarshalled message
473
+ msg = 'message is a string'
474
+ client_call.remote_send(msg)
475
+ server_call = expect_server_to_receive(msg)
476
+ server_call.remote_send('server_response')
477
+ expect(client_call.remote_read).to eq('unmarshalled:server_response')
478
+ send_and_receive_close_and_status(
479
+ call, inner_call_of_active_call(server_call))
480
+ end
481
+ end
482
+
483
+ describe '#each_remote_read' do
484
+ it 'creates an Enumerator' do
485
+ call = make_test_call
486
+ client_call = ActiveCall.new(call, @pass_through,
487
+ @pass_through, deadline)
488
+ expect(client_call.each_remote_read).to be_a(Enumerator)
489
+ # finish the call
490
+ client_call.cancel
491
+ end
492
+
493
+ it 'the returned enumerator can read n responses' do
494
+ call = make_test_call
495
+ ActiveCall.client_invoke(call)
496
+ client_call = ActiveCall.new(call, @pass_through,
497
+ @pass_through, deadline)
498
+ msg = 'message is a string'
499
+ reply = 'server_response'
500
+ client_call.remote_send(msg)
501
+ server_call = expect_server_to_receive(msg)
502
+ e = client_call.each_remote_read
503
+ n = 3 # arbitrary value > 1
504
+ n.times do
505
+ server_call.remote_send(reply)
506
+ expect(e.next).to eq(reply)
507
+ end
508
+ send_and_receive_close_and_status(
509
+ call, inner_call_of_active_call(server_call))
510
+ end
511
+
512
+ it 'the returns an enumerator that stops after an OK Status' do
513
+ call = make_test_call
514
+ ActiveCall.client_invoke(call)
515
+ client_call = ActiveCall.new(call, @pass_through,
516
+ @pass_through, deadline)
517
+ msg = 'message is a string'
518
+ reply = 'server_response'
519
+ client_call.remote_send(msg)
520
+ call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
521
+ server_call = expect_server_to_receive(msg)
522
+ e = client_call.each_remote_read
523
+ n = 3 # arbitrary value > 1
524
+ n.times do
525
+ server_call.remote_send(reply)
526
+ expect(e.next).to eq(reply)
527
+ end
528
+ server_call.send_status(OK, 'OK', true)
529
+ expect { e.next }.to raise_error(StopIteration)
530
+ end
531
+ end
532
+
533
+ describe '#closing the call from the client' do
534
+ it 'finishes ok if the server sends a status response' do
535
+ call = make_test_call
536
+ ActiveCall.client_invoke(call)
537
+ client_call = ActiveCall.new(call, @pass_through,
538
+ @pass_through, deadline)
539
+ msg = 'message is a string'
540
+ client_call.remote_send(msg)
541
+ expect do
542
+ call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
543
+ end.to_not raise_error
544
+ server_call = expect_server_to_receive(msg)
545
+ server_call.remote_send('server_response')
546
+ expect(client_call.remote_read).to eq('server_response')
547
+ server_call.send_status(OK, 'status code is OK')
548
+ expect { client_call.receive_and_check_status }.to_not raise_error
549
+ end
550
+
551
+ it 'finishes ok if the server sends an early status response' do
552
+ call = make_test_call
553
+ ActiveCall.client_invoke(call)
554
+ client_call = ActiveCall.new(call, @pass_through,
555
+ @pass_through, deadline)
556
+ msg = 'message is a string'
557
+ client_call.remote_send(msg)
558
+ server_call = expect_server_to_receive(msg)
559
+ server_call.remote_send('server_response')
560
+ server_call.send_status(OK, 'status code is OK')
561
+ expect(client_call.remote_read).to eq('server_response')
562
+ expect do
563
+ call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
564
+ end.to_not raise_error
565
+ expect { client_call.receive_and_check_status }.to_not raise_error
566
+ end
567
+
568
+ it 'finishes ok if SEND_CLOSE and RECV_STATUS has been sent' do
569
+ call = make_test_call
570
+ ActiveCall.client_invoke(call)
571
+ client_call = ActiveCall.new(call, @pass_through,
572
+ @pass_through, deadline)
573
+ msg = 'message is a string'
574
+ client_call.remote_send(msg)
575
+ server_call = expect_server_to_receive(msg)
576
+ server_call.remote_send('server_response')
577
+ server_call.send_status(OK, 'status code is OK')
578
+ expect(client_call.remote_read).to eq('server_response')
579
+ expect do
580
+ call.run_batch(
581
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil,
582
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
583
+ end.to_not raise_error
584
+ end
585
+ end
586
+
587
+ # Test sending of the initial metadata in #run_server_bidi
588
+ # from the server handler both implicitly and explicitly.
589
+ describe '#run_server_bidi metadata sending tests', run_server_bidi: true do
590
+ before(:each) do
591
+ @requests = ['first message', 'second message']
592
+ @server_to_client_metadata = { 'test_key' => 'test_val' }
593
+ @server_status = OK
594
+
595
+ @client_call = make_test_call
596
+ @client_call.run_batch(CallOps::SEND_INITIAL_METADATA => {})
597
+
598
+ recvd_rpc = @received_rpcs_queue.pop
599
+ recvd_call = recvd_rpc.call
600
+ @server_call = ActiveCall.new(
601
+ recvd_call,
602
+ @pass_through,
603
+ @pass_through,
604
+ deadline,
605
+ metadata_received: true,
606
+ started: false,
607
+ metadata_to_send: @server_to_client_metadata)
608
+ end
609
+
610
+ after(:each) do
611
+ # Send the requests and send a close so the server can send a status
612
+ @requests.each do |message|
613
+ @client_call.run_batch(CallOps::SEND_MESSAGE => message)
614
+ end
615
+ @client_call.run_batch(CallOps::SEND_CLOSE_FROM_CLIENT => nil)
616
+
617
+ @server_thread.join
618
+
619
+ # Expect that initial metadata was sent,
620
+ # the requests were echoed, and a status was sent
621
+ batch_result = @client_call.run_batch(
622
+ CallOps::RECV_INITIAL_METADATA => nil)
623
+ expect(batch_result.metadata).to eq(@server_to_client_metadata)
624
+
625
+ @requests.each do |message|
626
+ batch_result = @client_call.run_batch(
627
+ CallOps::RECV_MESSAGE => nil)
628
+ expect(batch_result.message).to eq(message)
629
+ end
630
+
631
+ batch_result = @client_call.run_batch(
632
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
633
+ expect(batch_result.status.code).to eq(@server_status)
634
+ end
635
+
636
+ it 'sends the initial metadata implicitly if not already sent' do
637
+ # Server handler that doesn't have access to a "call"
638
+ # It echoes the requests
639
+ fake_gen_each_reply_with_no_call_param = proc do |msgs|
640
+ msgs
641
+ end
642
+
643
+ int_ctx = GRPC::InterceptionContext.new
644
+
645
+ @server_thread = Thread.new do
646
+ @server_call.run_server_bidi(
647
+ fake_gen_each_reply_with_no_call_param, int_ctx)
648
+ @server_call.send_status(@server_status)
649
+ end
650
+ end
651
+
652
+ it 'sends the metadata when sent explicitly and not already sent' do
653
+ # Fake server handler that has access to a "call" object and
654
+ # uses it to explicitly update and send the initial metadata
655
+ fake_gen_each_reply_with_call_param = proc do |msgs, call_param|
656
+ call_param.merge_metadata_to_send(@server_to_client_metadata)
657
+ call_param.send_initial_metadata
658
+ msgs
659
+ end
660
+ int_ctx = GRPC::InterceptionContext.new
661
+
662
+ @server_thread = Thread.new do
663
+ @server_call.run_server_bidi(
664
+ fake_gen_each_reply_with_call_param, int_ctx)
665
+ @server_call.send_status(@server_status)
666
+ end
667
+ end
668
+ end
669
+
670
+ def expect_server_to_receive(sent_text, **kw)
671
+ c = expect_server_to_be_invoked(**kw)
672
+ expect(c.remote_read).to eq(sent_text)
673
+ c
674
+ end
675
+
676
+ def expect_server_to_be_invoked(**kw)
677
+ recvd_rpc = @received_rpcs_queue.pop
678
+ expect(recvd_rpc).to_not eq nil
679
+ recvd_call = recvd_rpc.call
680
+ recvd_call.run_batch(CallOps::SEND_INITIAL_METADATA => kw)
681
+ ActiveCall.new(recvd_call, @pass_through, @pass_through, deadline,
682
+ metadata_received: true, started: true)
683
+ end
684
+
685
+ def make_test_call
686
+ @ch.create_call(nil, nil, '/method', nil, deadline)
687
+ end
688
+
689
+ def deadline
690
+ Time.now + 2 # in 2 seconds; arbitrary
691
+ end
692
+ end