grpc 1.30.2-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/etc/roots.pem +4644 -0
  3. data/grpc_c.32.ruby +0 -0
  4. data/grpc_c.64.ruby +0 -0
  5. data/src/ruby/bin/math_client.rb +140 -0
  6. data/src/ruby/bin/math_pb.rb +34 -0
  7. data/src/ruby/bin/math_server.rb +191 -0
  8. data/src/ruby/bin/math_services_pb.rb +51 -0
  9. data/src/ruby/bin/noproto_client.rb +93 -0
  10. data/src/ruby/bin/noproto_server.rb +97 -0
  11. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  12. data/src/ruby/ext/grpc/ext-export.gcc +6 -0
  13. data/src/ruby/ext/grpc/extconf.rb +107 -0
  14. data/src/ruby/ext/grpc/rb_byte_buffer.c +64 -0
  15. data/src/ruby/ext/grpc/rb_byte_buffer.h +35 -0
  16. data/src/ruby/ext/grpc/rb_call.c +1050 -0
  17. data/src/ruby/ext/grpc/rb_call.h +53 -0
  18. data/src/ruby/ext/grpc/rb_call_credentials.c +297 -0
  19. data/src/ruby/ext/grpc/rb_call_credentials.h +31 -0
  20. data/src/ruby/ext/grpc/rb_channel.c +835 -0
  21. data/src/ruby/ext/grpc/rb_channel.h +34 -0
  22. data/src/ruby/ext/grpc/rb_channel_args.c +155 -0
  23. data/src/ruby/ext/grpc/rb_channel_args.h +38 -0
  24. data/src/ruby/ext/grpc/rb_channel_credentials.c +267 -0
  25. data/src/ruby/ext/grpc/rb_channel_credentials.h +32 -0
  26. data/src/ruby/ext/grpc/rb_completion_queue.c +100 -0
  27. data/src/ruby/ext/grpc/rb_completion_queue.h +36 -0
  28. data/src/ruby/ext/grpc/rb_compression_options.c +470 -0
  29. data/src/ruby/ext/grpc/rb_compression_options.h +29 -0
  30. data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
  31. data/src/ruby/ext/grpc/rb_event_thread.c +143 -0
  32. data/src/ruby/ext/grpc/rb_event_thread.h +21 -0
  33. data/src/ruby/ext/grpc/rb_grpc.c +328 -0
  34. data/src/ruby/ext/grpc/rb_grpc.h +76 -0
  35. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +573 -0
  36. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +865 -0
  37. data/src/ruby/ext/grpc/rb_loader.c +57 -0
  38. data/src/ruby/ext/grpc/rb_loader.h +25 -0
  39. data/src/ruby/ext/grpc/rb_server.c +372 -0
  40. data/src/ruby/ext/grpc/rb_server.h +32 -0
  41. data/src/ruby/ext/grpc/rb_server_credentials.c +243 -0
  42. data/src/ruby/ext/grpc/rb_server_credentials.h +32 -0
  43. data/src/ruby/lib/grpc.rb +37 -0
  44. data/src/ruby/lib/grpc/2.3/grpc_c.so +0 -0
  45. data/src/ruby/lib/grpc/2.4/grpc_c.so +0 -0
  46. data/src/ruby/lib/grpc/2.5/grpc_c.so +0 -0
  47. data/src/ruby/lib/grpc/2.6/grpc_c.so +0 -0
  48. data/src/ruby/lib/grpc/2.7/grpc_c.so +0 -0
  49. data/src/ruby/lib/grpc/core/status_codes.rb +135 -0
  50. data/src/ruby/lib/grpc/core/time_consts.rb +56 -0
  51. data/src/ruby/lib/grpc/errors.rb +277 -0
  52. data/src/ruby/lib/grpc/generic/active_call.rb +669 -0
  53. data/src/ruby/lib/grpc/generic/bidi_call.rb +233 -0
  54. data/src/ruby/lib/grpc/generic/client_stub.rb +501 -0
  55. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  56. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  57. data/src/ruby/lib/grpc/generic/rpc_desc.rb +204 -0
  58. data/src/ruby/lib/grpc/generic/rpc_server.rb +551 -0
  59. data/src/ruby/lib/grpc/generic/service.rb +211 -0
  60. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +40 -0
  61. data/src/ruby/lib/grpc/grpc.rb +24 -0
  62. data/src/ruby/lib/grpc/logconfig.rb +44 -0
  63. data/src/ruby/lib/grpc/notifier.rb +45 -0
  64. data/src/ruby/lib/grpc/structs.rb +15 -0
  65. data/src/ruby/lib/grpc/version.rb +18 -0
  66. data/src/ruby/pb/README.md +42 -0
  67. data/src/ruby/pb/generate_proto_ruby.sh +51 -0
  68. data/src/ruby/pb/grpc/health/checker.rb +75 -0
  69. data/src/ruby/pb/grpc/health/v1/health_pb.rb +31 -0
  70. data/src/ruby/pb/grpc/health/v1/health_services_pb.rb +62 -0
  71. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +44 -0
  72. data/src/ruby/pb/grpc/testing/metrics_pb.rb +28 -0
  73. data/src/ruby/pb/grpc/testing/metrics_services_pb.rb +49 -0
  74. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +17 -0
  75. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +105 -0
  76. data/src/ruby/pb/src/proto/grpc/testing/test_pb.rb +16 -0
  77. data/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +118 -0
  78. data/src/ruby/pb/test/client.rb +769 -0
  79. data/src/ruby/pb/test/server.rb +252 -0
  80. data/src/ruby/pb/test/xds_client.rb +213 -0
  81. data/src/ruby/spec/call_credentials_spec.rb +42 -0
  82. data/src/ruby/spec/call_spec.rb +180 -0
  83. data/src/ruby/spec/channel_connection_spec.rb +126 -0
  84. data/src/ruby/spec/channel_credentials_spec.rb +82 -0
  85. data/src/ruby/spec/channel_spec.rb +234 -0
  86. data/src/ruby/spec/client_auth_spec.rb +126 -0
  87. data/src/ruby/spec/client_server_spec.rb +664 -0
  88. data/src/ruby/spec/compression_options_spec.rb +149 -0
  89. data/src/ruby/spec/debug_message_spec.rb +134 -0
  90. data/src/ruby/spec/error_sanity_spec.rb +49 -0
  91. data/src/ruby/spec/errors_spec.rb +142 -0
  92. data/src/ruby/spec/generic/active_call_spec.rb +672 -0
  93. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  94. data/src/ruby/spec/generic/client_stub_spec.rb +1083 -0
  95. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  96. data/src/ruby/spec/generic/rpc_desc_spec.rb +374 -0
  97. data/src/ruby/spec/generic/rpc_server_pool_spec.rb +127 -0
  98. data/src/ruby/spec/generic/rpc_server_spec.rb +748 -0
  99. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  100. data/src/ruby/spec/generic/service_spec.rb +263 -0
  101. data/src/ruby/spec/google_rpc_status_utils_spec.rb +282 -0
  102. data/src/ruby/spec/pb/codegen/grpc/testing/package_options.proto +28 -0
  103. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
  104. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import2.proto +23 -0
  105. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +41 -0
  106. data/src/ruby/spec/pb/codegen/package_option_spec.rb +82 -0
  107. data/src/ruby/spec/pb/duplicate/codegen_spec.rb +57 -0
  108. data/src/ruby/spec/pb/health/checker_spec.rb +236 -0
  109. data/src/ruby/spec/server_credentials_spec.rb +79 -0
  110. data/src/ruby/spec/server_spec.rb +209 -0
  111. data/src/ruby/spec/spec_helper.rb +61 -0
  112. data/src/ruby/spec/support/helpers.rb +107 -0
  113. data/src/ruby/spec/support/services.rb +160 -0
  114. data/src/ruby/spec/testdata/README +1 -0
  115. data/src/ruby/spec/testdata/ca.pem +20 -0
  116. data/src/ruby/spec/testdata/client.key +28 -0
  117. data/src/ruby/spec/testdata/client.pem +20 -0
  118. data/src/ruby/spec/testdata/server1.key +28 -0
  119. data/src/ruby/spec/testdata/server1.pem +22 -0
  120. data/src/ruby/spec/time_consts_spec.rb +74 -0
  121. metadata +394 -0
