Skip to content

Commit

Permalink
Misc updates, debug output, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
MSP-Greg committed Sep 17, 2019
1 parent 84f8504 commit fe6ddcd
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 61 deletions.
18 changes: 18 additions & 0 deletions test/helper.rb
Expand Up @@ -21,6 +21,9 @@
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
Thread.abort_on_exception = true

$debugging_info = ''.dup
$debugging_hold = false # needed for TestCLI#test_control_clustered

require "puma"
require "puma/events"
require "puma/detect"
Expand Down Expand Up @@ -132,4 +135,19 @@ def self.run(reporter, options = {}) # :nodoc:
prove_it!
super
end

def full_name
"#{self.class.name}##{name}"
end
end

Minitest.after_run do
# needed for TestCLI#test_control_clustered
unless $debugging_hold
out = $debugging_info.strip
unless out.empty?
puts "", " Debugging Info".rjust(75, '-'),
out, '-' * 75, ""
end
end
end
31 changes: 15 additions & 16 deletions test/helpers/integration.rb
Expand Up @@ -20,24 +20,21 @@ def setup

def teardown
if defined?(@server) && @server
begin
Process.kill "INT", @server.pid
rescue
Errno::ESRCH
end
begin
Process.wait @server.pid
rescue Errno::ECHILD
end
@server.close unless @server.closed?
@server = nil
stop_server @pid, signal: :INT
end

@ios_to_close.each do |io|
io.close if io.is_a?(IO) && !io.closed?
io = nil
end
refute File.exist?(@bind_path), "Bind path must be removed after stop"
File.unlink(@bind_path) rescue nil

# wait until the end for OS buffering?
if defined?(@server) && @server
@server.close unless @server.closed?
@server = nil
end
end

private
Expand All @@ -56,25 +53,27 @@ def cli_server(argv, unix: false)
end

def stop_server(pid = @pid, signal: :TERM)
Process.kill signal, pid
sleep 1
begin
Process.kill signal, pid
rescue Errno::ESRCH
end
begin
Process.wait2 pid
rescue Errno::ECHILD
end
end

def restart_server_and_listen(argv)
cli_server(argv)
cli_server argv
connection = connect
initial_reply = read_body(connection)
restart_server(connection)
restart_server connection
[initial_reply, read_body(connect)]
end

# reuses an existing connection to make sure that works
def restart_server(connection)
Process.kill :USR2, @server.pid
Process.kill :USR2, @pid
connection.write "GET / HTTP/1.1\r\n\r\n" # trigger it to start by sending a new request
wait_for_server_to_boot
end
Expand Down
37 changes: 29 additions & 8 deletions test/test_cli.rb
Expand Up @@ -81,13 +81,17 @@ def test_control_clustered
"--control-token", "",
"test/rackup/lobster.ru"], @events

# without this, Minitest.after_run will trigger on this test ?
$debugging_hold = true

t = Thread.new { cli.run }

wait_booted

s = UNIXSocket.new @tmp_path
s << "GET /stats HTTP/1.0\r\n\r\n"
body = s.read
s.close

require 'json'
status = JSON.parse(body.split("\n").last)
Expand All @@ -99,10 +103,23 @@ def test_control_clustered
s = UNIXSocket.new @tmp_path
s << "GET /stats HTTP/1.0\r\n\r\n"
body = s.read
assert_match(/\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "workers": 2, "phase": 0, "booted_workers": 2, "old_workers": 0, "worker_status": \[\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "pid": \d+, "index": 0, "phase": 0, "booted": true, "last_checkin": "[^"]+", "last_status": \{ "backlog":0, "running":2, "pool_capacity":2, "max_threads": 2 \} \},\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "pid": \d+, "index": 1, "phase": 0, "booted": true, "last_checkin": "[^"]+", "last_status": \{ "backlog":0, "running":2, "pool_capacity":2, "max_threads": 2 \} \}\] \}/, body.split("\r\n").last)
s.close

cli.launcher.stop
t.join
assert_match(/\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "workers": 2, "phase": 0, "booted_workers": 2, "old_workers": 0, "worker_status": \[\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "pid": \d+, "index": 0, "phase": 0, "booted": true, "last_checkin": "[^"]+", "last_status": \{ "backlog":0, "running":2, "pool_capacity":2, "max_threads": 2 \} \},\{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "pid": \d+, "index": 1, "phase": 0, "booted": true, "last_checkin": "[^"]+", "last_status": \{ "backlog":0, "running":2, "pool_capacity":2, "max_threads": 2 \} \}\] \}/, body.split("\r\n").last)
ensure
if UNIX_SKT_EXIST && HAS_FORK
cli.launcher.stop

done = nil
until done
@events.stdout.rewind
log = @events.stdout.readlines.join ''
done = log[/ - Goodbye!/]
end

t.join
$debugging_hold = false
end
end

def test_control
Expand All @@ -121,11 +138,14 @@ def test_control
s = UNIXSocket.new @tmp_path
s << "GET /stats HTTP/1.0\r\n\r\n"
body = s.read
s.close

assert_match(/{ "started_at": "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", "backlog": 0, "running": 0, "pool_capacity": 16, "max_threads": 16 }/, body.split("\r\n").last)

cli.launcher.stop
t.join
ensure
if UNIX_SKT_EXIST
cli.launcher.stop
t.join
end
end

def test_control_stop
Expand All @@ -144,10 +164,11 @@ def test_control_stop
s = UNIXSocket.new @tmp_path
s << "GET /stop HTTP/1.0\r\n\r\n"
body = s.read
s.close

assert_equal '{ "status": "ok" }', body.split("\r\n").last

t.join
ensure
t.join if UNIX_SKT_EXIST
end

