1 # -*- encoding: binary -*-
7 class TestParser < Test::Unit::TestCase
10 @hp = Kcar::Parser.new
14 assert_nothing_raised { @hp.reset }
17 def test_parser_status_eof
18 buf = "HTTP/1.0 200 OK\r\n\r\n"
20 hdr_object_id = hdr.object_id
21 response = @hp.headers(hdr, buf)
22 assert_equal(["200 OK", hdr], response)
24 assert ! @hp.keepalive?
25 assert_equal hdr_object_id, hdr.object_id
29 def test_parser_status_eof_one_one
30 buf = "HTTP/1.1 200 OK\r\n\r\n"
32 response = @hp.headers(hdr, buf)
33 assert_equal(["200 OK", hdr], response)
35 assert @hp.keepalive? # no content-length
38 def test_parser_status_with_content_length
39 buf = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
41 response = @hp.headers(hdr, buf)
42 assert_equal(["200 OK", hdr], response)
43 assert_equal([%w(Content-Length 0)], hdr)
47 def test_parser_content_length
48 buf = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
49 rv = @hp.headers([], buf)
50 assert_equal "200 OK", rv[0]
51 assert_equal([ %w(Content-Length 5) ], rv[1])
52 assert_equal 2, rv.size
54 assert_equal 5, @hp.body_bytes_left
57 def test_parser_content_length_with_body
58 buf = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nabcde"
59 rv = @hp.headers([], buf)
60 assert_equal "200 OK", rv[0]
61 assert_equal([ %w(Content-Length 5) ], rv[1])
62 assert_equal "abcde", buf
63 assert_equal 5, @hp.body_bytes_left
67 buf = "HTTP/1.1 200 OK\nContent-Length: 5\n\r\nabcde"
68 rv = @hp.headers([], buf)
69 assert_equal "200 OK", rv[0]
70 assert_equal([ %w(Content-Length 5) ], rv[1])
71 assert_equal "abcde", buf
72 assert_equal 5, @hp.body_bytes_left
76 def test_chunky_bad_crlf
77 buf = "HTTP/1.1 200 OK\n" \
78 "Transfer-Encoding: chunked\n\n" \
80 rv = @hp.headers([], buf)
81 assert_equal "200 OK", rv[0]
82 assert_equal([ %w(Transfer-Encoding chunked) ], rv[1])
83 assert_equal "6\nabcdef\n0\n\n", buf
84 assert_nil @hp.body_bytes_left
86 assert_nil @hp.filter_body(tmp = "", buf)
87 assert_equal "abcdef", tmp
92 buf = "HTTP/1.1 200 OK\r\n" \
93 "Transfer-Encoding: chunked\r\n\r\n" \
94 "6\r\nabcdef\r\n0\r\n\r\n"
95 rv = @hp.headers([], buf)
96 assert_equal "200 OK", rv[0]
97 assert_equal([ %w(Transfer-Encoding chunked) ], rv[1])
98 assert_equal "6\r\nabcdef\r\n0\r\n\r\n", buf
99 assert_nil @hp.body_bytes_left
101 assert_nil @hp.filter_body(tmp = "", buf)
102 assert_equal "abcdef", tmp
104 assert @hp.keepalive?
107 def test_chunky_two_step
108 buf = "HTTP/1.1 200 OK\r\n" \
109 "Transfer-Encoding: chunked\r\n\r\n" \
111 buf2 = "ef\r\n0\r\n\r\n"
112 rv = @hp.headers([], buf)
113 assert_equal "200 OK", rv[0]
114 assert_equal([ %w(Transfer-Encoding chunked) ], rv[1])
115 assert_equal "6\r\nabcd", buf
116 assert_nil @hp.body_bytes_left
118 assert_nil @hp.filter_body(tmp = "", buf)
119 assert_equal "abcd", tmp
121 assert ! @hp.body_eof?
122 assert_nil @hp.filter_body(tmp = "", buf2)
123 assert_equal "ef", tmp
125 assert_equal({}, @hp.trailers(tmp = {}, buf2))
126 assert @hp.keepalive?
127 assert_nothing_raised { @hp.reset }
130 def test_trailers_ary
131 buf = "HTTP/1.1 200 OK\r\n" \
133 "Transfer-Encoding: chunked\r\n\r\n" \
134 "6\r\nabcdef\r\n0\r\nFoo: bar\r\n\r\n"
135 rv = @hp.headers([], buf)
136 assert_equal "200 OK", rv[0]
137 assert_equal([ %w(Trailer Foo), %w(Transfer-Encoding chunked) ], rv[1])
138 assert_equal "6\r\nabcdef\r\n0\r\nFoo: bar\r\n\r\n", buf
139 assert_nil @hp.body_bytes_left
141 assert_nil @hp.filter_body(tmp = "", buf)
142 assert_equal "abcdef", tmp
144 expect = [ %w(Trailer Foo),
145 %w(Transfer-Encoding chunked),
147 assert_equal(expect, @hp.trailers(rv[1], buf))
148 assert @hp.keepalive?
149 assert_nothing_raised { @hp.reset }
152 def test_extract_trailers_ary
153 tmp = [ %w(Trailer Foo), %w(Transfer-Encoding chunked), %w(Foo bar) ]
154 assert_equal [ %w(Foo bar) ], @hp.extract_trailers(tmp)
157 def test_extract_trailers_hash
160 'Transfer-Encoding' => 'chunked',
163 assert_equal [ %w(Foo bar) ], @hp.extract_trailers(tmp)
166 def test_extract_trailers_header_hash
167 tmp = Rack::Utils::HeaderHash.new(
169 'Transfer-Encoding' => 'chunked',
172 assert_equal [ %w(foo bar) ], @hp.extract_trailers(tmp)
175 def test_repeated_headers_rack_hash
176 hdr = Rack::Utils::HeaderHash.new
177 buf = "HTTP/1.1 200 OK\r\nSet-Cookie: a=b\r\n"
178 assert_nil @hp.headers(hdr, buf)
179 assert_equal({ 'Set-Cookie' => 'a=b' }, hdr.to_hash)
180 assert_nil @hp.headers(hdr, buf << "set-cookie: c=d\r\n")
181 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
183 assert_equal({ 'Set-Cookie' => "a=b\nc=d" }, hdr.to_hash)
186 def test_repeated_headers_plain_hash
188 buf = "HTTP/1.1 200 OK\r\nSet-Cookie: a=b\r\n"
189 assert_nil @hp.headers(hdr, buf)
190 assert_equal({ 'Set-Cookie' => 'a=b' }, hdr)
191 assert_nil @hp.headers(hdr, buf << "set-cookie: c=d\r\n")
192 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
194 assert_equal({ 'Set-Cookie' => 'a=b', 'set-cookie' => 'c=d' }, hdr)
197 def test_repeated_headers_array
199 buf = "HTTP/1.1 200 OK\r\nSet-Cookie: a=b\r\n"
200 assert_nil @hp.headers(hdr, buf)
201 assert_equal([ %w(Set-Cookie a=b) ] , hdr)
202 assert_nil @hp.headers(hdr, buf << "set-cookie: c=d\r\n")
203 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
205 assert_equal([ %w(Set-Cookie a=b), %w(set-cookie c=d) ], hdr)
208 def test_long_line_headers_array
210 buf = "HTTP/1.1 200 OK\r\na: b\r\n"
211 assert_nil @hp.headers(hdr, buf)
212 assert_equal([ %w(a b) ] , hdr)
213 assert_nil @hp.headers(hdr, buf << " c\r\n")
214 assert_equal([ [ 'a', 'b c'] ], hdr)
215 assert_nil @hp.headers(hdr, buf << " d\n")
216 assert_equal([ [ 'a', 'b c d'] ], hdr)
217 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
218 assert_equal([ [ 'a', 'b c d'] ], hdr)
221 def test_long_line_headers_plain_hash
223 buf = "HTTP/1.1 200 OK\r\na: b\r\n"
224 assert_nil @hp.headers(hdr, buf)
225 assert_equal({ 'a' => 'b' }, hdr)
226 assert_nil @hp.headers(hdr, buf << " c\r\n")
227 assert_equal({ 'a' => 'b c' }, hdr)
228 assert_nil @hp.headers(hdr, buf << " d\r\n")
229 assert_equal({ 'a' => 'b c d' }, hdr)
230 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
231 assert_equal({ 'a' => 'b c d' }, hdr)
234 def test_long_line_headers_rack_hash
235 hdr = Rack::Utils::HeaderHash.new
236 buf = "HTTP/1.1 200 OK\r\na: b\r\n"
237 assert_nil @hp.headers(hdr, buf)
238 assert_equal({ 'a' => 'b' }, hdr.to_hash)
239 assert_nil @hp.headers(hdr, buf << " c\r\n")
240 assert_equal({ 'a' => 'b c' }, hdr)
241 assert_nil @hp.headers(hdr, buf << " d\r\n")
242 assert_equal({ 'a' => 'b c d' }, hdr)
243 assert_nil @hp.headers(hdr, buf << "A: e\r\n")
244 assert_equal([ "200 OK", hdr ], @hp.headers(hdr, buf << "\r\n"))
245 assert_equal({ 'a' => "b c d\ne"}, hdr.to_hash)
248 def test_content_length_invalid
249 assert_raises(Kcar::ParserError) do
250 @hp.headers([], "HTTP/1.1 200 OK\r\nContent-Length: 5a\r\n\r\n")
252 assert_raises(Kcar::ParserError) do
253 @hp.headers([], "HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\n")
258 resp = "HTTP/1.1 200 OK\r\nHost:\texample.com\r\n\r\n"
259 assert @hp.headers(env = {}, resp)
260 assert_equal 'example.com', env['Host']
263 def test_trailing_whitespace
264 resp = "HTTP/1.1 200 OK\r\nHost: example.com \r\n\r\n"
265 assert @hp.headers(env = {}, resp)
266 assert_equal 'example.com', env['Host']
269 def test_trailing_tab
270 resp = "HTTP/1.1 200 OK\r\nHost: example.com\t\r\n\r\n"
271 assert @hp.headers(env = {}, resp)
272 assert_equal 'example.com', env['Host']
275 def test_trailing_multiple_linear_whitespace
276 resp = "HTTP/1.1 200 OK\r\nHost: example.com\t \t \t\r\n\r\n"
277 assert @hp.headers(env = {}, resp)
278 assert_equal 'example.com', env['Host']
281 def test_embedded_linear_whitespace_ok
282 resp = "HTTP/1.1 200 OK\r\nX-Space: hello\t world\t \r\n\r\n"
283 assert @hp.headers(env = {}, resp)
284 assert_equal "hello\t world", env["X-Space"]
287 def test_empty_header
288 resp = "HTTP/1.1 200 OK\r\nHost: \r\n\r\n"
289 assert @hp.headers(env = {}, resp)
290 assert_equal '', env['Host']
295 n = ObjectSpace.memsize_of(@hp)
296 assert_kind_of Integer, n
298 warn 'ObjectSpace not available'