grpc 1.28.0-universal-darwin → 1.30.0.pre1-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.

@@ -14,11 +14,13 @@
14
14
  # limitations under the License.
15
15
 
16
16
  # Regenerates gRPC service stubs from proto files.
17
- set +e
17
+ set -e
18
18
  cd $(dirname $0)/../../..
19
19
 
20
- PROTOC=bins/opt/protobuf/protoc
21
- PLUGIN=protoc-gen-grpc=bins/opt/grpc_ruby_plugin
20
+ # protoc and grpc_*_plugin binaries can be obtained by running
21
+ # $ bazel build @com_google_protobuf//:protoc //src/compiler:all
22
+ PROTOC=bazel-bin/external/com_google_protobuf/protoc
23
+ PLUGIN=protoc-gen-grpc=bazel-bin/src/compiler/grpc_ruby_plugin
22
24
 
23
25
  $PROTOC -I src/proto src/proto/grpc/health/v1/health.proto \
24
26
  --grpc_out=src/ruby/pb \
@@ -34,6 +34,7 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
34
34
  optional :oauth_scope, :string, 3
35
35
  optional :server_id, :string, 4
36
36
  optional :grpclb_route_type, :enum, 5, "grpc.testing.GrpclbRouteType"
37
+ optional :hostname, :string, 6
37
38
  end
38
39
  add_message "grpc.testing.StreamingInputCallRequest" do
39
40
  optional :payload, :message, 1, "grpc.testing.Payload"
@@ -63,6 +64,14 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
63
64
  optional :passed, :bool, 1
64
65
  repeated :backoff_ms, :int32, 2
65
66
  end
67
+ add_message "grpc.testing.LoadBalancerStatsRequest" do
68
+ optional :num_rpcs, :int32, 1
69
+ optional :timeout_sec, :int32, 2
70
+ end
71
+ add_message "grpc.testing.LoadBalancerStatsResponse" do
72
+ map :rpcs_by_peer, :string, :int32, 1
73
+ optional :num_failures, :int32, 2
74
+ end
66
75
  add_enum "grpc.testing.PayloadType" do
67
76
  value :COMPRESSABLE, 0
68
77
  end
@@ -88,6 +97,8 @@ module Grpc
88
97
  StreamingOutputCallResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallResponse").msgclass
89
98
  ReconnectParams = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ReconnectParams").msgclass
90
99
  ReconnectInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ReconnectInfo").msgclass
100
+ LoadBalancerStatsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.LoadBalancerStatsRequest").msgclass
101
+ LoadBalancerStatsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.LoadBalancerStatsResponse").msgclass
91
102
  PayloadType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadType").enummodule
92
103
  GrpclbRouteType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.GrpclbRouteType").enummodule
93
104
  end
@@ -96,6 +96,22 @@ module Grpc
96
96
  rpc :Stop, Empty, ReconnectInfo
97
97
  end
98
98
 
99
+ Stub = Service.rpc_stub_class
100
+ end
101
+ module LoadBalancerStatsService
102
+ # A service used to obtain stats for verifying LB behavior.
103
+ class Service
104
+
105
+ include GRPC::GenericService
106
+
107
+ self.marshal_class_method = :encode
108
+ self.unmarshal_class_method = :decode
109
+ self.service_name = 'grpc.testing.LoadBalancerStatsService'
110
+
111
+ # Gets the backend distribution for RPCs sent by a test client.
112
+ rpc :GetClientStats, LoadBalancerStatsRequest, LoadBalancerStatsResponse
113
+ end
114
+
99
115
  Stub = Service.rpc_stub_class
100
116
  end
101
117
  end
