1 # -*- encoding: binary -*-
7 class TestTeeInput < Test::Unit::TestCase
13 @rd.sync = @wr.sync = true
18 return if $$ != @start_pid
30 init_parser("hello", 5 + (4096 * 4 * 3) + "#$/foo#$/".size)
31 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
35 3.times { @wr.write("ffff" * 4096) }
40 assert_nothing_raised { line = ti.gets }
41 assert_equal(4096 * 4 * 3 + 5 + $/.size, line.size)
42 assert_equal("hello" << ("ffff" * 4096 * 3) << "#$/", line)
43 assert_nothing_raised { line = ti.gets }
44 assert_equal "foo#$/", line
46 assert_nothing_raised { pid, status = Process.waitpid2(pid) }
47 assert status.success?
51 init_parser("hello", 5 + "#$/foo".size)
52 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
60 assert_nothing_raised { line = ti.gets }
61 assert_equal("hello#$/", line)
62 assert_nothing_raised { line = ti.gets }
63 assert_equal "foo", line
65 assert_nothing_raised { pid, status = Process.waitpid2(pid) }
66 assert status.success?
71 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
72 assert_equal 0, @parser.content_length
73 assert @parser.body_eof?
74 assert_equal StringIO, ti.tmp.class
75 assert_equal 0, ti.tmp.pos
76 assert_equal 5, ti.size
77 assert_equal 'hello', ti.read
78 assert_equal '', ti.read
79 assert_nil ti.read(4096)
82 def test_read_with_buffer
84 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
87 assert_equal 'hell', rv
88 assert_equal 'hell', buf
89 assert_equal rv.object_id, buf.object_id
90 assert_equal 'o', ti.read
91 assert_equal nil, ti.read(5, buf)
92 assert_equal 0, ti.rewind
93 assert_equal 'hello', ti.read(5, buf)
94 assert_equal 'hello', buf
98 init_parser('.' * Unicorn::Const::MAX_BODY << 'a')
99 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
100 assert_equal 0, @parser.content_length
101 assert @parser.body_eof?
102 assert_kind_of File, ti.tmp
103 assert_equal 0, ti.tmp.pos
104 assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
107 def test_read_in_full_if_content_length
109 init_parser('.' * b, 300)
110 assert_equal 300, @parser.content_length
111 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
114 sleep 1 # still a *potential* race here that would make the test moot...
117 assert_equal a, ti.read(a).size
118 _, status = Process.waitpid2(pid)
119 assert status.success?
123 def test_big_body_multi
124 init_parser('.', Unicorn::Const::MAX_BODY + 1)
125 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
126 assert_equal Unicorn::Const::MAX_BODY, @parser.content_length
127 assert ! @parser.body_eof?
128 assert_kind_of File, ti.tmp
129 assert_equal 0, ti.tmp.pos
130 assert_equal 1, ti.tmp.size
131 assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
132 nr = Unicorn::Const::MAX_BODY / 4
135 nr.times { @wr.write('....') }
139 assert_equal '.', ti.read(1)
140 assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
142 assert_equal '....', ti.read(4)
143 assert_equal Unicorn::Const::MAX_BODY + 1, ti.size
145 assert_nil ti.read(1)
147 assert_nothing_raised { pid, status = Process.waitpid2(pid) }
148 assert status.success?
152 @parser = Unicorn::HttpParser.new
153 @buf = "POST / HTTP/1.1\r\n" \
154 "Host: localhost\r\n" \
155 "Transfer-Encoding: chunked\r\n" \
157 assert_equal @env, @parser.headers(@env, @buf)
158 assert_equal "", @buf
162 5.times { @wr.write("5\r\nabcde\r\n") }
166 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
167 assert_nil @parser.content_length
169 assert ! @parser.body_eof?
170 assert_equal 25, ti.size
171 assert @parser.body_eof?
172 assert_equal 25, ti.len
173 assert_equal 0, ti.tmp.pos
174 assert_nothing_raised { ti.rewind }
175 assert_equal 0, ti.tmp.pos
176 assert_equal 'abcdeabcdeabcdeabcde', ti.read(20)
177 assert_equal 20, ti.tmp.pos
178 assert_nothing_raised { ti.rewind }
179 assert_equal 0, ti.tmp.pos
180 assert_kind_of File, ti.tmp
182 assert_nothing_raised { pid, status = Process.waitpid2(pid) }
183 assert status.success?
186 def test_chunked_ping_pong
187 @parser = Unicorn::HttpParser.new
188 @buf = "POST / HTTP/1.1\r\n" \
189 "Host: localhost\r\n" \
190 "Transfer-Encoding: chunked\r\n" \
192 assert_equal @env, @parser.headers(@env, @buf)
193 assert_equal "", @buf
194 chunks = %w(aa bbb cccc dddd eeee)
198 chunks.each do |chunk|
199 rd.read(1) == "." and
200 @wr.write("#{'%x' % [ chunk.size]}\r\n#{chunk}\r\n")
204 ti = Unicorn::TeeInput.new(@rd, @env, @parser, @buf)
205 assert_nil @parser.content_length
207 assert ! @parser.body_eof?
208 chunks.each do |chunk|
210 assert_equal chunk, ti.read(16384)
212 _, status = Process.waitpid2(pid)
213 assert status.success?
218 def init_parser(body, size = nil)
219 @parser = Unicorn::HttpParser.new
220 body = body.to_s.freeze
221 @buf = "POST / HTTP/1.1\r\n" \
222 "Host: localhost\r\n" \
223 "Content-Length: #{size || body.size}\r\n" \
225 assert_equal @env, @parser.headers(@env, @buf)
226 assert_equal body, @buf