2019-09-11 10:22:29 -04:00
|
|
|
require_relative "helper"
|
|
|
|
require_relative "helpers/integration"
|
|
|
|
|
|
|
|
class TestIntegrationPumactl < TestIntegration
|
2020-07-12 13:00:29 -04:00
|
|
|
include TmpPath
|
2020-10-13 18:36:55 -04:00
|
|
|
parallelize_me! if ::Puma.mri?
|
2019-09-19 13:37:53 -04:00
|
|
|
|
2020-10-10 19:55:11 -04:00
|
|
|
def workers ; 2 ; end
|
|
|
|
|
2019-09-11 10:22:29 -04:00
|
|
|
def setup
|
|
|
|
super
|
|
|
|
|
2020-07-06 08:10:55 -04:00
|
|
|
@state_path = tmp_path('.state')
|
|
|
|
@control_path = tmp_path('.sock')
|
2019-09-11 10:22:29 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def teardown
|
|
|
|
super
|
|
|
|
|
2020-03-03 15:09:08 -05:00
|
|
|
refute File.exist?(@control_path), "Control path must be removed after stop"
|
|
|
|
ensure
|
2019-09-19 13:37:53 -04:00
|
|
|
[@state_path, @control_path].each { |p| File.unlink(p) rescue nil }
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_stop_tcp
|
2021-03-15 10:10:43 -04:00
|
|
|
skip_if :jruby, :truffleruby # Undiagnose thread race. TODO fix
|
2019-09-19 13:37:53 -04:00
|
|
|
@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
|
2019-09-11 10:22:29 -04:00
|
|
|
end
|
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
def test_stop_unix
|
2020-03-03 15:09:08 -05:00
|
|
|
ctl_unix
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_halt_unix
|
|
|
|
ctl_unix 'halt'
|
|
|
|
end
|
|
|
|
|
|
|
|
def ctl_unix(signal='stop')
|
2021-03-15 10:10:43 -04:00
|
|
|
skip_unless :unix
|
2020-05-19 14:32:02 -04:00
|
|
|
stderr = Tempfile.new(%w(stderr .log))
|
|
|
|
cli_server "-q test/rackup/sleep.ru --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}",
|
|
|
|
config: "stdout_redirect nil, '#{stderr.path}'",
|
|
|
|
unix: true
|
2019-09-11 10:22:29 -04:00
|
|
|
|
2020-03-03 15:09:08 -05:00
|
|
|
cli_pumactl signal, unix: true
|
2019-09-11 10:22:29 -04:00
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
_, status = Process.wait2(@pid)
|
2019-09-11 10:22:29 -04:00
|
|
|
assert_equal 0, status
|
2020-05-19 14:32:02 -04:00
|
|
|
refute_match 'error', File.read(stderr.path)
|
2019-09-11 10:22:29 -04:00
|
|
|
@server = nil
|
|
|
|
end
|
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
def test_phased_restart_cluster
|
2021-03-15 10:10:43 -04:00
|
|
|
skip_unless :fork
|
2020-10-10 19:55:11 -04:00
|
|
|
cli_server "-q -w #{workers} test/rackup/sleep.ru --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}", unix: true
|
2019-09-11 10:22:29 -04:00
|
|
|
|
2020-09-08 14:42:07 -04:00
|
|
|
start = Time.now
|
|
|
|
|
2019-09-11 10:22:29 -04:00
|
|
|
s = UNIXSocket.new @bind_path
|
|
|
|
@ios_to_close << s
|
2020-02-17 23:49:56 -05:00
|
|
|
s << "GET /sleep1 HTTP/1.0\r\n\r\n"
|
2019-09-11 10:22:29 -04:00
|
|
|
|
|
|
|
# Get the PIDs of the phase 0 workers.
|
|
|
|
phase0_worker_pids = get_worker_pids 0
|
2019-09-11 11:14:11 -04:00
|
|
|
assert File.exist? @bind_path
|
2019-09-11 10:22:29 -04:00
|
|
|
|
|
|
|
# Phased restart
|
2019-09-19 13:37:53 -04:00
|
|
|
cli_pumactl "phased-restart", unix: true
|
2019-09-11 10:22:29 -04:00
|
|
|
|
|
|
|
# Get the PIDs of the phase 1 workers.
|
|
|
|
phase1_worker_pids = get_worker_pids 1
|
|
|
|
|
|
|
|
msg = "phase 0 pids #{phase0_worker_pids.inspect} phase 1 pids #{phase1_worker_pids.inspect}"
|
|
|
|
|
2020-10-10 19:55:11 -04:00
|
|
|
assert_equal workers, phase0_worker_pids.length, msg
|
|
|
|
assert_equal workers, phase1_worker_pids.length, msg
|
2019-09-11 10:22:29 -04:00
|
|
|
assert_empty phase0_worker_pids & phase1_worker_pids, "#{msg}\nBoth workers should be replaced with new"
|
2019-09-11 11:14:11 -04:00
|
|
|
assert File.exist?(@bind_path), "Bind path must exist after phased restart"
|
2019-09-11 10:22:29 -04:00
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
cli_pumactl "stop", unix: true
|
2019-09-11 10:22:29 -04:00
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
_, status = Process.wait2(@pid)
|
2019-09-11 10:22:29 -04:00
|
|
|
assert_equal 0, status
|
2022-01-17 10:07:57 -05:00
|
|
|
assert_operator Time.now - start, :<, (DARWIN ? 8 : 6)
|
2019-09-11 10:22:29 -04:00
|
|
|
@server = nil
|
|
|
|
end
|
|
|
|
|
2020-07-27 08:02:11 -04:00
|
|
|
def test_prune_bundler_with_multiple_workers
|
2021-03-15 10:10:43 -04:00
|
|
|
skip_unless :fork
|
2020-07-27 08:02:11 -04:00
|
|
|
|
|
|
|
cli_server "-q -C test/config/prune_bundler_with_multiple_workers.rb --control-url unix://#{@control_path} --control-token #{TOKEN} -S #{@state_path}", unix: true
|
|
|
|
|
|
|
|
s = UNIXSocket.new @bind_path
|
|
|
|
@ios_to_close << s
|
|
|
|
s << "GET / HTTP/1.0\r\n\r\n"
|
|
|
|
|
|
|
|
body = s.read
|
|
|
|
|
|
|
|
assert_match "200 OK", body
|
|
|
|
assert_match "embedded app", body
|
|
|
|
|
|
|
|
cli_pumactl "stop", unix: true
|
|
|
|
|
2020-10-22 15:54:57 -04:00
|
|
|
_, _ = Process.wait2(@pid)
|
2020-07-27 08:02:11 -04:00
|
|
|
@server = nil
|
|
|
|
end
|
|
|
|
|
2019-09-19 13:37:53 -04:00
|
|
|
def test_kill_unknown
|
2021-03-15 10:10:43 -04:00
|
|
|
skip_if :jruby
|
2019-09-11 10:22:29 -04:00
|
|
|
|
|
|
|
# we run ls to get a 'safe' pid to pass off as puma in cli stop
|
|
|
|
# do not want to accidentally kill a valid other process
|
|
|
|
io = IO.popen(windows? ? "dir" : "ls")
|
|
|
|
safe_pid = io.pid
|
|
|
|
Process.wait safe_pid
|
|
|
|
|
|
|
|
sout = StringIO.new
|
|
|
|
|
|
|
|
e = assert_raises SystemExit do
|
|
|
|
Puma::ControlCLI.new(%W!-p #{safe_pid} stop!, sout).run
|
|
|
|
end
|
|
|
|
sout.rewind
|
|
|
|
# windows bad URI(is not URI?)
|
|
|
|
assert_match(/No pid '\d+' found|bad URI\(is not URI\?\)/, sout.readlines.join(""))
|
|
|
|
assert_equal(1, e.status)
|
|
|
|
end
|
|
|
|
end
|