@@ -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
@@ -0,0 +1,134 @@
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
+ TEST_DEBUG_MESSAGE = 'raised by test server'.freeze
18
+
19
+ # a test service that checks the cert of its peer
20
+ class DebugMessageTestService
21
+ include GRPC::GenericService
22
+ rpc :an_rpc_raises_abort, EchoMsg, EchoMsg
23
+ rpc :an_rpc_raises_standarderror, EchoMsg, EchoMsg
24
+
25
+ def an_rpc_raises_abort(_req, _call)
26
+ fail GRPC::Aborted.new(
27
+ 'aborted',
28
+ {},
29
+ TEST_DEBUG_MESSAGE)
30
+ end
31
+
32
+ def an_rpc_raises_standarderror(_req, _call)
33
+ fail(StandardError, TEST_DEBUG_MESSAGE)
34
+ end
35
+ end
36
+
37
+ DebugMessageTestServiceStub = DebugMessageTestService.rpc_stub_class
38
+
39
+ describe 'surfacing and transmitting of debug messages' do
40
+ RpcServer = GRPC::RpcServer
41
+
42
+ before(:all) do
43
+ server_opts = {
44
+ poll_period: 1
45
+ }
46
+ @srv = new_rpc_server_for_testing(**server_opts)
47
+ @port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
48
+ @srv.handle(DebugMessageTestService)
49
+ @srv_thd = Thread.new { @srv.run }
50
+ @srv.wait_till_running
51
+ end
52
+
53
+ after(:all) do
54
+ expect(@srv.stopped?).to be(false)
55
+ @srv.stop
56
+ @srv_thd.join
57
+ end
58
+
59
+ it 'debug error message is not present BadStatus exceptions that dont set it' do
60
+ exception_message = ''
61
+ begin
62
+ fail GRPC::Unavailable('unavailable', {})
63
+ rescue StandardError => e
64
+ p "Got exception: #{e.message}"
65
+ exception_message = e.message
66
+ end
67
+ expect(exception_message.empty?).to be(false)
68
+ expect(exception_message.include?('debug_error_string')).to be(false)
69
+ end
70
+
71
+ it 'debug error message is present in locally generated errors' do
72
+ # Create a secure channel. This is just one way to force a
73
+ # connection handshake error, which shoud result in C-core
74
+ # generating a status and error message and surfacing them up.
75
+ test_root = File.join(File.dirname(__FILE__), 'testdata')
76
+ files = ['ca.pem', 'client.key', 'client.pem']
77
+ creds = files.map { |f| File.open(File.join(test_root, f)).read }
78
+ creds = GRPC::Core::ChannelCredentials.new(creds[0], creds[1], creds[2])
79
+ stub = DebugMessageTestServiceStub.new(
80
+ "localhost:#{@port}", creds)
81
+ begin
82
+ stub.an_rpc_raises_abort(EchoMsg.new)
83
+ rescue StandardError => e
84
+ p "Got exception: #{e.message}"
85
+ exception_message = e.message
86
+ # check that the RPC did actually result in a BadStatus exception
87
+ expect(e.is_a?(GRPC::BadStatus)).to be(true)
88
+ end
89
+ # just check that the debug_error_string is non-empty (we know that
90
+ # it's a JSON object, so the first character is '{').
91
+ expect(exception_message.include?('. debug_error_string:{')).to be(true)
92
+ end
93
+
94
+ it 'debug message is not transmitted from server to client' do
95
+ # in order to not accidentally leak internal details about a
96
+ # server to untrusted clients, avoid including the debug_error_string
97
+ # field of a BadStatusException raised at a server in the
98
+ # RPC status that it sends to clients.
99
+ stub = DebugMessageTestServiceStub.new(
100
+ "localhost:#{@port}", :this_channel_is_insecure)
101
+ exception_message = ''
102
+ begin
103
+ stub.an_rpc_raises_abort(EchoMsg.new)
104
+ rescue StandardError => e
105
+ p "Got exception: #{e.message}"
106
+ exception_message = e.message
107
+ # check that the status was aborted is an indirect way to
108
+ # tell that the RPC did actually get handled by the server
109
+ expect(e.is_a?(GRPC::Aborted)).to be(true)
110
+ end
111
+ # just assert that the contents of the server-side BadStatus
112
+ # debug_error_string field were *not* propagated to the client.
113
+ expect(exception_message.include?('. debug_error_string:{')).to be(true)
114
+ expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(false)
115
+ end
116
+
117
+ it 'standard_error messages are transmitted from server to client' do
118
+ # this test exists mostly in order to understand the test case
119
+ # above, by comparison.
120
+ stub = DebugMessageTestServiceStub.new(
121
+ "localhost:#{@port}", :this_channel_is_insecure)
122
+ exception_message = ''
123
+ begin
124
+ stub.an_rpc_raises_standarderror(EchoMsg.new)
125
+ rescue StandardError => e
126
+ p "Got exception: #{e.message}"
127
+ exception_message = e.message
128
+ expect(e.is_a?(GRPC::BadStatus)).to be(true)
129
+ end
130
+ # assert that the contents of the StandardError exception message
131
+ # are propagated to the client.
132
+ expect(exception_message.include?(TEST_DEBUG_MESSAGE)).to be(true)
133
+ end
134
+ end
@@ -55,6 +55,8 @@ describe GenericService do
55
55
  expect(GenericService.underscore('AMethod')).to eq('a_method')
56
56
  expect(GenericService.underscore('PrintHTML')).to eq('print_html')
57
57
  expect(GenericService.underscore('SeeHTMLBooks')).to eq('see_html_books')
58
+
59
+ expect(GenericService.underscore('SeeHTMLBooks'.freeze)).to eq('see_html_books')
58
60
  end
59
61
  end
60
62
 
@@ -27,8 +27,13 @@ message AnotherTestResponse { }
27
27
 
28
28
  message Foo { }
29
29
 
30
+ message Bar {
31
+ message Baz { }
32
+ }
33
+
30
34
  service AnotherTestService {
31
35
  rpc GetTest(AnotherTestRequest) returns (AnotherTestResponse) { }
32
36
  rpc OtherTest(Thing) returns (Thing) { }
33
37
  rpc FooTest(Foo) returns (Foo) { }
38
+ rpc NestedMessageTest(Foo) returns (Bar.Baz) { }
34
39
  }
@@ -40,6 +40,8 @@ describe 'Code Generation Options' do
40
40
  expect(services[:OtherTest].output).to eq(A::Other::Thing)
41
41
  expect(services[:FooTest].input).to eq(RPC::Test::New::Package::Options::Foo)
42
42
  expect(services[:FooTest].output).to eq(RPC::Test::New::Package::Options::Foo)
43
+ expect(services[:NestedMessageTest].input).to eq(RPC::Test::New::Package::Options::Foo)
44
+ expect(services[:NestedMessageTest].output).to eq(RPC::Test::New::Package::Options::Bar::Baz)
43
45
  end
44
46
  end
45
47
  end