grpc 0.10.0 → 0.11.0

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/bin/{interop/test/cpp/interop/test.rb → grpc_ruby_interop_client} +4 -14
  4. data/bin/{interop/test/cpp/interop/empty.rb → grpc_ruby_interop_server} +4 -15
  5. data/bin/interop/interop_client.rb +9 -335
  6. data/bin/interop/interop_server.rb +9 -153
  7. data/bin/math_client.rb +3 -3
  8. data/bin/math_server.rb +18 -1
  9. data/bin/noproto_server.rb +2 -1
  10. data/ext/grpc/rb_call.c +82 -15
  11. data/ext/grpc/rb_channel.c +141 -11
  12. data/ext/grpc/rb_channel_args.c +2 -1
  13. data/ext/grpc/rb_completion_queue.c +8 -7
  14. data/ext/grpc/rb_credentials.c +7 -6
  15. data/ext/grpc/rb_grpc.c +23 -8
  16. data/ext/grpc/rb_server.c +31 -45
  17. data/ext/grpc/rb_server_credentials.c +91 -34
  18. data/lib/grpc/generic/active_call.rb +7 -7
  19. data/lib/grpc/generic/bidi_call.rb +17 -12
  20. data/lib/grpc/generic/client_stub.rb +88 -22
  21. data/lib/grpc/generic/rpc_server.rb +19 -18
  22. data/lib/grpc/generic/service.rb +8 -10
  23. data/lib/grpc/grpc.so +0 -0
  24. data/lib/grpc/logconfig.rb +26 -10
  25. data/lib/grpc/version.rb +1 -1
  26. data/spec/call_spec.rb +9 -1
  27. data/spec/channel_spec.rb +2 -2
  28. data/spec/client_server_spec.rb +28 -11
  29. data/spec/credentials_spec.rb +7 -7
  30. data/spec/generic/active_call_spec.rb +43 -18
  31. data/spec/generic/client_stub_spec.rb +21 -1
  32. data/spec/generic/rpc_server_spec.rb +20 -9
  33. data/spec/pb/health/checker_spec.rb +232 -0
  34. data/spec/server_credentials_spec.rb +32 -7
  35. data/spec/server_spec.rb +8 -4
  36. data/spec/spec_helper.rb +13 -1
  37. metadata +31 -51
  38. data/.gitignore +0 -15
  39. data/.rspec +0 -4
  40. data/.rubocop.yml +0 -10
  41. data/.rubocop_todo.yml +0 -44
  42. data/CHANGELOG.md +0 -11
  43. data/Gemfile +0 -4
  44. data/README.md +0 -84
  45. data/bin/interop/README.md +0 -8
  46. data/bin/interop/test/cpp/interop/messages.rb +0 -89
  47. data/bin/interop/test/cpp/interop/test_services.rb +0 -60
  48. data/grpc.gemspec +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 296a3415a75bad4a6d252472eea237cc77517ca0
4
- data.tar.gz: facb8556323b3884eb64b8d9cf9332ee18502eed
3
+ metadata.gz: b272ebd68681b700d46662fda7888004ed93abda
4
+ data.tar.gz: 9ed56e0929ed31e957390ce91d8c9c97dd66ca2d
5
5
  SHA512:
