grpc 1.30.2-universal-darwin

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.bundle +0 -0
  45. data/src/ruby/lib/grpc/2.4/grpc_c.bundle +0 -0
  46. data/src/ruby/lib/grpc/2.5/grpc_c.bundle +0 -0
  47. data/src/ruby/lib/grpc/2.6/grpc_c.bundle +0 -0
  48. data/src/ruby/lib/grpc/2.7/grpc_c.bundle +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,252 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2015 gRPC authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # interop_server is a Testing app that runs a gRPC interop testing server.
18
+ #
19
+ # It helps validate interoperation b/w gRPC in different environments
20
+ #
21
+ # Helps validate interoperation b/w different gRPC implementations.
22
+ #
23
+ # Usage: $ path/to/interop_server.rb --port
24
+
25
+ this_dir = File.expand_path(File.dirname(__FILE__))
26
+ lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
27
+ pb_dir = File.dirname(this_dir)
28
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
29
+ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
30
+ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
31
+
32
+ require 'forwardable'
33
+ require 'logger'
34
+ require 'optparse'
35
+
36
+ require 'grpc'
37
+
38
+ require_relative '../src/proto/grpc/testing/empty_pb'
39
+ require_relative '../src/proto/grpc/testing/messages_pb'
40
+ require_relative '../src/proto/grpc/testing/test_services_pb'
41
+
42
+ # DebugIsTruncated extends the default Logger to truncate debug messages
43
+ class DebugIsTruncated < Logger
44
+ def debug(s)
45
+ super(truncate(s, 1024))
46
+ end
47
+
48
+ # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
49
+ #
50
+ # 'Once upon a time in a world far far away'.truncate(27)
51
+ # # => "Once upon a time in a wo..."
52
+ #
53
+ # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
54
+ #
55
+ # 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
56
+ # # => "Once upon a time in a..."
57
+ #
58
+ # 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
59
+ # # => "Once upon a time in a..."
60
+ #
61
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
62
+ # for a total length not exceeding <tt>length</tt>:
63
+ #
64
+ # 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
65
+ # # => "And they f... (continued)"
66
+ def truncate(s, truncate_at, options = {})
67
+ return s unless s.length > truncate_at
68
+ omission = options[:omission] || '...'
69
+ with_extra_room = truncate_at - omission.length
70
+ stop = \
71
+ if options[:separator]
72
+ rindex(options[:separator], with_extra_room) || with_extra_room
73
+ else
74
+ with_extra_room
75
+ end
76
+ "#{s[0, stop]}#{omission}"
77
+ end
78
+ end
79
+
80
+ # RubyLogger defines a logger for gRPC based on the standard ruby logger.
81
+ module RubyLogger
82
+ def logger
83
+ LOGGER
84
+ end
85
+
86
+ LOGGER = DebugIsTruncated.new(STDOUT)
87
+ LOGGER.level = Logger::WARN
88
+ end
89
+
90
+ # GRPC is the general RPC module
91
+ module GRPC
92
+ # Inject the noop #logger if no module-level logger method has been injected.
93
+ extend RubyLogger
94
+ end
95
+
96
+ # loads the certificates by the test server.
97
+ def load_test_certs
98
+ this_dir = File.expand_path(File.dirname(__FILE__))
99
+ data_dir = File.join(File.dirname(File.dirname(this_dir)), 'spec/testdata')
100
+ files = ['ca.pem', 'server1.key', 'server1.pem']
101
+ files.map { |f| File.open(File.join(data_dir, f)).read }
102
+ end
103
+
104
+ # creates a ServerCredentials from the test certificates.
105
+ def test_server_creds
106
+ certs = load_test_certs
107
+ GRPC::Core::ServerCredentials.new(
108
+ nil, [{private_key: certs[1], cert_chain: certs[2]}], false)
109
+ end
110
+
111
+ # produces a string of null chars (\0) of length l.
112
+ def nulls(l)
113
+ fail 'requires #{l} to be +ve' if l < 0
114
+ [].pack('x' * l).force_encoding('ascii-8bit')
115
+ end
116
+
117
+ def maybe_echo_metadata(_call)
118
+
119
+ # these are consistent for all interop tests
120
+ initial_metadata_key = "x-grpc-test-echo-initial"
121
+ trailing_metadata_key = "x-grpc-test-echo-trailing-bin"
122
+
123
+ if _call.metadata.has_key?(initial_metadata_key)
124
+ _call.metadata_to_send[initial_metadata_key] = _call.metadata[initial_metadata_key]
125
+ end
126
+ if _call.metadata.has_key?(trailing_metadata_key)
127
+ _call.output_metadata[trailing_metadata_key] = _call.metadata[trailing_metadata_key]
128
+ end
129
+ end
130
+
131
+ def maybe_echo_status_and_message(req)
132
+ unless req.response_status.nil?
133
+ fail GRPC::BadStatus.new_status_exception(
134
+ req.response_status.code, req.response_status.message)
135
+ end
136
+ end
137
+
138
+ # A FullDuplexEnumerator passes requests to a block and yields generated responses
139
+ class FullDuplexEnumerator
140
+ include Grpc::Testing
141
+ include Grpc::Testing::PayloadType
142
+
143
+ def initialize(requests)
144
+ @requests = requests
145
+ end
146
+ def each_item
147
+ return enum_for(:each_item) unless block_given?
148
+ GRPC.logger.info('interop-server: started receiving')
149
+ begin
150
+ cls = StreamingOutputCallResponse
151
+ @requests.each do |req|
152
+ maybe_echo_status_and_message(req)
153
+ req.response_parameters.each do |params|
154
+ resp_size = params.size
155
+ GRPC.logger.info("read a req, response size is #{resp_size}")
156
+ yield cls.new(payload: Payload.new(type: req.response_type,
157
+ body: nulls(resp_size)))
158
+ end
159
+ end
160
+ GRPC.logger.info('interop-server: finished receiving')
161
+ rescue StandardError => e
162
+ GRPC.logger.info('interop-server: failed')
163
+ GRPC.logger.warn(e)
164
+ fail e
165
+ end
166
+ end
167
+ end
168
+
169
+ # A runnable implementation of the schema-specified testing service, with each
170
+ # service method implemented as required by the interop testing spec.
171
+ class TestTarget < Grpc::Testing::TestService::Service
172
+ include Grpc::Testing
173
+ include Grpc::Testing::PayloadType
174
+
175
+ def empty_call(_empty, _call)
176
+ Empty.new
177
+ end
178
+
179
+ def unary_call(simple_req, _call)
180
+ maybe_echo_metadata(_call)
181
+ maybe_echo_status_and_message(simple_req)
182
+ req_size = simple_req.response_size
183
+ SimpleResponse.new(payload: Payload.new(type: :COMPRESSABLE,
184
+ body: nulls(req_size)))
185
+ end
186
+
187
+ def streaming_input_call(call)
188
+ sizes = call.each_remote_read.map { |x| x.payload.body.length }
189
+ sum = sizes.inject(0) { |s, x| s + x }
190
+ StreamingInputCallResponse.new(aggregated_payload_size: sum)
191
+ end
192
+
193
+ def streaming_output_call(req, _call)
194
+ cls = StreamingOutputCallResponse
195
+ req.response_parameters.map do |p|
196
+ cls.new(payload: Payload.new(type: req.response_type,
197
+ body: nulls(p.size)))
198
+ end
199
+ end
200
+
201
+ def full_duplex_call(reqs, _call)
202
+ maybe_echo_metadata(_call)
203
+ # reqs is a lazy Enumerator of the requests sent by the client.
204
+ FullDuplexEnumerator.new(reqs).each_item
205
+ end
206
+
207
+ def half_duplex_call(reqs)
208
+ # TODO: update with unique behaviour of the half_duplex_call if that's
209
+ # ever required by any of the tests.
210
+ full_duplex_call(reqs)
211
+ end
212
+ end
213
+
214
+ # validates the command line options, returning them as a Hash.
215
+ def parse_options
216
+ options = {
217
+ 'port' => nil,
218
+ 'secure' => false
219
+ }
220
+ OptionParser.new do |opts|
221
+ opts.banner = 'Usage: --port port'
222
+ opts.on('--port PORT', 'server port') do |v|
223
+ options['port'] = v
224
+ end
225
+ opts.on('--use_tls USE_TLS', ['false', 'true'],
226
+ 'require a secure connection?') do |v|
227
+ options['secure'] = v == 'true'
228
+ end
229
+ end.parse!
230
+
231
+ if options['port'].nil?
232
+ fail(OptionParser::MissingArgument, 'please specify --port')
233
+ end
234
+ options
235
+ end
236
+
237
+ def main
238
+ opts = parse_options
239
+ host = "0.0.0.0:#{opts['port']}"
240
+ s = GRPC::RpcServer.new
241
+ if opts['secure']
242
+ s.add_http2_port(host, test_server_creds)
243
+ GRPC.logger.info("... running securely on #{host}")
244
+ else
245
+ s.add_http2_port(host, :this_port_is_insecure)
246
+ GRPC.logger.info("... running insecurely on #{host}")
247
+ end
248
+ s.handle(TestTarget)
249
+ s.run_till_terminated
250
+ end
251
+
252
+ main
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2015 gRPC authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # This is the xDS interop test Ruby client. This is meant to be run by
18
+ # the run_xds_tests.py test runner.
19
+ #
20
+ # Usage: $ tools/run_tests/run_xds_tests.py --test_case=... ...
21
+ # --client_cmd="path/to/xds_client.rb --server=<hostname> \
22
+ # --stats_port=<port> \
23
+ # --qps=<qps>"
24
+
25
+ # These lines are required for the generated files to load grpc
26
+ this_dir = File.expand_path(File.dirname(__FILE__))
27
+ lib_dir = File.join(File.dirname(File.dirname(this_dir)), 'lib')
28
+ pb_dir = File.dirname(this_dir)
29
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
30
+ $LOAD_PATH.unshift(pb_dir) unless $LOAD_PATH.include?(pb_dir)
31
+
32
+ require 'optparse'
33
+ require 'logger'
34
+
35
+ require_relative '../../lib/grpc'
36
+ require 'google/protobuf'
37
+
38
+ require_relative '../src/proto/grpc/testing/empty_pb'
39
+ require_relative '../src/proto/grpc/testing/messages_pb'
40
+ require_relative '../src/proto/grpc/testing/test_services_pb'
41
+
42
+ # Some global variables to be shared by server and client
43
+ $watchers = Array.new
44
+ $watchers_mutex = Mutex.new
45
+ $watchers_cv = ConditionVariable.new
46
+ $shutdown = false
47
+
48
+ # RubyLogger defines a logger for gRPC based on the standard ruby logger.
49
+ module RubyLogger
50
+ def logger
51
+ LOGGER
52
+ end
53
+
54
+ LOGGER = Logger.new(STDOUT)
55
+ LOGGER.level = Logger::INFO
56
+ end
57
+
58
+ # GRPC is the general RPC module
59
+ module GRPC
60
+ # Inject the noop #logger if no module-level logger method has been injected.
61
+ extend RubyLogger
62
+ end
63
+
64
+ # creates a test stub
65
+ def create_stub(opts)
66
+ address = "#{opts.server}"
67
+ GRPC.logger.info("... connecting insecurely to #{address}")
68
+ Grpc::Testing::TestService::Stub.new(
69
+ address,
70
+ :this_channel_is_insecure,
71
+ )
72
+ end
73
+
74
+ # This implements LoadBalancerStatsService required by the test runner
75
+ class TestTarget < Grpc::Testing::LoadBalancerStatsService::Service
76
+ include Grpc::Testing
77
+
78
+ def get_client_stats(req, _call)
79
+ finish_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) +
80
+ req['timeout_sec']
81
+ watcher = {}
82
+ $watchers_mutex.synchronize do
83
+ watcher = {
84
+ "rpcs_by_peer" => Hash.new(0),
85
+ "rpcs_needed" => req['num_rpcs'],
86
+ "no_remote_peer" => 0
87
+ }
88
+ $watchers << watcher
89
+ seconds_remaining = finish_time -
90
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
91
+ while watcher['rpcs_needed'] > 0 && seconds_remaining > 0
92
+ $watchers_cv.wait($watchers_mutex, seconds_remaining)
93
+ seconds_remaining = finish_time -
94
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
95
+ end
96
+ $watchers.delete_at($watchers.index(watcher))
97
+ end
98
+ LoadBalancerStatsResponse.new(
99
+ rpcs_by_peer: watcher['rpcs_by_peer'],
100
+ num_failures: watcher['no_remote_peer'] + watcher['rpcs_needed']
101
+ );
102
+ end
103
+ end
104
+
105
+ # send 1 rpc every 1/qps second
106
+ def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs)
107
+ include Grpc::Testing
108
+ req = SimpleRequest.new()
109
+ target_next_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
110
+ while !$shutdown
111
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
112
+ sleep_seconds = target_next_start - now
113
+ if sleep_seconds < 0
114
+ target_next_start = now + target_seconds_between_rpcs
115
+ GRPC.logger.info(
116
+ "ruby xds: warning, rpc takes too long to finish. " \
117
+ "Deficit = %.1fms. " \
118
+ "If you consistently see this, the qps is too high." \
119
+ % [(sleep_seconds * 1000).abs().round(1)])
120
+ else
121
+ target_next_start += target_seconds_between_rpcs
122
+ sleep(sleep_seconds)
123
+ end
124
+ begin
125
+ deadline = GRPC::Core::TimeConsts::from_relative_time(30) # 30 seconds
126
+ resp = stub.unary_call(req, deadline: deadline)
127
+ remote_peer = resp.hostname
128
+ rescue GRPC::BadStatus => e
129
+ remote_peer = ""
130
+ GRPC.logger.info("ruby xds: rpc failed:|#{e.message}|, " \
131
+ "this may or may not be expected")
132
+ if fail_on_failed_rpcs
133
+ raise e
134
+ end
135
+ end
136
+ $watchers_mutex.synchronize do
137
+ $watchers.each do |watcher|
138
+ watcher['rpcs_needed'] -= 1
139
+ if remote_peer.strip.empty?
140
+ watcher['no_remote_peer'] += 1
141
+ else
142
+ watcher['rpcs_by_peer'][remote_peer] += 1
143
+ end
144
+ end
145
+ $watchers_cv.broadcast
146
+ end
147
+ end
148
+ end
149
+
150
+ # Args is used to hold the command line info.
151
+ Args = Struct.new(:fail_on_failed_rpcs, :num_channels,
152
+ :server, :stats_port, :qps)
153
+
154
+ # validates the command line options, returning them as a Hash.
155
+ def parse_args
156
+ args = Args.new
157
+ args['fail_on_failed_rpcs'] = false
158
+ args['num_channels'] = 1
159
+ OptionParser.new do |opts|
160
+ opts.on('--fail_on_failed_rpcs BOOL', ['false', 'true']) do |v|
161
+ args['fail_on_failed_rpcs'] = v == 'true'
162
+ end
163
+ opts.on('--num_channels CHANNELS', 'number of channels') do |v|
164
+ args['num_channels'] = v.to_i
165
+ end
166
+ opts.on('--server SERVER_HOST', 'server hostname') do |v|
167
+ GRPC.logger.info("ruby xds: server address is #{v}")
168
+ args['server'] = v
169
+ end
170
+ opts.on('--stats_port STATS_PORT', 'stats port') do |v|
171
+ GRPC.logger.info("ruby xds: stats port is #{v}")
172
+ args['stats_port'] = v
173
+ end
174
+ opts.on('--qps QPS', 'qps') do |v|
175
+ GRPC.logger.info("ruby xds: qps is #{v}")
176
+ args['qps'] = v
177
+ end
178
+ end.parse!
179
+ args
180
+ end
181
+
182
+ def main
183
+ opts = parse_args
184
+
185
+ # This server hosts the LoadBalancerStatsService
186
+ host = "0.0.0.0:#{opts['stats_port']}"
187
+ s = GRPC::RpcServer.new
188
+ s.add_http2_port(host, :this_port_is_insecure)
189
+ s.handle(TestTarget)
190
+ server_thread = Thread.new {
191
+ # run the server until the main test runner terminates this process
192
+ s.run_till_terminated_or_interrupted(['TERM'])
193
+ }
194
+
195
+ # The client just sends unary rpcs continuously in a regular interval
196
+ stub = create_stub(opts)
197
+ target_seconds_between_rpcs = (1.0 / opts['qps'].to_f)
198
+ client_threads = Array.new
199
+ opts['num_channels'].times {
200
+ client_threads << Thread.new {
201
+ run_test_loop(stub, target_seconds_between_rpcs,
202
+ opts['fail_on_failed_rpcs'])
203
+ }
204
+ }
205
+
206
+ server_thread.join
207
+ $shutdown = true
208
+ client_threads.each { |thd| thd.join }
209
+ end
210
+
211
+ if __FILE__ == $0
212
+ main
213
+ end