def control_gc_stats(uri, cntl)
Expand Down
34 changes: 17 additions & 17 deletions test/test_integration_cluster.rb
Expand Up @@ -2,23 +2,28 @@
require_relative "helpers/integration"

class TestIntegrationCluster < TestIntegration
parallelize_me!

DARWIN = !!RUBY_PLATFORM[/darwin/]

def setup
skip NO_FORK_MSG unless HAS_FORK
super
end

skip NO_FORK_MSG unless HAS_FORK
def teardown
super if HAS_FORK
end

def test_siginfo_thread_print
skip_unless_signal_exist? :INFO

cli_server("-w #{WORKERS} -q test/rackup/hello.ru")
cli_server "-w #{WORKERS} -q test/rackup/hello.ru"
worker_pids = get_worker_pids
output = []
t = Thread.new { output << @server.readlines }
Process.kill(:INFO, worker_pids.first)
Process.kill(:INT, @server.pid)
Process.kill :INFO, worker_pids.first
Process.kill :INT , @pid
t.join

assert_match "Thread TID", output.join
Expand Down Expand Up @@ -65,31 +70,24 @@ def test_term_exit_code
end

def test_term_suppress
cli_server("-w #{WORKERS} -C test/config/suppress_exception.rb test/rackup/hello.ru")
cli_server "-w #{WORKERS} -C test/config/suppress_exception.rb test/rackup/hello.ru"

Process.kill(:TERM, @server.pid)
begin
Process.wait @server.pid
rescue Errno::ECHILD
end
status = $?.exitstatus
_, status = stop_server

assert_equal 0, status
@server.close unless @server.closed?
@server = nil # prevent `#teardown` from killing already killed server
end

def test_term_worker_clean_exit
skip "Intermittent failure on Ruby 2.2" if RUBY_VERSION < '2.3'

pid = cli_server("-w #{WORKERS} test/rackup/hello.ru").pid
cli_server "-w #{WORKERS} test/rackup/hello.ru"

# Get the PIDs of the child workers.
worker_pids = get_worker_pids

# Signal the workers to terminate, and wait for them to die.
Process.kill :TERM, pid
Process.wait pid
Process.kill :TERM, @pid
Process.wait @pid

zombies = bad_exit_pids worker_pids

Expand Down Expand Up @@ -151,6 +149,8 @@ def term_closes_listeners(unix: false)
refused = replies.count { |r| r == :refused }
msg = "#{responses} responses, #{resets} resets, #{refused} refused"

$debugging_info << "#{full_name}\n #{msg}\n"

assert_operator 9, :<=, responses, msg

assert_operator 10, :>=, resets , msg
Expand All @@ -168,6 +168,7 @@ def usr1_all_respond(unix: false)

s = connect "sleep1", unix: unix
replies << read_body(s)

Process.kill :USR1, @pid

refused = thread_run_refused unix: unix
Expand Down Expand Up @@ -243,7 +244,6 @@ def worker_respawn(phase = 1, size = WORKERS)
assert_empty phase0_exited, msg

threads.each { |th| Thread.kill th }
stop_server signal: :KILL
end

# Returns an array of pids still in the process table, so it should
Expand Down
34 changes: 22 additions & 12 deletions test/test_integration_pumactl.rb
Expand Up @@ -2,6 +2,8 @@
require_relative "helpers/integration"

class TestIntegrationPumactl < TestIntegration
parallelize_me!

def setup
super

Expand All @@ -12,26 +14,34 @@ def setup
def teardown
super

begin
# refute File.exist?(@bind_path), "Bind path must be removed after stop"
ensure
[@state_path, @control_path].each { |p| File.unlink(p) rescue nil }
end
[@state_path, @control_path].each { |p| File.unlink(p) rescue nil }
end

def test_stop_tcp
@control_tcp_port = UniquePort.call
cli_server "-q test/rackup/sleep.ru --control-url tcp://#{HOST}:#{@control_tcp_port} --control-token #{TOKEN} -S #{@state_path}"

cli_pumactl "stop"

_, status = Process.wait2(@pid)
assert_equal 0, status

@server = nil
end

def test_pumactl_stop
def test_stop_unix
skip UNIX_SKT_MSG unless UNIX_SKT_EXIST
cli_server "-q test/rackup/sleep.ru --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}"
cli_server "-q test/rackup/sleep.ru --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}", unix: true

cli_pumactl "stop", unix: true

_, status = Process.wait2(@server.pid)
_, status = Process.wait2(@pid)
assert_equal 0, status

@server = nil
end

def test_pumactl_phased_restart_cluster
def test_phased_restart_cluster
skip NO_FORK_MSG unless HAS_FORK

cli_server "-q -w #{WORKERS} test/rackup/sleep.ru --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}", unix: true
Expand Down Expand Up @@ -59,13 +69,13 @@ def test_pumactl_phased_restart_cluster

cli_pumactl "stop", unix: true

_, status = Process.wait2(@server.pid)
_, status = Process.wait2(@pid)
assert_equal 0, status

@server = nil
end

def test_pumactl_kill_unknown
def test_kill_unknown
skip_on :jruby

# we run ls to get a 'safe' pid to pass off as puma in cli stop
Expand All @@ -91,7 +101,7 @@ def cli_pumactl(argv, unix: false)
if unix
pumactl = IO.popen("#{BASE} bin/pumactl -C unix://#{@control_path} -T #{TOKEN} #{argv}", "r")
else
pumactl = IO.popen("#{BASE} bin/pumactl #{argv}", "r")
pumactl = IO.popen("#{BASE} bin/pumactl -C tcp://#{HOST}:#{@control_tcp_port} -T #{TOKEN} #{argv}", "r")
end
@ios_to_close << pumactl
Process.wait pumactl.pid
Expand Down

0 comments on commit fe6ddcd

Please sign in to comment.