diff --git a/Rakefile b/Rakefile index 12ac12710fb..cc02aa130ab 100755 --- a/Rakefile +++ b/Rakefile @@ -12,7 +12,8 @@ load 'tools/distrib/docker_for_windows.rb' # Add rubocop style checking tasks RuboCop::RakeTask.new(:rubocop) do |task| task.options = ['-c', 'src/ruby/.rubocop.yml'] - task.patterns = ['src/ruby/{lib,spec}/**/*.rb'] + # add end2end tests to formatter but don't add generated proto _pb.rb's + task.patterns = ['src/ruby/{lib,spec}/**/*.rb', 'src/ruby/end2end/*.rb'] end spec = Gem::Specification.load('grpc.gemspec') diff --git a/src/ruby/.rubocop.yml b/src/ruby/.rubocop.yml index 0f61ccfa812..7174f3b15af 100644 --- a/src/ruby/.rubocop.yml +++ b/src/ruby/.rubocop.yml @@ -9,6 +9,7 @@ AllCops: - 'bin/math_services_pb.rb' - 'pb/grpc/health/v1/*' - 'pb/test/**/*' + - 'end2end/lib/*' Metrics/CyclomaticComplexity: Max: 9 diff --git a/src/ruby/end2end/channel_closing_client.rb b/src/ruby/end2end/channel_closing_client.rb index a9df0784217..84497973607 100755 --- a/src/ruby/end2end/channel_closing_client.rb +++ b/src/ruby/end2end/channel_closing_client.rb @@ -31,10 +31,13 @@ require_relative './end2end_common' +# Calls '#close' on a Channel when "shutdown" called. This tries to +# trigger a hang or crash bug by closing a channel actively being watched class ChannelClosingClientController < ClientControl::ClientController::Service def initialize(ch) @ch = ch end + def shutdown(_, _) @ch.close ClientControl::Void.new @@ -53,7 +56,8 @@ def main end end.parse! - ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) + ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, + :this_channel_is_insecure) srv = GRPC::RpcServer.new thd = Thread.new do diff --git a/src/ruby/end2end/channel_closing_driver.rb b/src/ruby/end2end/channel_closing_driver.rb index 98c8eaa1cdf..43e2fe8cbbd 100755 --- a/src/ruby/end2end/channel_closing_driver.rb +++ b/src/ruby/end2end/channel_closing_driver.rb @@ -29,23 +29,24 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# make sure that the client doesn't hang when channel is closed explictly while it's used +# make sure that the client doesn't hang when channel is closed +# explictly while it's used require_relative './end2end_common' def main - STDERR.puts "start server" + STDERR.puts 'start server' server_runner = ServerRunner.new server_port = server_runner.run sleep 1 - STDERR.puts "start client" - control_stub, client_pid = start_client("channel_closing_client.rb", server_port) + STDERR.puts 'start client' + control_stub, client_pid = start_client('channel_closing_client.rb', + server_port) sleep 3 - begin Timeout.timeout(10) do control_stub.shutdown(ClientControl::Void.new) @@ -55,8 +56,9 @@ def main STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) - STDERR.puts "killed client child" - raise 'Timed out waiting for client process. It likely hangs when a channel is closed while connectivity is watched' + STDERR.puts 'killed client child' + raise 'Timed out waiting for client process. It likely hangs when a ' \ + 'channel is closed while connectivity is watched' end server_runner.stop diff --git a/src/ruby/end2end/channel_state_client.rb b/src/ruby/end2end/channel_state_client.rb index 476329ff73a..08c21bbb8e8 100755 --- a/src/ruby/end2end/channel_state_client.rb +++ b/src/ruby/end2end/channel_state_client.rb @@ -34,15 +34,16 @@ require_relative './end2end_common' def main server_port = '' OptionParser.new do |opts| - opts.on('--client_control_port=P', String) do |p| - STDERR.puts "client_control_port ignored" + opts.on('--client_control_port=P', String) do + STDERR.puts 'client_control_port ignored' end opts.on('--server_port=P', String) do |p| server_port = p end end.parse! - ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, :this_channel_is_insecure) + ch = GRPC::Core::Channel.new("localhost:#{server_port}", {}, + :this_channel_is_insecure) loop do state = ch.connectivity_state diff --git a/src/ruby/end2end/channel_state_driver.rb b/src/ruby/end2end/channel_state_driver.rb index 8ef32acfffe..c3184bf9392 100755 --- a/src/ruby/end2end/channel_state_driver.rb +++ b/src/ruby/end2end/channel_state_driver.rb @@ -34,14 +34,14 @@ require_relative './end2end_common' def main - STDERR.puts "start server" + STDERR.puts 'start server' server_runner = ServerRunner.new server_port = server_runner.run sleep 1 - STDERR.puts "start client" - _, client_pid = start_client("channel_state_client.rb", server_port) + STDERR.puts 'start client' + _, client_pid = start_client('channel_state_client.rb', server_port) sleep 3 @@ -53,8 +53,9 @@ def main STDERR.puts "timeout wait for client pid #{client_pid}" Process.kill('SIGKILL', client_pid) Process.wait(client_pid) - STDERR.puts "killed client child" - raise 'Timed out waiting for client process. It likely hangs when ended abruptly' + STDERR.puts 'killed client child' + raise 'Timed out waiting for client process. ' \ + 'It likely hangs when ended abruptly' end server_runner.stop diff --git a/src/ruby/end2end/end2end_common.rb b/src/ruby/end2end/end2end_common.rb index d98e41f6421..9534bb20787 100755 --- a/src/ruby/end2end/end2end_common.rb +++ b/src/ruby/end2end/end2end_common.rb @@ -43,6 +43,7 @@ require 'socket' require 'optparse' require 'thread' require 'timeout' +require 'English' # see https://github.com/bbatsov/rubocop/issues/1747 # GreeterServer is simple server that implements the Helloworld Greeter server. class EchoServerImpl < Echo::EchoServer::Service @@ -52,9 +53,11 @@ class EchoServerImpl < Echo::EchoServer::Service end end +# ServerRunner starts an "echo server" that test clients can make calls to class ServerRunner def initialize end + def run @srv = GRPC::RpcServer.new port = @srv.add_http2_port('0.0.0.0:0', :this_port_is_insecure) @@ -66,10 +69,11 @@ class ServerRunner @srv.wait_till_running port end + def stop @srv.stop @thd.join - raise "server not stopped" unless @srv.stopped? + fail 'server not stopped' unless @srv.stopped? end end @@ -81,22 +85,24 @@ def start_client(client_main, server_port) tmp_server.close client_path = File.join(this_dir, client_main) - client_pid = Process.spawn(RbConfig.ruby, client_path, - "--client_control_port=#{client_control_port}", - "--server_port=#{server_port}") + client_pid = Process.spawn(RbConfig.ruby, + client_path, + "--client_control_port=#{client_control_port}", + "--server_port=#{server_port}") sleep 1 - control_stub = ClientControl::ClientController::Stub.new("localhost:#{client_control_port}", :this_channel_is_insecure) - return control_stub, client_pid + control_stub = ClientControl::ClientController::Stub.new( + "localhost:#{client_control_port}", :this_channel_is_insecure) + [control_stub, client_pid] end def cleanup(control_stub, client_pid, server_runner) control_stub.shutdown(ClientControl::Void.new) Process.wait(client_pid) - client_exit_code = $?.exitstatus + client_exit_code = $CHILD_STATUS if client_exit_code != 0 - raise "term sig test failure: client exit code: #{client_exit_code}" + fail "term sig test failure: client exit code: #{client_exit_code}" end server_runner.stop diff --git a/src/ruby/end2end/sig_handling_client.rb b/src/ruby/end2end/sig_handling_client.rb index f0b2ba61caf..5b1e54718ec 100755 --- a/src/ruby/end2end/sig_handling_client.rb +++ b/src/ruby/end2end/sig_handling_client.rb @@ -31,20 +31,25 @@ require_relative './end2end_common' +# Test client. Sends RPC's as normal but process also has signal handlers class SigHandlingClientController < ClientControl::ClientController::Service def initialize(srv, stub) @srv = srv @stub = stub end + def do_echo_rpc(req, _) response = @stub.echo(Echo::EchoRequest.new(request: req.request)) - raise "bad response" unless response.response == req.request + fail 'bad response' unless response.response == req.request ClientControl::Void.new end + def shutdown(_, _) Thread.new do - #TODO(apolcyn) There is a race between stopping the server and the "shutdown" rpc completing, - # See if stop method on server can end active RPC cleanly, to avoid this sleep. + # TODO(apolcyn) There is a race between stopping the + # server and the "shutdown" rpc completing, + # See if stop method on server can end active RPC cleanly, to + # avoid this sleep. sleep 3 @srv.stop end @@ -64,17 +69,19 @@ def main end end.parse! - Signal.trap("TERM") do - STDERR.puts "SIGTERM received" + Signal.trap('TERM') do + STDERR.puts 'SIGTERM received' end - Signal.trap("INT") do - STDERR.puts "SIGINT received" + Signal.trap('INT') do + STDERR.puts 'SIGINT received' end srv = GRPC::RpcServer.new - srv.add_http2_port("0.0.0.0:#{client_control_port}", :this_port_is_insecure) - stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure) + srv.add_http2_port("0.0.0.0:#{client_control_port}", + :this_port_is_insecure) + stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", + :this_channel_is_insecure) srv.handle(SigHandlingClientController.new(srv, stub)) srv.run end diff --git a/src/ruby/end2end/sig_handling_driver.rb b/src/ruby/end2end/sig_handling_driver.rb index 4d205da9ae3..c5d46e074cb 100755 --- a/src/ruby/end2end/sig_handling_driver.rb +++ b/src/ruby/end2end/sig_handling_driver.rb @@ -35,20 +35,21 @@ require_relative './end2end_common' def main - STDERR.puts "start server" + STDERR.puts 'start server' server_runner = ServerRunner.new server_port = server_runner.run sleep 1 - STDERR.puts "start client" - control_stub, client_pid = start_client("sig_handling_client.rb", server_port) + STDERR.puts 'start client' + control_stub, client_pid = start_client('sig_handling_client.rb', server_port) sleep 1 count = 0 while count < 5 - control_stub.do_echo_rpc(ClientControl::DoEchoRpcRequest.new(request: 'hello')) + control_stub.do_echo_rpc( + ClientControl::DoEchoRpcRequest.new(request: 'hello')) Process.kill('SIGTERM', client_pid) Process.kill('SIGINT', client_pid) count += 1