kcar/response: a few more micro-optimizations
[kcar.git] / test / test_parser.rb
blob7eab684020e33d6efb7d62b8b36a863d641c0256
1 # -*- encoding: binary -*-
2 require 'test/unit'
3 require 'pp'
4 require 'kcar'
5 require 'rack'
7 class TestParser < Test::Unit::TestCase
9   def setup
10     @hp = Kcar::Parser.new
11   end
13   def test_reset
14     assert_nothing_raised { @hp.reset }
15   end
17   def test_parser_status_eof
18     buf = "HTTP/1.0 200 OK\r\n\r\n"
19     hdr = []
20     hdr_object_id = hdr.object_id
21     response = @hp.headers(hdr, buf)
22     assert_equal(["200 OK", hdr], response)
23     assert hdr.empty?
24     assert ! @hp.keepalive?
25     assert_equal hdr_object_id, hdr.object_id
26     assert_equal "", buf
27   end
29   def test_parser_status_eof_one_one
30     buf = "HTTP/1.1 200 OK\r\n\r\n"
31     hdr = []
32     response = @hp.headers(hdr, buf)
33     assert_equal(["200 OK", hdr], response)
34     assert hdr.empty?
35     assert @hp.keepalive? # no content-length
36   end
38   def test_parser_status_with_content_length
39     buf = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"
40     hdr = []
41     response = @hp.headers(hdr, buf)
42     assert_equal(["200 OK", hdr], response)
43     assert_equal([%w(Content-Length 0)], hdr)
44     assert @hp.keepalive?
45   end
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
53     assert_equal "", buf
54     assert_equal 5, @hp.body_bytes_left
55   end
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
64   end
66   def test_bad_crlf
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
73     assert ! @hp.chunked?
74   end
76   def test_chunky_bad_crlf
77     buf = "HTTP/1.1 200 OK\n" \
78           "Transfer-Encoding: chunked\n\n" \
79           "6\nabcdef\n0\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
85     assert @hp.chunked?
86     assert_nil @hp.filter_body(tmp = "", buf)
87     assert_equal "abcdef", tmp
88     assert @hp.keepalive?
89   end
91   def test_chunky
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
100     assert @hp.chunked?
101     assert_nil @hp.filter_body(tmp = "", buf)
102     assert_equal "abcdef", tmp
103     assert @hp.body_eof?
104     assert @hp.keepalive?
105   end
107   def test_chunky_two_step
108     buf = "HTTP/1.1 200 OK\r\n" \
109           "Transfer-Encoding: chunked\r\n\r\n" \
110           "6\r\nabcd"
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
117     assert @hp.chunked?
118     assert_nil @hp.filter_body(tmp = "", buf)
119     assert_equal "abcd", tmp
120     assert_equal "", buf
121     assert ! @hp.body_eof?
122     assert_nil @hp.filter_body(tmp = "", buf2)
123     assert_equal "ef", tmp
124     assert @hp.body_eof?
125     assert_equal({}, @hp.trailers(tmp = {}, buf2))
126     assert @hp.keepalive?
127     assert_nothing_raised { @hp.reset }
128   end
130   def test_trailers_ary
131     buf = "HTTP/1.1 200 OK\r\n" \
132           "Trailer: Foo\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
140     assert @hp.chunked?
141     assert_nil @hp.filter_body(tmp = "", buf)
142     assert_equal "abcdef", tmp
143     assert @hp.body_eof?
144     expect = [ %w(Trailer Foo),
145                %w(Transfer-Encoding chunked),
146                %w(Foo bar) ]
147     assert_equal(expect, @hp.trailers(rv[1], buf))
148     assert @hp.keepalive?
149     assert_nothing_raised { @hp.reset }
150   end
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)
155   end
157   def test_extract_trailers_hash
158     tmp = {
159       'Trailer' => 'Foo',
160       'Transfer-Encoding' => 'chunked',
161       'Foo' => 'bar'
162     }
163     assert_equal [ %w(Foo bar) ], @hp.extract_trailers(tmp)
164   end
166   def test_extract_trailers_header_hash
167     tmp = Rack::Utils::HeaderHash.new(
168       'Trailer' => 'foo',
169       'Transfer-Encoding' => 'chunked',
170       'Foo' => 'bar'
171     )
172     assert_equal [ %w(foo bar) ], @hp.extract_trailers(tmp)
173   end
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"))
182     assert_equal "", buf
183     assert_equal({ 'Set-Cookie' => "a=b\nc=d" }, hdr.to_hash)
184   end
186   def test_repeated_headers_plain_hash
187     hdr = {}
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"))
193     assert_equal "", buf
194     assert_equal({ 'Set-Cookie' => 'a=b', 'set-cookie' => 'c=d' }, hdr)
195   end
197   def test_repeated_headers_array
198     hdr = []
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"))
204     assert_equal "", buf
205     assert_equal([ %w(Set-Cookie a=b), %w(set-cookie c=d) ], hdr)
206   end
208   def test_long_line_headers_array
209     hdr = []
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)
219   end
221   def test_long_line_headers_plain_hash
222     hdr = {}
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)
232   end
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)
246   end
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")
251     end
252     assert_raises(Kcar::ParserError) do
253       @hp.headers([], "HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\n")
254     end
255   end