diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/exec/test_exec.rb | 9 | ||||
-rw-r--r-- | test/unit/test_ccc.rb | 90 | ||||
-rw-r--r-- | test/unit/test_http_parser.rb | 18 | ||||
-rw-r--r-- | test/unit/test_socket_helper.rb | 12 | ||||
-rw-r--r-- | test/unit/test_util.rb | 4 |
5 files changed, 105 insertions, 28 deletions
diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb index ca0b7bc..08f92ae 100644 --- a/test/exec/test_exec.rb +++ b/test/exec/test_exec.rb @@ -97,6 +97,9 @@ run lambda { |env| end def test_sd_listen_fds_emulation + # [ruby-core:69895] [Bug #11336] fixed by r51576 + return if RUBY_VERSION.to_f < 2.3 + File.open("config.ru", "wb") { |fp| fp.write(HI) } sock = TCPServer.new(@addr, @port) @@ -124,9 +127,7 @@ run lambda { |env| end ensure sock.close if sock - # disabled test on old Rubies: https://bugs.ruby-lang.org/issues/11336 - # [ruby-core:69895] [Bug #11336] fixed by r51576 - end if RUBY_VERSION.to_f >= 2.3 + end def test_inherit_listener_unspecified File.open("config.ru", "wb") { |fp| fp.write(HI) } @@ -142,7 +143,7 @@ run lambda { |env| res = hit(["http://#@addr:#@port/"]) assert_equal [ "HI\n" ], res assert_shutdown(pid) - assert_equal 1, sock.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).int, + assert sock.getsockopt(:SOL_SOCKET, :SO_KEEPALIVE).bool, 'unicorn should always set SO_KEEPALIVE on inherited sockets' ensure sock.close if sock diff --git a/test/unit/test_ccc.rb b/test/unit/test_ccc.rb new file mode 100644 index 0000000..0db0c38 --- /dev/null +++ b/test/unit/test_ccc.rb @@ -0,0 +1,90 @@ +require 'socket' +require 'unicorn' +require 'io/wait' +require 'tempfile' +require 'test/unit' + +class TestCccTCPI < Test::Unit::TestCase + def test_ccc_tcpi + start_pid = $$ + host = '127.0.0.1' + srv = TCPServer.new(host, 0) + port = srv.addr[1] + err = Tempfile.new('unicorn_ccc') + rd, wr = IO.pipe + sleep_pipe = IO.pipe + pid = fork do + sleep_pipe[1].close + reqs = 0 + rd.close + worker_pid = nil + app = lambda do |env| + worker_pid ||= begin + at_exit { wr.write(reqs.to_s) if worker_pid == $$ } + $$ + end + reqs += 1 + + # will wake up when writer closes + sleep_pipe[0].read if env['PATH_INFO'] == '/sleep' + + [ 200, [ %w(Content-Length 0), %w(Content-Type text/plain) ], [] ] + end + ENV['UNICORN_FD'] = srv.fileno.to_s + opts = { + listeners: [ "#{host}:#{port}" ], + stderr_path: err.path, + check_client_connection: true, + } + uni = Unicorn::HttpServer.new(app, opts) + uni.start.join + end + wr.close + + # make sure the server is running, at least + client = TCPSocket.new(host, port) + client.write("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n") + assert client.wait_readable(10), 'never got response from server' + res = client.read + assert_match %r{\AHTTP/1\.1 200}, res, 'got part of first response' + assert_match %r{\r\n\r\n\z}, res, 'got end of response, server is ready' + client.close + + # start a slow request... + sleeper = TCPSocket.new(host, port) + sleeper.write("GET /sleep HTTP/1.1\r\nHost: example.com\r\n\r\n") + + # and a bunch of aborted ones + nr = 100 + nr.times do |i| + client = TCPSocket.new(host, port) + client.write("GET /collections/#{rand(10000)} HTTP/1.1\r\n" \ + "Host: example.com\r\n\r\n") + client.close + end + sleep_pipe[1].close # wake up the reader in the worker + res = sleeper.read + assert_match %r{\AHTTP/1\.1 200}, res, 'got part of first sleeper response' + assert_match %r{\r\n\r\n\z}, res, 'got end of sleeper response' + sleeper.close + kpid = pid + pid = nil + Process.kill(:QUIT, kpid) + _, status = Process.waitpid2(kpid) + assert status.success? + reqs = rd.read.to_i + warn "server got #{reqs} requests with #{nr} CCC aborted\n" if $DEBUG + assert_operator reqs, :<, nr + assert_operator reqs, :>=, 2, 'first 2 requests got through, at least' + ensure + return if start_pid != $$ + srv.close if srv + if pid + Process.kill(:QUIT, pid) + _, status = Process.waitpid2(pid) + assert status.success? + end + err.close! if err + rd.close if rd + end +end diff --git a/test/unit/test_http_parser.rb b/test/unit/test_http_parser.rb index 7cbc0f8..31e6f71 100644 --- a/test/unit/test_http_parser.rb +++ b/test/unit/test_http_parser.rb @@ -851,24 +851,6 @@ class HttpParserTest < Test::Unit::TestCase assert_equal '', parser.env['HTTP_HOST'] end - # so we don't care about the portability of this test - # if it doesn't leak on Linux, it won't leak anywhere else - # unless your C compiler or platform is otherwise broken - LINUX_PROC_PID_STATUS = "/proc/self/status" - def test_memory_leak - match_rss = /^VmRSS:\s+(\d+)/ - if File.read(LINUX_PROC_PID_STATUS) =~ match_rss - before = $1.to_i - 1000000.times { Unicorn::HttpParser.new } - File.read(LINUX_PROC_PID_STATUS) =~ match_rss - after = $1.to_i - diff = after - before - assert(diff < 10000, "memory grew more than 10M: #{diff}") - end - end if RUBY_PLATFORM =~ /linux/ && - File.readable?(LINUX_PROC_PID_STATUS) && - !defined?(RUBY_ENGINE) - def test_memsize require 'objspace' if ObjectSpace.respond_to?(:memsize_of) diff --git a/test/unit/test_socket_helper.rb b/test/unit/test_socket_helper.rb index 7526e82..8699409 100644 --- a/test/unit/test_socket_helper.rb +++ b/test/unit/test_socket_helper.rb @@ -150,28 +150,31 @@ class TestSocketHelper < Test::Unit::TestCase end def test_tcp_defer_accept_default + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert cur >= 1 - end if defined?(TCP_DEFER_ACCEPT) + end def test_tcp_defer_accept_disable + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :tcp_defer_accept => false) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert_equal 0, cur - end if defined?(TCP_DEFER_ACCEPT) + end def test_tcp_defer_accept_nr + return unless defined?(TCP_DEFER_ACCEPT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :tcp_defer_accept => 60) cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0] assert cur > 1 - end if defined?(TCP_DEFER_ACCEPT) + end def test_ipv6only port = begin @@ -186,6 +189,7 @@ class TestSocketHelper < Test::Unit::TestCase end def test_reuseport + return unless defined?(Socket::SO_REUSEPORT) port = unused_port @test_addr name = "#@test_addr:#{port}" sock = bind_listen(name, :reuseport => true) @@ -193,5 +197,5 @@ class TestSocketHelper < Test::Unit::TestCase assert_operator cur, :>, 0 rescue Errno::ENOPROTOOPT # kernel does not support SO_REUSEPORT (older Linux) - end if defined?(Socket::SO_REUSEPORT) + end end diff --git a/test/unit/test_util.rb b/test/unit/test_util.rb index 4d17a16..dc6302e 100644 --- a/test/unit/test_util.rb +++ b/test/unit/test_util.rb @@ -69,7 +69,7 @@ class TestUtil < Test::Unit::TestCase } } tmp.close! - end if STDIN.respond_to?(:external_encoding) + end def test_reopen_logs_renamed_with_internal_encoding tmp = Tempfile.new('') @@ -101,5 +101,5 @@ class TestUtil < Test::Unit::TestCase } } tmp.close! - end if STDIN.respond_to?(:external_encoding) + end end |