6
- metadata.gz: 416c3b38ba0f659d6bf05fcc794a88fd7142a72f9b313229ffeb1d7f1adcf0d80ae78454ae38fc1e4d587f9ce430131f06d81d3dc7c028a7a69f800ab1ea8a1f
7
- data.tar.gz: be7d80cafebe1a21aa9fa4f0f3fd1b19a447fffa641c2828f11de540e371157e39673b9841f07d9a1f251d41050160a6f3f7d181cceb09fd7e5ab77cb31d700d
6
+ metadata.gz: 4d355d654d8cfedbffff3f454f11fb866eaf515ba0ca6dfcd38d0e23f7341902e0d3e824535ed2d77520eeaf97518b7b60055aeef596fd5dfa31b2fa729b763c
7
+ data.tar.gz: d2eae88c15cb5b1d551bed405657ba0dea498bf858367f6cc4ac3a815626b89bcd39e05c88917551522afd42da68c6ff36a12bf419ede487658a4535c285240d
data/Rakefile CHANGED
@@ -20,7 +20,8 @@ SPEC_SUITES = [
20
20
  { id: :bidi, title: 'bidi tests', dir: %w(spec/generic),
21
21
  tag: 'bidi' },
22
22
  { id: :server, title: 'rpc server thread tests', dir: %w(spec/generic),
23
- tag: 'server' }
23
+ tag: 'server' },
24
+ { id: :pb, title: 'protobuf service tests', dir: %w(spec/pb) }
24
25
  ]
25
26
  namespace :suite do
26
27
  SPEC_SUITES.each do |suite|
@@ -50,7 +51,8 @@ task 'suite:wrapper' => [:compile, :rubocop]
50
51
  task 'suite:idiomatic' => 'suite:wrapper'
51
52
  task 'suite:bidi' => 'suite:wrapper'
52
53
  task 'suite:server' => 'suite:wrapper'
54
+ task 'suite:pb' => 'suite:server'
53
55
 
54
56
  desc 'Compiles the gRPC extension then runs all the tests'
55
- task all: ['suite:idiomatic', 'suite:bidi', 'suite:server']
57
+ task all: ['suite:idiomatic', 'suite:bidi', 'suite:pb', 'suite:server']
56
58
  task default: :all
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
1
3
  # Copyright 2015, Google Inc.
2
4
  # All rights reserved.
3
5
  #
@@ -27,17 +29,5 @@
27
29
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
30
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
31
 
30
- # Generated by the protocol buffer compiler. DO NOT EDIT!
31
- # source: test/cpp/interop/test.proto
32
-
33
- require 'google/protobuf'
34
-
35
- require 'test/cpp/interop/empty'
36
- require 'test/cpp/interop/messages'
37
- Google::Protobuf::DescriptorPool.generated_pool.build do
38
- end
39
-
40
- module Grpc
41
- module Testing
42
- end
43
- end
32
+ # Provides a gem binary entry point for the interop client.
33
+ require 'test/client'
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
1
3
  # Copyright 2015, Google Inc.
2
4
  # All rights reserved.
3
5
  #
@@ -27,18 +29,5 @@
27
29
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
30
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
31
 
30
- # Generated by the protocol buffer compiler. DO NOT EDIT!
31
- # source: test/cpp/interop/empty.proto
32
-
33
- require 'google/protobuf'
34
-
35
- Google::Protobuf::DescriptorPool.generated_pool.build do
36
- add_message "grpc.testing.Empty" do
37
- end
38
- end
39
-
40
- module Grpc
41
- module Testing
42
- Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Empty").msgclass
43
- end
44
- end
32
+ # Provides a gem binary entry point for the interop server
33
+ require 'test/server'
@@ -29,6 +29,12 @@
29
29
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
30
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
31
 
32
+ # #######################################################################
33
+ # DEPRECATED: The behaviour in this file has been moved to pb/test/client.rb
34
+ #
35
+ # This file remains to support existing tools and scripts that use it.
36
+ # ######################################################################
37
+ #
32
38
  # interop_client is a testing tool that accesses a gRPC interop testing
33
39
  # server and runs a test on it.
34
40
  #
@@ -39,339 +45,7 @@
39
45
  # --test_case=<testcase_name>
40
46
 
41
47
  this_dir = File.expand_path(File.dirname(__FILE__))