@@ -0,0 +1,126 @@
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
+ def create_channel_creds
18
+ test_root = File.join(File.dirname(__FILE__), 'testdata')
19
+ files = ['ca.pem', 'client.key', 'client.pem']
20
+ creds = files.map { |f| File.open(File.join(test_root, f)).read }
21
+ GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
22
+ end
23
+
24
+ def client_cert
25
+ test_root = File.join(File.dirname(__FILE__), 'testdata')
26
+ cert = File.open(File.join(test_root, 'client.pem')).read
27
+ fail unless cert.is_a?(String)
28
+ cert
29
+ end
30
+
31
+ def create_server_creds
32
+ test_root = File.join(File.dirname(__FILE__), 'testdata')
33
+ GRPC.logger.info("test root: #{test_root}")
34
+ files = ['ca.pem', 'server1.key', 'server1.pem']
35
+ creds = files.map { |f| File.open(File.join(test_root, f)).read }
36
+ GRPC::Core::ServerCredentials.new(
37
+ creds[0],
38
+ [{ private_key: creds[1], cert_chain: creds[2] }],
39
+ true) # force client auth
40
+ end
41
+
42
+ # a test service that checks the cert of its peer
43
+ class SslTestService
44
+ include GRPC::GenericService
45
+ rpc :an_rpc, EchoMsg, EchoMsg
46
+ rpc :a_client_streaming_rpc, stream(EchoMsg), EchoMsg
47
+ rpc :a_server_streaming_rpc, EchoMsg, stream(EchoMsg)
48
+ rpc :a_bidi_rpc, stream(EchoMsg), stream(EchoMsg)
49
+
50
+ def check_peer_cert(call)
51
+ error_msg = "want:\n#{client_cert}\n\ngot:\n#{call.peer_cert}"
52
+ fail(error_msg) unless call.peer_cert == client_cert
53
+ end
54
+
55
+ def an_rpc(req, call)
56
+ check_peer_cert(call)
57
+ req
58
+ end
59
+
60
+ def a_client_streaming_rpc(call)
61
+ check_peer_cert(call)
62
+ call.each_remote_read.each { |r| GRPC.logger.info(r) }
63
+ EchoMsg.new
64
+ end
65
+
66
+ def a_server_streaming_rpc(_, call)
67
+ check_peer_cert(call)
68
+ [EchoMsg.new, EchoMsg.new]
69
+ end
70
+
71
+ def a_bidi_rpc(requests, call)
72
+ check_peer_cert(call)
73
+ requests.each { |r| GRPC.logger.info(r) }
74
+ [EchoMsg.new, EchoMsg.new]
75
+ end
76
+ end
77
+
78
+ SslTestServiceStub = SslTestService.rpc_stub_class
79
+
80
+ describe 'client-server auth' do
81
+ RpcServer = GRPC::RpcServer
82
+
83
+ before(:all) do
84
+ server_opts = {
85
+ poll_period: 1
86
+ }
87
+ @srv = new_rpc_server_for_testing(**server_opts)
88
+ port = @srv.add_http2_port('0.0.0.0:0', create_server_creds)
89
+ @srv.handle(SslTestService)
90
+ @srv_thd = Thread.new { @srv.run }
91
+ @srv.wait_till_running
92
+
93
+ client_opts = {
94
+ channel_args: {
95
+ GRPC::Core::Channel::SSL_TARGET => 'foo.test.google.fr'
96
+ }
97
+ }
98
+ @stub = SslTestServiceStub.new("localhost:#{port}",
99
+ create_channel_creds,
100
+ **client_opts)
101
+ end
102
+
103
+ after(:all) do
104
+ expect(@srv.stopped?).to be(false)
105
+ @srv.stop
106
+ @srv_thd.join
107
+ end
108
+
109
+ it 'client-server auth with unary RPCs' do
110
+ @stub.an_rpc(EchoMsg.new)
111
+ end
112
+
113
+ it 'client-server auth with client streaming RPCs' do
114
+ @stub.a_client_streaming_rpc([EchoMsg.new, EchoMsg.new])
115
+ end
116
+
117
+ it 'client-server auth with server streaming RPCs' do
118
+ responses = @stub.a_server_streaming_rpc(EchoMsg.new)
119
+ responses.each { |r| GRPC.logger.info(r) }
120
+ end
121
+
122
+ it 'client-server auth with bidi RPCs' do
123
+ responses = @stub.a_bidi_rpc([EchoMsg.new, EchoMsg.new])
124
+ responses.each { |r| GRPC.logger.info(r) }
125
+ end
126
+ end
@@ -0,0 +1,664 @@
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
18
+
19
+ shared_context 'setup: tags' do
20
+ let(:sent_message) { 'sent message' }
21
+ let(:reply_text) { 'the reply' }
22
+
23
+ def deadline
24
+ Time.now + 5
25
+ end
26
+
27
+ def server_allows_client_to_proceed(metadata = {})
28
+ recvd_rpc = @server.request_call
29
+ expect(recvd_rpc).to_not eq nil
30
+ server_call = recvd_rpc.call
31
+ ops = { CallOps::SEND_INITIAL_METADATA => metadata }
32
+ server_batch = server_call.run_batch(ops)
33
+ expect(server_batch.send_metadata).to be true
34
+ server_call
35
+ end
36
+
37
+ def new_client_call
38
+ @ch.create_call(nil, nil, '/method', nil, deadline)
39
+ end
40
+
41
+ def ok_status
42
+ Struct::Status.new(StatusCodes::OK, 'OK')
43
+ end
44
+ end
45
+
46
+ shared_examples 'basic GRPC message delivery is OK' do
47
+ include GRPC::Core
48
+ include_context 'setup: tags'
49
+
50
+ context 'the test channel' do
51
+ it 'should have a target' do
52
+ expect(@ch.target).to be_a(String)
53
+ end
54
+ end
55
+
56
+ context 'a client call' do
57
+ it 'should have a peer' do
58
+ expect(new_client_call.peer).to be_a(String)
59
+ end
60
+ end
61
+
62
+ it 'calls have peer info' do
63
+ call = new_client_call
64
+ expect(call.peer).to be_a(String)
65
+ end
66
+
67
+ it 'servers receive requests from clients and can respond' do
68
+ call = new_client_call
69
+ server_call = nil
70
+
71
+ server_thread = Thread.new do
72
+ server_call = server_allows_client_to_proceed
73
+ end
74
+
75
+ client_ops = {
76
+ CallOps::SEND_INITIAL_METADATA => {},
77
+ CallOps::SEND_MESSAGE => sent_message,
78
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
79
+ }
80
+ client_batch = call.run_batch(client_ops)
81
+ expect(client_batch.send_metadata).to be true
82
+ expect(client_batch.send_message).to be true
83
+ expect(client_batch.send_close).to be true
84
+
85
+ # confirm the server can read the inbound message
86
+ server_thread.join
87
+ server_ops = {
88
+ CallOps::RECV_MESSAGE => nil,
89
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
90
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status
91
+ }
92
+ server_batch = server_call.run_batch(server_ops)
93
+ expect(server_batch.message).to eq(sent_message)
94
+ expect(server_batch.send_close).to be true
95
+ expect(server_batch.send_status).to be true
96
+
97
+ # finish the call
98
+ final_client_batch = call.run_batch(
99
+ CallOps::RECV_INITIAL_METADATA => nil,
100
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
101
+ expect(final_client_batch.metadata).to eq({})
102
+ expect(final_client_batch.status.code).to eq(0)
103
+ end
104
+
105
+ it 'responses written by servers are received by the client' do
106
+ call = new_client_call
107
+ server_call = nil
108
+
109
+ server_thread = Thread.new do
110
+ server_call = server_allows_client_to_proceed
111
+ end
112
+
113
+ client_ops = {
114
+ CallOps::SEND_INITIAL_METADATA => {},
115
+ CallOps::SEND_MESSAGE => sent_message,
116
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
117
+ }
118
+ client_batch = call.run_batch(client_ops)
119
+ expect(client_batch.send_metadata).to be true
120
+ expect(client_batch.send_message).to be true
121
+ expect(client_batch.send_close).to be true
122
+
123
+ # confirm the server can read the inbound message
124
+ server_thread.join
125
+ server_ops = {
126
+ CallOps::RECV_MESSAGE => nil,
127
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
128
+ CallOps::SEND_MESSAGE => reply_text,
129
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status
130
+ }
131
+ server_batch = server_call.run_batch(server_ops)
132
+ expect(server_batch.message).to eq(sent_message)
133
+ expect(server_batch.send_close).to be true
134
+ expect(server_batch.send_message).to be true
135
+ expect(server_batch.send_status).to be true
136
+
137
+ # finish the call
138
+ final_client_batch = call.run_batch(
139
+ CallOps::RECV_INITIAL_METADATA => nil,
140
+ CallOps::RECV_MESSAGE => nil,
141
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
142
+ expect(final_client_batch.metadata).to eq({})
143
+ expect(final_client_batch.message).to eq(reply_text)
144
+ expect(final_client_batch.status.code).to eq(0)
145
+ end
146
+
147
+ it 'compressed messages can be sent and received' do
148
+ call = new_client_call
149
+ server_call = nil
150
+ long_request_str = '0' * 2000
151
+ long_response_str = '1' * 2000
152
+ md = { 'grpc-internal-encoding-request' => 'gzip' }
153
+
154
+ server_thread = Thread.new do
155
+ server_call = server_allows_client_to_proceed(md)
156
+ end
157
+
158
+ client_ops = {
159
+ CallOps::SEND_INITIAL_METADATA => md,
160
+ CallOps::SEND_MESSAGE => long_request_str,
161
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
162
+ }
163
+ client_batch = call.run_batch(client_ops)
164
+ expect(client_batch.send_metadata).to be true
165
+ expect(client_batch.send_message).to be true
166
+ expect(client_batch.send_close).to be true
167
+
168
+ # confirm the server can read the inbound message
169
+ server_thread.join
170
+ server_ops = {
171
+ CallOps::RECV_MESSAGE => nil,
172
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
173
+ CallOps::SEND_MESSAGE => long_response_str,
174
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status
175
+ }
176
+ server_batch = server_call.run_batch(server_ops)
177
+ expect(server_batch.message).to eq(long_request_str)
178
+ expect(server_batch.send_close).to be true
179
+ expect(server_batch.send_message).to be true
180
+ expect(server_batch.send_status).to be true
181
+
182
+ client_ops = {
183
+ CallOps::RECV_INITIAL_METADATA => nil,
184
+ CallOps::RECV_MESSAGE => nil,
185
+ CallOps::RECV_STATUS_ON_CLIENT => nil
186
+ }
187
+ final_client_batch = call.run_batch(client_ops)
188
+ expect(final_client_batch.metadata).to eq({})
189
+ expect(final_client_batch.message).to eq long_response_str
190
+ expect(final_client_batch.status.code).to eq(0)
191
+ end
192
+
193
+ it 'servers can ignore a client write and send a status' do
194
+ call = new_client_call
195
+ server_call = nil
196
+
197
+ server_thread = Thread.new do
198
+ server_call = server_allows_client_to_proceed
199
+ end
200
+
201
+ client_ops = {
202
+ CallOps::SEND_INITIAL_METADATA => {},
203
+ CallOps::SEND_MESSAGE => sent_message,
204
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
205
+ }
206
+ client_batch = call.run_batch(client_ops)
207
+ expect(client_batch.send_metadata).to be true
208
+ expect(client_batch.send_message).to be true
209
+ expect(client_batch.send_close).to be true
210
+
211
+ # confirm the server can read the inbound message
212
+ the_status = Struct::Status.new(StatusCodes::OK, 'OK')
213
+ server_thread.join
214
+ server_ops = {
215
+ CallOps::SEND_STATUS_FROM_SERVER => the_status
216
+ }
217
+ server_batch = server_call.run_batch(server_ops)
218
+ expect(server_batch.message).to eq nil
219
+ expect(server_batch.send_status).to be true
220
+
221
+ final_client_batch = call.run_batch(
222
+ CallOps::RECV_INITIAL_METADATA => nil,
223
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
224
+ expect(final_client_batch.metadata).to eq({})
225
+ expect(final_client_batch.status.code).to eq(0)
226
+ end
227
+
228
+ it 'completes calls by sending status to client and server' do
229
+ call = new_client_call
230
+ server_call = nil
231
+
232
+ server_thread = Thread.new do
233
+ server_call = server_allows_client_to_proceed
234
+ end
235
+
236
+ client_ops = {
237
+ CallOps::SEND_INITIAL_METADATA => {},
238
+ CallOps::SEND_MESSAGE => sent_message
239
+ }
240
+ client_batch = call.run_batch(client_ops)
241
+ expect(client_batch.send_metadata).to be true
242
+ expect(client_batch.send_message).to be true
243
+
244
+ # confirm the server can read the inbound message and respond
245
+ the_status = Struct::Status.new(StatusCodes::OK, 'OK', {})
246
+ server_thread.join
247
+ server_ops = {
248
+ CallOps::RECV_MESSAGE => nil,
249
+ CallOps::SEND_MESSAGE => reply_text,
250
+ CallOps::SEND_STATUS_FROM_SERVER => the_status
251
+ }
252
+ server_batch = server_call.run_batch(server_ops)
253
+ expect(server_batch.message).to eq sent_message
254
+ expect(server_batch.send_status).to be true
255
+ expect(server_batch.send_message).to be true
256
+
257
+ # confirm the client can receive the server response and status.
258
+ client_ops = {
259
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil,
260
+ CallOps::RECV_INITIAL_METADATA => nil,
261
+ CallOps::RECV_MESSAGE => nil,
262
+ CallOps::RECV_STATUS_ON_CLIENT => nil
263
+ }
264
+ final_client_batch = call.run_batch(client_ops)
265
+ expect(final_client_batch.send_close).to be true
266
+ expect(final_client_batch.message).to eq reply_text
267
+ expect(final_client_batch.status).to eq the_status
268
+
269
+ # confirm the server can receive the client close.
270
+ server_ops = {
271
+ CallOps::RECV_CLOSE_ON_SERVER => nil
272
+ }
273
+ final_server_batch = server_call.run_batch(server_ops)
274
+ expect(final_server_batch.send_close).to be true
275
+ end
276
+
277
+ def client_cancel_test(cancel_proc, expected_code,
278
+ expected_details)
279
+ call = new_client_call
280
+ server_call = nil
281
+
282
+ server_thread = Thread.new do
283
+ server_call = server_allows_client_to_proceed
284
+ end
285
+
286
+ client_ops = {
287
+ CallOps::SEND_INITIAL_METADATA => {},
288
+ CallOps::RECV_INITIAL_METADATA => nil
289
+ }
290
+ client_batch = call.run_batch(client_ops)
291
+ expect(client_batch.send_metadata).to be true
292
+ expect(client_batch.metadata).to eq({})
293
+
294
+ cancel_proc.call(call)
295
+
296
+ server_thread.join
297
+ server_ops = {
298
+ CallOps::RECV_CLOSE_ON_SERVER => nil
299
+ }
300
+ server_batch = server_call.run_batch(server_ops)
301
+ expect(server_batch.send_close).to be true
302
+
303
+ client_ops = {
304
+ CallOps::RECV_STATUS_ON_CLIENT => {}
305
+ }
306
+ client_batch = call.run_batch(client_ops)
307
+
308
+ expect(client_batch.status.code).to be expected_code
309
+ expect(client_batch.status.details).to eq expected_details
310
+ end
311
+
312
+ it 'clients can cancel a call on the server' do
313
+ expected_code = StatusCodes::CANCELLED
314
+ expected_details = 'Cancelled'
315
+ cancel_proc = proc { |call| call.cancel }
316
+ client_cancel_test(cancel_proc, expected_code, expected_details)
317
+ end
318
+
319
+ it 'cancel_with_status unknown status' do
320
+ code = StatusCodes::UNKNOWN
321
+ details = 'test unknown reason'
322
+ cancel_proc = proc { |call| call.cancel_with_status(code, details) }
323
+ client_cancel_test(cancel_proc, code, details)
324
+ end
325
+
326
+ it 'cancel_with_status unknown status' do
327
+ code = StatusCodes::FAILED_PRECONDITION
328
+ details = 'test failed precondition reason'
329
+ cancel_proc = proc { |call| call.cancel_with_status(code, details) }
330
+ client_cancel_test(cancel_proc, code, details)
331
+ end
332
+ end
333
+
334
+ shared_examples 'GRPC metadata delivery works OK' do
335
+ include_context 'setup: tags'
336
+
337
+ describe 'from client => server' do
338
+ before(:example) do
339
+ n = 7 # arbitrary number of metadata
340
+ diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
341
+ diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
342
+ null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
343
+ null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
344
+ same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
345
+ same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
346
+ symbol_key = { a_key: 'a val' }
347
+ @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
348
+ @bad_keys = []
349
+ @bad_keys << { Object.new => 'a value' }
350
+ @bad_keys << { 1 => 'a value' }
351
+ end
352
+
353
+ it 'raises an exception if a metadata key is invalid' do
354
+ @bad_keys.each do |md|
355
+ call = new_client_call
356
+ client_ops = {
357
+ CallOps::SEND_INITIAL_METADATA => md
358
+ }
359
+ blk = proc do
360
+ call.run_batch(client_ops)
361
+ end
362
+ expect(&blk).to raise_error
363
+ end
364
+ end
365
+
366
+ it 'sends all the metadata pairs when keys and values are valid' do
367
+ @valid_metadata.each do |md|
368
+ recvd_rpc = nil
369
+ rcv_thread = Thread.new do
370
+ recvd_rpc = @server.request_call
371
+ end
372
+
373
+ call = new_client_call
374
+ client_ops = {
375
+ CallOps::SEND_INITIAL_METADATA => md,
376
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
377
+ }
378
+ client_batch = call.run_batch(client_ops)
379
+ expect(client_batch.send_metadata).to be true
380
+
381
+ # confirm the server can receive the client metadata
382
+ rcv_thread.join
383
+ expect(recvd_rpc).to_not eq nil
384
+ recvd_md = recvd_rpc.metadata
385
+ replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
386
+ expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
387
+
388
+ # finish the call
389
+ final_server_batch = recvd_rpc.call.run_batch(
390
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
391
+ CallOps::SEND_INITIAL_METADATA => nil,
392
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status)
393
+ expect(final_server_batch.send_close).to be(true)
394
+ expect(final_server_batch.send_metadata).to be(true)
395
+ expect(final_server_batch.send_status).to be(true)
396
+
397
+ final_client_batch = call.run_batch(
398
+ CallOps::RECV_INITIAL_METADATA => nil,
399
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
400
+ expect(final_client_batch.metadata).to eq({})
401
+ expect(final_client_batch.status.code).to eq(0)
402
+ end
403
+ end
404
+ end
405
+
406
+ describe 'from server => client' do
407
+ before(:example) do
408
+ n = 7 # arbitrary number of metadata
409
+ diff_keys_fn = proc { |i| [format('k%d', i), format('v%d', i)] }
410
+ diff_keys = Hash[n.times.collect { |x| diff_keys_fn.call x }]
411
+ null_vals_fn = proc { |i| [format('k%d', i), format('v\0%d', i)] }
412
+ null_vals = Hash[n.times.collect { |x| null_vals_fn.call x }]
413
+ same_keys_fn = proc { |i| [format('k%d', i), [format('v%d', i)] * n] }
414
+ same_keys = Hash[n.times.collect { |x| same_keys_fn.call x }]
415
+ symbol_key = { a_key: 'a val' }
416
+ @valid_metadata = [diff_keys, same_keys, null_vals, symbol_key]
417
+ @bad_keys = []
418
+ @bad_keys << { Object.new => 'a value' }
419
+ @bad_keys << { 1 => 'a value' }
420
+ end
421
+
422
+ it 'raises an exception if a metadata key is invalid' do
423
+ @bad_keys.each do |md|
424
+ recvd_rpc = nil
425
+ rcv_thread = Thread.new do
426
+ recvd_rpc = @server.request_call
427
+ end
428
+
429
+ call = new_client_call
430
+ # client signals that it's done sending metadata to allow server to
431
+ # respond
432
+ client_ops = {
433
+ CallOps::SEND_INITIAL_METADATA => nil
434
+ }
435
+ call.run_batch(client_ops)
436
+
437
+ # server gets the invocation
438
+ rcv_thread.join
439
+ expect(recvd_rpc).to_not eq nil
440
+ server_ops = {
441
+ CallOps::SEND_INITIAL_METADATA => md
442
+ }
443
+ blk = proc do
444
+ recvd_rpc.call.run_batch(server_ops)
445
+ end
446
+ expect(&blk).to raise_error
447
+
448
+ # cancel the call so the server can shut down immediately
449
+ call.cancel
450
+ end
451
+ end
452
+
453
+ it 'sends an empty hash if no metadata is added' do
454
+ recvd_rpc = nil
455
+ rcv_thread = Thread.new do
456
+ recvd_rpc = @server.request_call
457
+ end
458
+
459
+ call = new_client_call
460
+ # client signals that it's done sending metadata to allow server to
461
+ # respond
462
+ client_ops = {
463
+ CallOps::SEND_INITIAL_METADATA => nil,
464
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
465
+ }
466
+ client_batch = call.run_batch(client_ops)
467
+ expect(client_batch.send_metadata).to be true
468
+ expect(client_batch.send_close).to be true
469
+
470
+ # server gets the invocation but sends no metadata back
471
+ rcv_thread.join
472
+ expect(recvd_rpc).to_not eq nil
473
+ server_call = recvd_rpc.call
474
+ server_ops = {
475
+ # receive close and send status to finish the call
476
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
477
+ CallOps::SEND_INITIAL_METADATA => nil,
478
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status
479
+ }
480
+ srv_batch = server_call.run_batch(server_ops)
481
+ expect(srv_batch.send_close).to be true
482
+ expect(srv_batch.send_metadata).to be true
483
+ expect(srv_batch.send_status).to be true
484
+
485
+ # client receives nothing as expected
486
+ client_ops = {
487
+ CallOps::RECV_INITIAL_METADATA => nil,
488
+ # receive status to finish the call
489
+ CallOps::RECV_STATUS_ON_CLIENT => nil
490
+ }
491
+ final_client_batch = call.run_batch(client_ops)
492
+ expect(final_client_batch.metadata).to eq({})
493
+ expect(final_client_batch.status.code).to eq(0)
494
+ end
495
+
496
+ it 'sends all the pairs when keys and values are valid' do
497
+ @valid_metadata.each do |md|
498
+ recvd_rpc = nil
499
+ rcv_thread = Thread.new do
500
+ recvd_rpc = @server.request_call
501
+ end
502
+
503
+ call = new_client_call
504
+ # client signals that it's done sending metadata to allow server to
505
+ # respond
506
+ client_ops = {
507
+ CallOps::SEND_INITIAL_METADATA => nil,
508
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil
509
+ }
510
+ client_batch = call.run_batch(client_ops)
511
+ expect(client_batch.send_metadata).to be true
512
+ expect(client_batch.send_close).to be true
513
+
514
+ # server gets the invocation but sends no metadata back
515
+ rcv_thread.join
516
+ expect(recvd_rpc).to_not eq nil
517
+ server_call = recvd_rpc.call
518
+ server_ops = {
519
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
520
+ CallOps::SEND_INITIAL_METADATA => md,
521
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status
522
+ }
523
+ srv_batch = server_call.run_batch(server_ops)
524
+ expect(srv_batch.send_close).to be true
525
+ expect(srv_batch.send_metadata).to be true
526
+ expect(srv_batch.send_status).to be true
527
+
528
+ # client receives nothing as expected
529
+ client_ops = {
530
+ CallOps::RECV_INITIAL_METADATA => nil,
531
+ CallOps::RECV_STATUS_ON_CLIENT => nil
532
+ }
533
+ final_client_batch = call.run_batch(client_ops)
534
+ replace_symbols = Hash[md.each_pair.collect { |x, y| [x.to_s, y] }]
535
+ expect(final_client_batch.metadata).to eq(replace_symbols)
536
+ expect(final_client_batch.status.code).to eq(0)
537
+ end
538
+ end
539
+ end
540
+ end
541
+
542
+ describe 'the http client/server' do
543
+ before(:example) do
544
+ server_host = '0.0.0.0:0'
545
+ @server = new_core_server_for_testing(nil)
546
+ server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
547
+ @server.start
548
+ @ch = Channel.new("0.0.0.0:#{server_port}", nil, :this_channel_is_insecure)
549
+ end
550
+
551
+ after(:example) do
552
+ @ch.close
553
+ @server.shutdown_and_notify(deadline)
554
+ @server.close
555
+ end
556
+
557
+ it_behaves_like 'basic GRPC message delivery is OK' do
558
+ end
559
+
560
+ it_behaves_like 'GRPC metadata delivery works OK' do
561
+ end
562
+ end
563
+
564
+ describe 'the secure http client/server' do
565
+ include_context 'setup: tags'
566
+
567
+ def load_test_certs
568
+ test_root = File.join(File.dirname(__FILE__), 'testdata')
569
+ files = ['ca.pem', 'server1.key', 'server1.pem']
570
+ files.map { |f| File.open(File.join(test_root, f)).read }
571
+ end
572
+
573
+ before(:example) do
574
+ certs = load_test_certs
575
+ server_host = '0.0.0.0:0'
576
+ server_creds = GRPC::Core::ServerCredentials.new(
577
+ nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
578
+ @server = new_core_server_for_testing(nil)
579
+ server_port = @server.add_http2_port(server_host, server_creds)
580
+ @server.start
581
+ args = { Channel::SSL_TARGET => 'foo.test.google.fr' }
582
+ @ch = Channel.new("0.0.0.0:#{server_port}", args,
583
+ GRPC::Core::ChannelCredentials.new(certs[0], nil, nil))
584
+ end
585
+
586
+ after(:example) do
587
+ @server.shutdown_and_notify(deadline)
588
+ @server.close
589
+ end
590
+
591
+ it_behaves_like 'basic GRPC message delivery is OK' do
592
+ end
593
+
594
+ it_behaves_like 'GRPC metadata delivery works OK' do
595
+ end
596
+
597
+ def credentials_update_test(creds_update_md)
598
+ auth_proc = proc { creds_update_md }
599
+ call_creds = GRPC::Core::CallCredentials.new(auth_proc)
600
+
601
+ initial_md_key = 'k2'
602
+ initial_md_val = 'v2'
603
+ initial_md = { initial_md_key => initial_md_val }
604
+ expected_md = creds_update_md.clone
605
+ fail 'bad test param' unless expected_md[initial_md_key].nil?
606
+ expected_md[initial_md_key] = initial_md_val
607
+
608
+ recvd_rpc = nil
609
+ rcv_thread = Thread.new do
610
+ recvd_rpc = @server.request_call
611
+ end
612
+
613
+ call = new_client_call
614
+ call.set_credentials! call_creds
615
+
616
+ client_batch = call.run_batch(
617
+ CallOps::SEND_INITIAL_METADATA => initial_md,
618
+ CallOps::SEND_CLOSE_FROM_CLIENT => nil)
619
+ expect(client_batch.send_metadata).to be true
620
+ expect(client_batch.send_close).to be true
621
+
622
+ # confirm the server can receive the client metadata
623
+ rcv_thread.join
624
+ expect(recvd_rpc).to_not eq nil
625
+ recvd_md = recvd_rpc.metadata
626
+ replace_symbols = Hash[expected_md.each_pair.collect { |x, y| [x.to_s, y] }]
627
+ expect(recvd_md).to eq(recvd_md.merge(replace_symbols))
628
+
629
+ credentials_update_test_finish_call(call, recvd_rpc.call)
630
+ end
631
+
632
+ def credentials_update_test_finish_call(client_call, server_call)
633
+ final_server_batch = server_call.run_batch(
634
+ CallOps::RECV_CLOSE_ON_SERVER => nil,
635
+ CallOps::SEND_INITIAL_METADATA => nil,
636
+ CallOps::SEND_STATUS_FROM_SERVER => ok_status)
637
+ expect(final_server_batch.send_close).to be(true)
638
+ expect(final_server_batch.send_metadata).to be(true)
639
+ expect(final_server_batch.send_status).to be(true)
640
+
641
+ final_client_batch = client_call.run_batch(
642
+ CallOps::RECV_INITIAL_METADATA => nil,
643
+ CallOps::RECV_STATUS_ON_CLIENT => nil)
644
+ expect(final_client_batch.metadata).to eq({})
645
+ expect(final_client_batch.status.code).to eq(0)
646
+ end
647
+
648
+ it 'modifies metadata with CallCredentials' do
649
+ credentials_update_test('k1' => 'updated-v1')
650
+ end
651
+
652
+ it 'modifies large metadata with CallCredentials' do
653
+ val_array = %w(
654
+ '00000000000000000000000000000000000000000000000000000000000000',
655
+ '11111111111111111111111111111111111111111111111111111111111111',
656
+ )
657
+ md = {
658
+ k3: val_array,
659
+ k4: '0000000000000000000000000000000000000000000000000000000000',
660
+ keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey5: 'v1'
661
+ }
662
+ credentials_update_test(md)
663
+ end
664
+ end