diff options
Diffstat (limited to 'test/unit/test_server.rb')
-rw-r--r-- | test/unit/test_server.rb | 109 |
1 files changed, 43 insertions, 66 deletions
diff --git a/test/unit/test_server.rb b/test/unit/test_server.rb index 8096955..5a2252f 100644 --- a/test/unit/test_server.rb +++ b/test/unit/test_server.rb @@ -1,4 +1,5 @@ # -*- encoding: binary -*- +# frozen_string_literal: false # Copyright (c) 2005 Zed A. Shaw # You can redistribute it and/or modify it under the same terms as Ruby 1.8 or @@ -16,13 +17,30 @@ class TestHandler def call(env) while env['rack.input'].read(4096) end - [200, { 'Content-Type' => 'text/plain' }, ['hello!\n']] + [200, { 'content-type' => 'text/plain' }, ['hello!\n']] rescue Unicorn::ClientShutdown, Unicorn::HttpParserError => e $stderr.syswrite("#{e.class}: #{e.message} #{e.backtrace.empty?}\n") raise e end end +class TestRackAfterReply + def initialize + @called = false + end + + def call(env) + while env['rack.input'].read(4096) + end + + env["rack.after_reply"] << -> { @called = true } + + [200, { 'content-type' => 'text/plain' }, ["after_reply_called: #{@called}"]] + rescue Unicorn::ClientShutdown, Unicorn::HttpParserError => e + $stderr.syswrite("#{e.class}: #{e.message} #{e.backtrace.empty?}\n") + raise e + end +end class WebServerTest < Test::Unit::TestCase @@ -53,7 +71,7 @@ class WebServerTest < Test::Unit::TestCase tmp.sysseek(0) tmp.truncate(0) tmp.syswrite($$) - lambda { |env| [ 200, { 'Content-Type' => 'text/plain' }, [ "#$$\n" ] ] } + lambda { |env| [ 200, { 'content-type' => 'text/plain' }, [ "#$$\n" ] ] } } redirect_test_io do @server = HttpServer.new(app, :listeners => [ "127.0.0.1:#@port"] ) @@ -84,18 +102,30 @@ class WebServerTest < Test::Unit::TestCase tmp.close! end - def test_broken_app + def test_after_reply teardown - app = lambda { |env| raise RuntimeError, "hello" } - # [200, {}, []] } + redirect_test_io do - @server = HttpServer.new(app, :listeners => [ "127.0.0.1:#@port"] ) + @server = HttpServer.new(TestRackAfterReply.new, + :listeners => [ "127.0.0.1:#@port"]) @server.start end - sock = TCPSocket.new('127.0.0.1', @port) + + sock = tcp_socket('127.0.0.1', @port) sock.syswrite("GET / HTTP/1.0\r\n\r\n") - assert_match %r{\AHTTP/1.[01] 500\b}, sock.sysread(4096) - assert_nil sock.close + + responses = sock.read(4096) + assert_match %r{\AHTTP/1.[01] 200\b}, responses + assert_match %r{^after_reply_called: false}, responses + + sock = tcp_socket('127.0.0.1', @port) + sock.syswrite("GET / HTTP/1.0\r\n\r\n") + + responses = sock.read(4096) + assert_match %r{\AHTTP/1.[01] 200\b}, responses + assert_match %r{^after_reply_called: true}, responses + + sock.close end def test_simple_server @@ -103,62 +133,9 @@ class WebServerTest < Test::Unit::TestCase assert_equal 'hello!\n', results[0], "Handler didn't really run" end - def test_client_shutdown_writes - bs = 15609315 * rand - sock = TCPSocket.new('127.0.0.1', @port) - sock.syswrite("PUT /hello HTTP/1.1\r\n") - sock.syswrite("Host: example.com\r\n") - sock.syswrite("Transfer-Encoding: chunked\r\n") - sock.syswrite("Trailer: X-Foo\r\n") - sock.syswrite("\r\n") - sock.syswrite("%x\r\n" % [ bs ]) - sock.syswrite("F" * bs) - sock.syswrite("\r\n0\r\nX-") - "Foo: bar\r\n\r\n".each_byte do |x| - sock.syswrite x.chr - sleep 0.05 - end - # we wrote the entire request before shutting down, server should - # continue to process our request and never hit EOFError on our sock - sock.shutdown(Socket::SHUT_WR) - buf = sock.read - assert_equal 'hello!\n', buf.split(/\r\n\r\n/).last - next_client = Net::HTTP.get(URI.parse("http://127.0.0.1:#@port/")) - assert_equal 'hello!\n', next_client - lines = File.readlines("test_stderr.#$$.log") - assert lines.grep(/^Unicorn::ClientShutdown: /).empty? - assert_nil sock.close - end - - def test_client_shutdown_write_truncates - bs = 15609315 * rand - sock = TCPSocket.new('127.0.0.1', @port) - sock.syswrite("PUT /hello HTTP/1.1\r\n") - sock.syswrite("Host: example.com\r\n") - sock.syswrite("Transfer-Encoding: chunked\r\n") - sock.syswrite("Trailer: X-Foo\r\n") - sock.syswrite("\r\n") - sock.syswrite("%x\r\n" % [ bs ]) - sock.syswrite("F" * (bs / 2.0)) - - # shutdown prematurely, this will force the server to abort - # processing on us even during app dispatch - sock.shutdown(Socket::SHUT_WR) - IO.select([sock], nil, nil, 60) or raise "Timed out" - buf = sock.read - assert_equal "", buf - next_client = Net::HTTP.get(URI.parse("http://127.0.0.1:#@port/")) - assert_equal 'hello!\n', next_client - lines = File.readlines("test_stderr.#$$.log") - lines = lines.grep(/^Unicorn::ClientShutdown: bytes_read=\d+/) - assert_equal 1, lines.size - assert_match %r{\AUnicorn::ClientShutdown: bytes_read=\d+ true$}, lines[0] - assert_nil sock.close - end - def test_client_malformed_body bs = 15653984 - sock = TCPSocket.new('127.0.0.1', @port) + sock = tcp_socket('127.0.0.1', @port) sock.syswrite("PUT /hello HTTP/1.1\r\n") sock.syswrite("Host: example.com\r\n") sock.syswrite("Transfer-Encoding: chunked\r\n") @@ -180,7 +157,7 @@ class WebServerTest < Test::Unit::TestCase def do_test(string, chunk, close_after=nil, shutdown_delay=0) # Do not use instance variables here, because it needs to be thread safe - socket = TCPSocket.new("127.0.0.1", @port); + socket = tcp_socket("127.0.0.1", @port); request = StringIO.new(string) chunks_out = 0 @@ -225,14 +202,14 @@ class WebServerTest < Test::Unit::TestCase end def test_bad_client_400 - sock = TCPSocket.new('127.0.0.1', @port) + sock = tcp_socket('127.0.0.1', @port) sock.syswrite("GET / HTTP/1.0\r\nHost: foo\rbar\r\n\r\n") assert_match %r{\AHTTP/1.[01] 400\b}, sock.sysread(4096) assert_nil sock.close end def test_http_0_9 - sock = TCPSocket.new('127.0.0.1', @port) + sock = tcp_socket('127.0.0.1', @port) sock.syswrite("GET /hello\r\n") assert_match 'hello!\n', sock.sysread(4096) assert_nil sock.close |