42
- lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
43
- $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
44
- $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
45
-
46
- require 'optparse'
47
- require 'minitest'
48
- require 'minitest/assertions'
49
-
50
- require 'grpc'
51
- require 'googleauth'
52
- require 'google/protobuf'
53
-
54
- require 'test/cpp/interop/test_services'
55
- require 'test/cpp/interop/messages'
56
- require 'test/cpp/interop/empty'
57
-
58
- require 'signet/ssl_config'
59
-
60
- AUTH_ENV = Google::Auth::CredentialsLoader::ENV_VAR
61
-
62
- # loads the certificates used to access the test server securely.
63
- def load_test_certs
64
- this_dir = File.expand_path(File.dirname(__FILE__))
65
- data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
66
- files = ['ca.pem', 'server1.key', 'server1.pem']
67
- files.map { |f| File.open(File.join(data_dir, f)).read }
68
- end
69
-
70
- # loads the certificates used to access the test server securely.
71
- def load_prod_cert
72
- fail 'could not find a production cert' if ENV['SSL_CERT_FILE'].nil?
73
- GRPC.logger.info("loading prod certs from #{ENV['SSL_CERT_FILE']}")
74
- File.open(ENV['SSL_CERT_FILE']).read
75
- end
76
-
77
- # creates SSL Credentials from the test certificates.
78
- def test_creds
79
- certs = load_test_certs
80
- GRPC::Core::Credentials.new(certs[0])
81
- end
82
-
83
- # creates SSL Credentials from the production certificates.
84
- def prod_creds
85
- cert_text = load_prod_cert
86
- GRPC::Core::Credentials.new(cert_text)
87
- end
88
-
89
- # creates the SSL Credentials.
90
- def ssl_creds(use_test_ca)
91
- return test_creds if use_test_ca
92
- prod_creds
93
- end
94
-
95
- # creates a test stub that accesses host:port securely.
96
- def create_stub(opts)
97
- address = "#{opts.host}:#{opts.port}"
98
- if opts.secure
99
- stub_opts = {
100
- :creds => ssl_creds(opts.use_test_ca),
101
- GRPC::Core::Channel::SSL_TARGET => opts.host_override
102
- }
103
-
104
- # Add service account creds if specified
105
- wants_creds = %w(all compute_engine_creds service_account_creds)
106
- if wants_creds.include?(opts.test_case)
107
- unless opts.oauth_scope.nil?
108
- auth_creds = Google::Auth.get_application_default(opts.oauth_scope)
109
- stub_opts[:update_metadata] = auth_creds.updater_proc
110
- end
111
- end
112
-
113
- if opts.test_case == 'jwt_token_creds' # don't use a scope
114
- auth_creds = Google::Auth.get_application_default
115
- stub_opts[:update_metadata] = auth_creds.updater_proc
116
- end
117
-
118
- GRPC.logger.info("... connecting securely to #{address}")
119
- Grpc::Testing::TestService::Stub.new(address, **stub_opts)
120
- else
121
- GRPC.logger.info("... connecting insecurely to #{address}")
122
- Grpc::Testing::TestService::Stub.new(address)
123
- end
124
- end
125
-
126
- # produces a string of null chars (\0) of length l.
127
- def nulls(l)
128
- fail 'requires #{l} to be +ve' if l < 0
129
- [].pack('x' * l).force_encoding('utf-8')
130
- end
131
-
132
- # a PingPongPlayer implements the ping pong bidi test.
133
- class PingPongPlayer
134
- include Minitest::Assertions
135
- include Grpc::Testing
136
- include Grpc::Testing::PayloadType
137
- attr_accessor :assertions # required by Minitest::Assertions
138
- attr_accessor :queue
139
- attr_accessor :canceller_op
140
-
141
- # reqs is the enumerator over the requests
142
- def initialize(msg_sizes)
143
- @queue = Queue.new
144
- @msg_sizes = msg_sizes
145
- @assertions = 0 # required by Minitest::Assertions
146
- @canceller_op = nil # used to cancel after the first response
147
- end
148
-
149
- def each_item
150
- return enum_for(:each_item) unless block_given?
151
- req_cls, p_cls = StreamingOutputCallRequest, ResponseParameters # short
152
- count = 0
153
- @msg_sizes.each do |m|
154
- req_size, resp_size = m
155
- req = req_cls.new(payload: Payload.new(body: nulls(req_size)),
156
- response_type: :COMPRESSABLE,
157
- response_parameters: [p_cls.new(size: resp_size)])
158
- yield req
159
- resp = @queue.pop
160
- assert_equal(:COMPRESSABLE, resp.payload.type, 'payload type is wrong')
161
- assert_equal(resp_size, resp.payload.body.length,
162
- "payload body #{count} has the wrong length")
163
- p "OK: ping_pong #{count}"
164
- count += 1
165
- unless @canceller_op.nil?
166
- canceller_op.cancel
167
- break
168
- end
169
- end
170
- end
171
- end
172
-
173
- # defines methods corresponding to each interop test case.
174
- class NamedTests
175
- include Minitest::Assertions
176
- include Grpc::Testing
177
- include Grpc::Testing::PayloadType
178
- attr_accessor :assertions # required by Minitest::Assertions
179
-
180
- def initialize(stub, args)
181
- @assertions = 0 # required by Minitest::Assertions
182
- @stub = stub
183
- @args = args
184
- end
185
-
186
- def empty_unary
187
- resp = @stub.empty_call(Empty.new)
188
- assert resp.is_a?(Empty), 'empty_unary: invalid response'
189
- p 'OK: empty_unary'
190
- end
191
-
192
- def large_unary
193
- perform_large_unary
194
- p 'OK: large_unary'
195
- end
196
-
197
- def service_account_creds
198
- # ignore this test if the oauth options are not set
199
- if @args.oauth_scope.nil?
200
- p 'NOT RUN: service_account_creds; no service_account settings'
201
- return
202
- end
203
- json_key = File.read(ENV[AUTH_ENV])
204
- wanted_email = MultiJson.load(json_key)['client_email']
205
- resp = perform_large_unary(fill_username: true,
206
- fill_oauth_scope: true)
207
- assert_equal(wanted_email, resp.username,
208
- 'service_account_creds: incorrect username')
209
- assert(@args.oauth_scope.include?(resp.oauth_scope),
210
- 'service_account_creds: incorrect oauth_scope')
211
- p 'OK: service_account_creds'
212
- end
213
-
214
- def jwt_token_creds
215
- json_key = File.read(ENV[AUTH_ENV])
216
- wanted_email = MultiJson.load(json_key)['client_email']
217
- resp = perform_large_unary(fill_username: true)
218
- assert_equal(wanted_email, resp.username,
219
- 'service_account_creds: incorrect username')
220
- p 'OK: jwt_token_creds'
221
- end
222
-
223
- def compute_engine_creds
224
- resp = perform_large_unary(fill_username: true,
225
- fill_oauth_scope: true)
226
- assert_equal(@args.default_service_account, resp.username,
227
- 'compute_engine_creds: incorrect username')
228
- p 'OK: compute_engine_creds'
229
- end
230
-
231
- def client_streaming
232
- msg_sizes = [27_182, 8, 1828, 45_904]
233
- wanted_aggregate_size = 74_922
234
- reqs = msg_sizes.map do |x|
235
- req = Payload.new(body: nulls(x))
236
- StreamingInputCallRequest.new(payload: req)
237
- end
238
- resp = @stub.streaming_input_call(reqs)
239
- assert_equal(wanted_aggregate_size, resp.aggregated_payload_size,
240
- 'client_streaming: aggregate payload size is incorrect')
241
- p 'OK: client_streaming'
242
- end
243
-
244
- def server_streaming
245
- msg_sizes = [31_415, 9, 2653, 58_979]
246
- response_spec = msg_sizes.map { |s| ResponseParameters.new(size: s) }
247
- req = StreamingOutputCallRequest.new(response_type: :COMPRESSABLE,
248
- response_parameters: response_spec)
249
- resps = @stub.streaming_output_call(req)
250
- resps.each_with_index do |r, i|
251
- assert i < msg_sizes.length, 'too many responses'
252
- assert_equal(:COMPRESSABLE, r.payload.type,
253
- 'payload type is wrong')
254
- assert_equal(msg_sizes[i], r.payload.body.length,
255
- 'payload body #{i} has the wrong length')
256
- end
257
- p 'OK: server_streaming'
258
- end
259
-
260
- def ping_pong
261
- msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
262
- ppp = PingPongPlayer.new(msg_sizes)
263
- resps = @stub.full_duplex_call(ppp.each_item)
264
- resps.each { |r| ppp.queue.push(r) }
265
- p 'OK: ping_pong'
266
- end
267
-
268
- def cancel_after_begin
269
- msg_sizes = [27_182, 8, 1828, 45_904]
270
- reqs = msg_sizes.map do |x|
271
- req = Payload.new(body: nulls(x))
272
- StreamingInputCallRequest.new(payload: req)
273
- end
274
- op = @stub.streaming_input_call(reqs, return_op: true)
275
- op.cancel
276
- assert_raises(GRPC::Cancelled) { op.execute }
277
- assert(op.cancelled, 'call operation should be CANCELLED')
278
- p 'OK: cancel_after_begin'
279
- end
280
-
281
- def cancel_after_first_response
282
- msg_sizes = [[27_182, 31_415], [8, 9], [1828, 2653], [45_904, 58_979]]
283
- ppp = PingPongPlayer.new(msg_sizes)
284
- op = @stub.full_duplex_call(ppp.each_item, return_op: true)
285
- ppp.canceller_op = op # causes ppp to cancel after the 1st message
286
- op.execute.each { |r| ppp.queue.push(r) }
287
- op.wait
288
- assert(op.cancelled, 'call operation was not CANCELLED')
289
- p 'OK: cancel_after_first_response'
290
- end
291
-
292
- def all
293
- all_methods = NamedTests.instance_methods(false).map(&:to_s)
294
- all_methods.each do |m|
295
- next if m == 'all' || m.start_with?('assert')
296
- p "TESTCASE: #{m}"
297
- method(m).call
298
- end
299
- end
300
-
301
- private
302
-
303
- def perform_large_unary(fill_username: false, fill_oauth_scope: false)
304
- req_size, wanted_response_size = 271_828, 314_159
305
- payload = Payload.new(type: :COMPRESSABLE, body: nulls(req_size))
306
- req = SimpleRequest.new(response_type: :COMPRESSABLE,
307
- response_size: wanted_response_size,
308
- payload: payload)
309
- req.fill_username = fill_username
310
- req.fill_oauth_scope = fill_oauth_scope
311
- resp = @stub.unary_call(req)
312
- assert_equal(:COMPRESSABLE, resp.payload.type,
313
- 'large_unary: payload had the wrong type')
314
- assert_equal(wanted_response_size, resp.payload.body.length,
315
- 'large_unary: payload had the wrong length')
316
- assert_equal(nulls(wanted_response_size), resp.payload.body,
317
- 'large_unary: payload content is invalid')
318
- resp
319
- end
320
- end
321
-
322
- # Args is used to hold the command line info.
323
- Args = Struct.new(:default_service_account, :host, :host_override,
324
- :oauth_scope, :port, :secure, :test_case,
325
- :use_test_ca)
326
-
327
- # validates the the command line options, returning them as a Hash.
328
- def parse_args
329
- args = Args.new
330
- args.host_override = 'foo.test.google.fr'
331
- OptionParser.new do |opts|
332
- opts.on('--oauth_scope scope',
333
- 'Scope for OAuth tokens') { |v| args['oauth_scope'] = v }
334
- opts.on('--server_host SERVER_HOST', 'server hostname') do |v|
335
- args['host'] = v
336
- end
337
- opts.on('--default_service_account email_address',
338
- 'email address of the default service account') do |v|
339
- args['default_service_account'] = v
340
- end
341
- opts.on('--server_host_override HOST_OVERRIDE',
342
- 'override host via a HTTP header') do |v|
343
- args['host_override'] = v
344
- end
345
- opts.on('--server_port SERVER_PORT', 'server port') { |v| args['port'] = v }
346
- # instance_methods(false) gives only the methods defined in that class
347
- test_cases = NamedTests.instance_methods(false).map(&:to_s)
348
- test_case_list = test_cases.join(',')
349
- opts.on('--test_case CODE', test_cases, {}, 'select a test_case',
350
- " (#{test_case_list})") { |v| args['test_case'] = v }
351
- opts.on('-s', '--use_tls', 'require a secure connection?') do |v|
352
- args['secure'] = v
353
- end
354
- opts.on('-t', '--use_test_ca',
355
- 'if secure, use the test certificate?') do |v|
356
- args['use_test_ca'] = v
357
- end
358
- end.parse!
359
- _check_args(args)
360
- end
361
-
362
- def _check_args(args)
363
- %w(host port test_case).each do |a|
364
- if args[a].nil?
365
- fail(OptionParser::MissingArgument, "please specify --#{arg}")
366
- end
367
- end
368
- args
369
- end
370
-
371
- def main
372
- opts = parse_args
373
- stub = create_stub(opts)
374
- NamedTests.new(stub, opts).method(opts['test_case']).call
375
- end
48
+ pb_dir = File.join(File.dirname(File.dirname(this_dir)), 'pb')
49
+ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
376
50
 
