1 # -*- encoding: binary -*-
7 class TestStreamInput < Test::Unit::TestCase
11 @rd, @wr = Kgio::UNIXSocket.pair
12 @rd.sync = @wr.sync = true
17 return if $$ != @start_pid
24 def test_read_negative
25 r = init_request('hello')
26 si = Unicorn::StreamInput.new(@rd, r)
27 assert_raises(ArgumentError) { si.read(-1) }
28 assert_equal 'hello', si.read
32 r = init_request('hello')
33 si = Unicorn::StreamInput.new(@rd, r)
34 assert_equal 'hello', si.read
35 assert_equal '', si.read
40 def test_gets_oneliner
41 r = init_request('hello')
42 si = Unicorn::StreamInput.new(@rd, r)
43 assert_equal 'hello', si.gets
47 def test_gets_multiline
48 r = init_request("a\nb\n\n")
49 si = Unicorn::StreamInput.new(@rd, r)
50 assert_equal "a\n", si.gets
51 assert_equal "b\n", si.gets
52 assert_equal "\n", si.gets
56 def test_gets_empty_rs
58 r = init_request("a\nb\n\n")
59 si = Unicorn::StreamInput.new(@rd, r)
60 assert_equal "a\nb\n\n", si.gets
64 def test_read_with_equal_len
65 r = init_request("abcde")
66 si = Unicorn::StreamInput.new(@rd, r)
67 assert_equal "abcde", si.read(5)
71 def test_big_body_multi
72 r = init_request('.', Unicorn::Const::MAX_BODY + 1)
73 si = Unicorn::StreamInput.new(@rd, r)
74 assert_equal Unicorn::Const::MAX_BODY, @parser.content_length
75 assert ! @parser.body_eof?
76 nr = Unicorn::Const::MAX_BODY / 4
79 nr.times { @wr.write('....') }
83 assert_equal '.', si.read(1)
85 assert_equal '....', si.read(4), "nr=#{x}"
88 pid, status = Process.waitpid2(pid)
89 assert status.success?
93 r = init_request("hello", 5 + (4096 * 4 * 3) + "#$/foo#$/".size)
94 si = Unicorn::StreamInput.new(@rd, r)
98 3.times { @wr.write("ffff" * 4096) }
104 assert_equal(4096 * 4 * 3 + 5 + $/.size, line.size)
105 assert_equal("hello" << ("ffff" * 4096 * 3) << "#$/", line)
107 assert_equal "foo#$/", line
109 pid, status = Process.waitpid2(pid)
110 assert status.success?
113 def test_read_with_buffer
114 r = init_request('hello')
115 si = Unicorn::StreamInput.new(@rd, r)
118 assert_equal 'hell', rv
119 assert_equal 'hell', buf
120 assert_equal rv.object_id, buf.object_id
121 assert_equal 'o', si.read
122 assert_equal nil, si.read(5, buf)
125 def test_read_with_buffer_clobbers
126 r = init_request('hello')
127 si = Unicorn::StreamInput.new(@rd, r)
129 assert_equal 'hello', si.read(nil, buf)
130 assert_equal 'hello', buf
131 assert_equal '', si.read(nil, buf)
134 assert_nil si.read(5, buf)
139 r = init_request('hello')
140 si = Unicorn::StreamInput.new(@rd, r)
141 assert_equal '', si.read(0)
144 assert_equal rv.object_id, buf.object_id
146 assert_equal 'hello', si.read
147 assert_nil si.read(5)
148 assert_equal '', si.read(0)
151 assert_equal rv.object_id, buf.object_id
155 def test_gets_read_mix
156 r = init_request("hello\nasdfasdf")
157 si = Unicorn::StreamInput.new(@rd, r)
158 assert_equal "hello\n", si.gets
159 assert_equal "asdfasdf", si.read(9)
160 assert_nil si.read(9)
163 def test_gets_read_mix_chunked
164 r = @parser = Unicorn::HttpParser.new
166 @buf = "POST / HTTP/1.1\r\n" \
167 "Host: localhost\r\n" \
168 "Transfer-Encoding: chunked\r\n" \
170 assert_equal @env, @parser.headers(@env, @buf)
171 assert_equal body, @buf
172 si = Unicorn::StreamInput.new(@rd, r)
173 @wr.syswrite "\n\r\n"
174 assert_equal "hello\n", si.gets
175 @wr.syswrite "8\r\nasdfasdf\r\n"
176 assert_equal"asdfasdf", si.read(9) + si.read(9)
177 @wr.syswrite "0\r\n\r\n"
178 assert_nil si.read(9)
181 def test_gets_read_mix_big
182 r = init_request("hello\n#{'.' * 65536}")
183 si = Unicorn::StreamInput.new(@rd, r)
184 assert_equal "hello\n", si.gets
185 assert_equal '.' * 16384, si.read(16384)
186 assert_equal '.' * 16383, si.read(16383)
187 assert_equal '.' * 16384, si.read(16384)
188 assert_equal '.' * 16385, si.read(16385)
192 def init_request(body, size = nil)
193 @parser = Unicorn::HttpParser.new
194 body = body.to_s.freeze
195 @buf = "POST / HTTP/1.1\r\n" \
196 "Host: localhost\r\n" \
197 "Content-Length: #{size || body.size}\r\n" \
199 assert_equal @env, @parser.headers(@env, @buf)
200 assert_equal body, @buf