diff options
Diffstat (limited to 'test/unit')
-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 |
4 files changed, 100 insertions, 24 deletions
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 |