diff --git a/test/helper.rb b/test/helper.rb index 8ada8f5a..74cccc47 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -16,6 +16,7 @@ require "timeout" require "minitest/autorun" require "minitest/pride" require "minitest/proveit" +require_relative "helpers/apps" $LOAD_PATH << File.expand_path("../../lib", __FILE__) Thread.abort_on_exception = true @@ -43,10 +44,10 @@ end module UniquePort @port = 3211 + @mutex = Mutex.new def self.call - @port += 1 - @port + @mutex.synchronize { @port += 1 } end end @@ -69,8 +70,6 @@ end module TestSkips - @@next_port = 9000 - # usage: skip NO_FORK_MSG unless HAS_FORK # windows >= 2.6 fork is not defined, < 2.6 fork raises NotImplementedError HAS_FORK = ::Process.respond_to? :fork @@ -115,10 +114,6 @@ module TestSkips end skip skip_msg, bt if skip_msg end - - def next_port(incr = 1) - @@next_port += incr - end end Minitest::Test.include TestSkips diff --git a/test/helpers/apps.rb b/test/helpers/apps.rb new file mode 100644 index 00000000..f74e3eb0 --- /dev/null +++ b/test/helpers/apps.rb @@ -0,0 +1,12 @@ +module TestApps + + # call with "GET /sleep HTTP/1.1\r\n\r\n", where is the number of + # seconds to sleep + # same as rackup/sleep.ru + SLEEP = -> (env) do + dly = (env['REQUEST_PATH'][/\/sleep(\d+)/,1] || '0').to_i + sleep dly + [200, {"Content-Type" => "text/plain"}, ["Slept #{dly}"]] + end + +end diff --git a/test/rackup/10seconds.ru b/test/rackup/10seconds.ru deleted file mode 100644 index 0efa2a87..00000000 --- a/test/rackup/10seconds.ru +++ /dev/null @@ -1,4 +0,0 @@ -run lambda { |env| - sleep 10 - [200, {}, ["Hello World"]] -} diff --git a/test/rackup/1second.ru b/test/rackup/1second.ru deleted file mode 100644 index b86baa89..00000000 --- a/test/rackup/1second.ru +++ /dev/null @@ -1,4 +0,0 @@ -run lambda { |env| - sleep 1 - [200, {}, ["Hello World"]] -} diff --git a/test/rackup/hello-delay.ru b/test/rackup/hello-delay.ru deleted file mode 100644 index 65f202f3..00000000 --- a/test/rackup/hello-delay.ru +++ /dev/null @@ -1,3 +0,0 @@ -sleep 10 - -run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] } diff --git a/test/rackup/hello-map.ru b/test/rackup/hello-map.ru deleted file mode 100644 index 11401d48..00000000 --- a/test/rackup/hello-map.ru +++ /dev/null @@ -1,3 +0,0 @@ -map "/foo" do - run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello World"]] } -end diff --git a/test/rackup/hello-post.ru b/test/rackup/hello-post.ru deleted file mode 100644 index ff0e1a0a..00000000 --- a/test/rackup/hello-post.ru +++ /dev/null @@ -1,4 +0,0 @@ -run lambda { |env| - p :body => env['rack.input'].read - [200, {"Content-Type" => "text/plain"}, ["Hello World"]] -} diff --git a/test/rackup/hello-stuck-ci.ru b/test/rackup/hello-stuck-ci.ru deleted file mode 100644 index 1681c5ce..00000000 --- a/test/rackup/hello-stuck-ci.ru +++ /dev/null @@ -1 +0,0 @@ -run lambda { |env| sleep 10; [200, {"Content-Type" => "text/plain"}, ["Hello World"]] } diff --git a/test/rackup/hello-stuck.ru b/test/rackup/hello-stuck.ru deleted file mode 100644 index 01096c2f..00000000 --- a/test/rackup/hello-stuck.ru +++ /dev/null @@ -1 +0,0 @@ -run lambda { |env| sleep 60; [200, {"Content-Type" => "text/plain"}, ["Hello World"]] } diff --git a/test/rackup/hello-tcp.ru b/test/rackup/hello-tcp.ru deleted file mode 100644 index 7010e6a3..00000000 --- a/test/rackup/hello-tcp.ru +++ /dev/null @@ -1,5 +0,0 @@ -run lambda { |env, socket| - p :here - socket.puts "Sockets for the low, low price of free!" - socket.close -} diff --git a/test/rackup/hijack.ru b/test/rackup/hijack.ru deleted file mode 100644 index b992f384..00000000 --- a/test/rackup/hijack.ru +++ /dev/null @@ -1,6 +0,0 @@ - -run lambda { |env| - io = env['rack.hijack'].call - io.puts "HTTP/1.1 200\r\n\r\nBLAH" - [-1, {}, []] -} diff --git a/test/rackup/hijack2.ru b/test/rackup/hijack2.ru deleted file mode 100644 index bfdbeaf7..00000000 --- a/test/rackup/hijack2.ru +++ /dev/null @@ -1,5 +0,0 @@ -run lambda { |env| - body = lambda { |io| io.puts "BLAH\n"; io.close } - - [200, { 'rack.hijack' => body }, []] -} diff --git a/test/rackup/sleep.ru b/test/rackup/sleep.ru new file mode 100644 index 00000000..a924dc3f --- /dev/null +++ b/test/rackup/sleep.ru @@ -0,0 +1,9 @@ +# call with "GET /sleep HTTP/1.1\r\n\r\n", where is the number of +# seconds to sleep +# same as TestApps::SLEEP + +run lambda { |env| + dly = (env['REQUEST_PATH'][/\/sleep(\d+)/,1] || '0').to_i + sleep dly + [200, {"Content-Type" => "text/plain"}, ["Slept #{dly}"]] +} diff --git a/test/rackup/slow.ru b/test/rackup/slow.ru deleted file mode 100644 index 68f43fde..00000000 --- a/test/rackup/slow.ru +++ /dev/null @@ -1,4 +0,0 @@ -run lambda { |env| - 30000000.times { } - [200, {}, ["Hello World"]] -} diff --git a/test/test_cli.rb b/test/test_cli.rb index 4390eaf8..f372799a 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -41,8 +41,8 @@ class TestCLI < Minitest::Test end def test_control_for_tcp - tcp = next_port - cntl = next_port + tcp = UniquePort.call + cntl = UniquePort.call url = "tcp://127.0.0.1:#{cntl}/" cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:#{tcp}", @@ -207,8 +207,8 @@ class TestCLI < Minitest::Test def test_control_gc_stats_tcp skip_on :jruby, suffix: " - Hitting /gc route does not increment count" - uri = "tcp://127.0.0.1:#{next_port}/" - cntl_port = next_port + uri = "tcp://127.0.0.1:#{UniquePort.call}/" + cntl_port = UniquePort.call cntl = "tcp://127.0.0.1:#{cntl_port}/" control_gc_stats(uri, cntl) { TCPSocket.new "127.0.0.1", cntl_port } @@ -280,7 +280,7 @@ class TestCLI < Minitest::Test end def test_state - url = "tcp://127.0.0.1:#{next_port}" + url = "tcp://127.0.0.1:#{UniquePort.call}" cli = Puma::CLI.new ["--state", @tmp_path, "--control", url] cli.launcher.write_state diff --git a/test/test_integration.rb b/test/test_integration.rb index d886c323..fa131424 100644 --- a/test/test_integration.rb +++ b/test/test_integration.rb @@ -12,9 +12,10 @@ require "open3" class TestIntegration < Minitest::Test def setup - @state_path = "test/test_puma.state" - @bind_path = "test/test_server.sock" - @control_path = "test/test_control.sock" + unique = UniquePort.call + @state_path = "test/test_#{unique}_puma.state" + @bind_path = "test/test_#{unique}_server.sock" + @control_path = "test/test_#{unique}_control.sock" @token = "xxyyzz" @server = nil @@ -45,7 +46,7 @@ class TestIntegration < Minitest::Test end def server_cmd(argv) - @tcp_port = next_port + @tcp_port = UniquePort.call base = "#{Gem.ruby} -Ilib bin/puma" base = "bundle exec #{base}" if defined?(Bundler) "#{base} -b tcp://127.0.0.1:#{@tcp_port} #{argv}" @@ -100,9 +101,9 @@ class TestIntegration < Minitest::Test wait_for_server_to_boot(server) end - def connect + def connect(path = nil) s = TCPSocket.new "localhost", @tcp_port - s << "GET / HTTP/1.1\r\n\r\n" + s << "GET /#{path} HTTP/1.1\r\n\r\n" true until s.gets == "\r\n" s end @@ -158,8 +159,7 @@ class TestIntegration < Minitest::Test def test_phased_restart_via_pumactl skip NO_FORK_MSG unless HAS_FORK - # hello-stuck-ci uses sleep 10, hello-stuck uses sleep 60 - rackup = "test/rackup/hello-stuck#{ ENV['CI'] ? '-ci' : '' }.ru" + delay = 40 conf = Puma::Configuration.new do |c| c.quiet @@ -167,8 +167,8 @@ class TestIntegration < Minitest::Test c.bind "unix://#{@bind_path}" c.activate_control_app "unix://#{@control_path}", :auth_token => @token c.workers 2 - c.worker_shutdown_timeout 1 - c.rackup rackup + c.worker_shutdown_timeout 2 + c.rackup "test/rackup/sleep.ru" end l = Puma::Launcher.new conf, :events => @events @@ -181,7 +181,7 @@ class TestIntegration < Minitest::Test wait_booted s = UNIXSocket.new @bind_path - s << "GET / HTTP/1.0\r\n\r\n" + s << "GET /sleep#{delay} HTTP/1.0\r\n\r\n" sout = StringIO.new # Phased restart @@ -241,7 +241,7 @@ class TestIntegration < Minitest::Test def test_sigterm_closes_listeners_on_forked_servers skip NO_FORK_MSG unless HAS_FORK - pid = start_forked_server("-w 2 -q test/rackup/1second.ru") + pid = start_forked_server("-w 2 -q test/rackup/sleep.ru") threads = [] initial_reply = nil next_replies = [] @@ -249,7 +249,7 @@ class TestIntegration < Minitest::Test mutex = Mutex.new threads << Thread.new do - s = connect + s = connect "sleep1" mutex.synchronize { condition_variable.broadcast } initial_reply = read_body(s) end @@ -284,7 +284,7 @@ class TestIntegration < Minitest::Test threads.map(&:join) - assert_equal "Hello World", initial_reply + assert_equal "Slept 1", initial_reply assert_includes next_replies, :connection_refused @@ -351,9 +351,9 @@ class TestIntegration < Minitest::Test def test_not_accepts_new_connections_after_term_signal skip_on :jruby, :windows - server('test/rackup/10seconds.ru') + server('test/rackup/sleep.ru') - _stdin, curl_stdout, _stderr, curl_wait_thread = Open3.popen3("curl 127.0.0.1:#{@tcp_port}") + _stdin, curl_stdout, _stderr, curl_wait_thread = Open3.popen3("curl http://127.0.0.1:#{@tcp_port}/sleep10") sleep 1 # ensure curl send a request Process.kill(:TERM, @server.pid) @@ -368,7 +368,7 @@ class TestIntegration < Minitest::Test curl_wait_thread.join rejected_curl_wait_thread.join - assert_match(/Hello World/, curl_stdout.read) + assert_match(/Slept 10/, curl_stdout.read) assert_match(/Connection refused/, rejected_curl_stderr.read) Process.wait(@server.pid)