about summary refs log tree commit homepage
path: root/test
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-08-14 21:03:40 -0700
committerEric Wong <normalperson@yhbt.net>2009-08-15 02:35:38 -0700
commit60f9bcd4ba54d84a4b2e2cd621d5995ddf206ace (patch)
tree962d5b9ef2633af63aed070503cf86d607780ade /test
parentf3b379f938719ed7cdfdf2eb92491db276e2da07 (diff)
downloadunicorn-60f9bcd4ba54d84a4b2e2cd621d5995ddf206ace.tar.gz
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.
Diffstat (limited to 'test')
-rw-r--r--test/unit/test_tee_input.rb121
1 files changed, 110 insertions, 11 deletions
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