377
- main
51
+ require 'test/client'
@@ -29,6 +29,12 @@
29
29
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
30
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
31
 
32
+ # #######################################################################
33
+ # DEPRECATED: The behaviour in this file has been moved to pb/test/server.rb
34
+ #
35
+ # This file remains to support existing tools and scripts that use it.
36
+ # ######################################################################
37
+ #
32
38
  # interop_server is a Testing app that runs a gRPC interop testing server.
33
39
  #
34
40
  # It helps validate interoperation b/w gRPC in different environments
@@ -38,157 +44,7 @@
38
44
  # Usage: $ path/to/interop_server.rb --port
39
45
 
40
46
  this_dir = File.expand_path(File.dirname(__FILE__))
41
- lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
42
- $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
43
- $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
44
-
45
- require 'forwardable'
46
- require 'optparse'
47
-
48
- require 'grpc'
49
-
50
- require 'test/cpp/interop/test_services'
51
- require 'test/cpp/interop/messages'
52
- require 'test/cpp/interop/empty'
53
-
54
- # loads the certificates by the test server.
55
- def load_test_certs
56
- this_dir = File.expand_path(File.dirname(__FILE__))
57
- data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
58
- files = ['ca.pem', 'server1.key', 'server1.pem']
59
- files.map { |f| File.open(File.join(data_dir, f)).read }
60
- end
61
-
62
- # creates a ServerCredentials from the test certificates.
63
- def test_server_creds
64
- certs = load_test_certs
65
- GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
66
- end
67
-
68
- # produces a string of null chars (\0) of length l.
69
- def nulls(l)
70
- fail 'requires #{l} to be +ve' if l < 0
71
- [].pack('x' * l).force_encoding('utf-8')
72
- end
73
-
74
- # A EnumeratorQueue wraps a Queue yielding the items added to it via each_item.
75
- class EnumeratorQueue
76
- extend Forwardable
77
- def_delegators :@q, :push
78
-
79
- def initialize(sentinel)
80
- @q = Queue.new
81
- @sentinel = sentinel
82
- end
83
-
84
- def each_item
85
- return enum_for(:each_item) unless block_given?
86
- loop do
87
- r = @q.pop
88
- break if r.equal?(@sentinel)
89
- fail r if r.is_a? Exception
90
- yield r
91
- end
92
- end
93
- end
94
-
95
- # A runnable implementation of the schema-specified testing service, with each
96
- # service method implemented as required by the interop testing spec.
97
- class TestTarget < Grpc::Testing::TestService::Service
98
- include Grpc::Testing
99
- include Grpc::Testing::PayloadType
100
-
101
- def empty_call(_empty, _call)
102
- Empty.new
103
- end
104
-
105
- def unary_call(simple_req, _call)
106
- req_size = simple_req.response_size
107
- SimpleResponse.new(payload: Payload.new(type: :COMPRESSABLE,
108
- body: nulls(req_size)))
109
- end
110
-
111
- def streaming_input_call(call)
112
- sizes = call.each_remote_read.map { |x| x.payload.body.length }
113
- sum = sizes.inject { |s, x| s + x }
114
- StreamingInputCallResponse.new(aggregated_payload_size: sum)
115
- end
116
-
117
- def streaming_output_call(req, _call)
118
- cls = StreamingOutputCallResponse
119
- req.response_parameters.map do |p|
120
- cls.new(payload: Payload.new(type: req.response_type,
121
- body: nulls(p.size)))
122
- end
123
- end
124
-
125
- def full_duplex_call(reqs)
126
- # reqs is a lazy Enumerator of the requests sent by the client.
127
- q = EnumeratorQueue.new(self)
128
- cls = StreamingOutputCallResponse
129
- Thread.new do
130
- begin
131
- GRPC.logger.info('interop-server: started receiving')
132
- reqs.each do |req|
133
- resp_size = req.response_parameters[0].size
134
- GRPC.logger.info("read a req, response size is #{resp_size}")
135
- resp = cls.new(payload: Payload.new(type: req.response_type,
136
- body: nulls(resp_size)))
137
- q.push(resp)
138
- end
139
- GRPC.logger.info('interop-server: finished receiving')
140
- q.push(self)
141
- rescue StandardError => e
142
- GRPC.logger.info('interop-server: failed')
143
- GRPC.logger.warn(e)
144
- q.push(e) # share the exception with the enumerator
145
- end
146
- end
147
- q.each_item
148
- end
149
-
150
- def half_duplex_call(reqs)
151
- # TODO: update with unique behaviour of the half_duplex_call if that's
152
- # ever required by any of the tests.
153
- full_duplex_call(reqs)
154
- end
155
- end
156
-
157
- # validates the the command line options, returning them as a Hash.
158
- def parse_options
159
- options = {
160
- 'port' => nil,
161
- 'secure' => false
162
- }
163
- OptionParser.new do |opts|
164
- opts.banner = 'Usage: --port port'
165
- opts.on('--port PORT', 'server port') do |v|
166
- options['port'] = v
167
- end
168
- opts.on('-s', '--use_tls', 'require a secure connection?') do |v|
169
- options['secure'] = v
170
- end
171
- end.parse!
172
-
173
- if options['port'].nil?
174
- fail(OptionParser::MissingArgument, 'please specify --port')
175
- end
176
- options
177
- end
178
-
179
- def main
180
- opts = parse_options
181
- host = "0.0.0.0:#{opts['port']}"
182
- s = GRPC::RpcServer.new
183
- if opts['secure']
184
- s.add_http2_port(host, test_server_creds)
185
- GRPC.logger.info("... running securely on #{host}")
186
- else
187
- s.add_http2_port(host)
188
- GRPC.logger.info("... running insecurely on #{host}")
189
- end
190
- s.handle(TestTarget)
191
- s.run_till_terminated
192
- end
47
+ pb_dir = File.join(File.dirname(File.dirname(this_dir)), 'pb')
48
+ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
193
49
 
194
- main
50
+ require 'test/server'