From 60f9bcd4ba54d84a4b2e2cd621d5995ddf206ace Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 14 Aug 2009 21:03:40 -0700 Subject: tee_input: make interface more usable outside of Unicorn TeeInput being needed is now (once again) an uncommon code path so there's no point in relying on global constants. While we're at it, allow StringIO to be used in the presence of small inputs; too. --- test/unit/test_tee_input.rb | 121 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 11 deletions(-) (limited to 'test') diff --git a/test/unit/test_tee_input.rb b/test/unit/test_tee_input.rb index 3a6c998..0594d6d 100644 --- a/test/unit/test_tee_input.rb +++ b/test/unit/test_tee_input.rb @@ -27,7 +27,7 @@ class TestTeeInput < Test::Unit::TestCase def test_gets_long init_parser("hello", 5 + (4096 * 4 * 3) + "#$/foo#$/".size) - ti = Unicorn::TeeInput.new(@rd) + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) status = line = nil pid = fork { @rd.close @@ -48,7 +48,7 @@ class TestTeeInput < Test::Unit::TestCase def test_gets_short init_parser("hello", 5 + "#$/foo".size) - ti = Unicorn::TeeInput.new(@rd) + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) status = line = nil pid = fork { @rd.close @@ -65,19 +65,118 @@ class TestTeeInput < Test::Unit::TestCase assert status.success? end + def test_small_body + init_parser('hello') + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) + assert_equal 0, @parser.content_length + assert @parser.body_eof? + assert_equal StringIO, ti.instance_eval { @tmp.class } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_equal 5, ti.size + assert_equal 'hello', ti.read + assert_equal '', ti.read + assert_nil ti.read(4096) + end + + def test_read_with_buffer + init_parser('hello') + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) + buf = '' + rv = ti.read(4, buf) + assert_equal 'hell', rv + assert_equal 'hell', buf + assert_equal rv.object_id, buf.object_id + assert_equal 'o', ti.read + assert_equal nil, ti.read(5, buf) + assert_equal 0, ti.rewind + assert_equal 'hello', ti.read(5, buf) + assert_equal 'hello', buf + end + + def test_big_body + init_parser('.' * Unicorn::Const::MAX_BODY << 'a') + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) + assert_equal 0, @parser.content_length + assert @parser.body_eof? + assert_kind_of File, ti.instance_eval { @tmp } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_equal Unicorn::Const::MAX_BODY + 1, ti.size + end + + def test_big_body_multi + init_parser('.', Unicorn::Const::MAX_BODY + 1) + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) + assert_equal Unicorn::Const::MAX_BODY, @parser.content_length + assert ! @parser.body_eof? + assert_kind_of File, ti.instance_eval { @tmp } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_equal 1, ti.instance_eval { tmp_size } + assert_equal Unicorn::Const::MAX_BODY + 1, ti.size + nr = Unicorn::Const::MAX_BODY / 4 + pid = fork { + @rd.close + nr.times { @wr.write('....') } + @wr.close + } + @wr.close + assert_equal '.', ti.read(1) + assert_equal Unicorn::Const::MAX_BODY + 1, ti.size + nr.times { + assert_equal '....', ti.read(4) + assert_equal Unicorn::Const::MAX_BODY + 1, ti.size + } + assert_nil ti.read(1) + status = nil + assert_nothing_raised { pid, status = Process.waitpid2(pid) } + assert status.success? + end + + def test_chunked + @parser = Unicorn::HttpParser.new + @buf = "POST / HTTP/1.1\r\n" \ + "Host: localhost\r\n" \ + "Transfer-Encoding: chunked\r\n" \ + "\r\n" + assert_equal @env, @parser.headers(@env, @buf) + assert_equal "", @buf + + pid = fork { + @rd.close + 5.times { @wr.write("5\r\nabcde\r\n") } + @wr.write("0\r\n") + } + @wr.close + ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf) + assert_nil @parser.content_length + assert_nil ti.instance_eval { @size } + assert ! @parser.body_eof? + assert_equal 25, ti.size + assert @parser.body_eof? + assert_equal 25, ti.instance_eval { @size } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_nothing_raised { ti.rewind } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_equal 'abcdeabcdeabcdeabcde', ti.read(20) + assert_equal 20, ti.instance_eval { @tmp.pos } + assert_nothing_raised { ti.rewind } + assert_equal 0, ti.instance_eval { @tmp.pos } + assert_kind_of File, ti.instance_eval { @tmp } + status = nil + assert_nothing_raised { pid, status = Process.waitpid2(pid) } + assert status.success? + end + private def init_parser(body, size = nil) - @parser = Unicorn::TeeInput::PARSER - @parser.reset + @parser = Unicorn::HttpParser.new body = body.to_s.freeze - buf = "POST / HTTP/1.1\r\n" \ - "Host: localhost\r\n" \ - "Content-Length: #{size || body.size}\r\n" \ - "\r\n#{body}" - buf = Unicorn::TeeInput::RAW.replace(buf) - assert_equal @env, @parser.headers(@env, buf) - assert_equal body, buf + @buf = "POST / HTTP/1.1\r\n" \ + "Host: localhost\r\n" \ + "Content-Length: #{size || body.size}\r\n" \ + "\r\n#{body}" + assert_equal @env, @parser.headers(@env, @buf) + assert_equal body, @buf end end -- cgit v1.2.3-24-ge0c7