fix uninstalled testing and reduce require paths
[unicorn.git] / test / unit / test_http_parser_ng.rb
blob0c8107254d0b1f76c7fb201b6d23397045733daf
1 # -*- encoding: binary -*-
3 require './test/test_helper'
4 require 'digest/md5'
6 include Unicorn
8 class HttpParserNgTest < Test::Unit::TestCase
10   def setup
11     @parser = HttpParser.new
12   end
14   def test_parser_max_len
15     assert_raises(RangeError) do
16       HttpParser.max_header_len = 0xffffffff + 1
17     end
18   end
20   def test_next_clear
21     r = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
22     @parser.buf << r
23     @parser.parse
24     @parser.response_start_sent = true
25     assert @parser.keepalive?
26     assert @parser.next?
27     assert @parser.response_start_sent
29     # persistent client makes another request:
30     @parser.buf << r
31     @parser.parse
32     assert @parser.keepalive?
33     assert @parser.next?
34     assert_equal false, @parser.response_start_sent
35   end
37   def test_connection_TE
38     @parser.buf << "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: TE\r\n"
39     @parser.buf << "TE: trailers\r\n\r\n"
40     @parser.parse
41     assert @parser.keepalive?
42     assert @parser.next?
43   end
45   def test_keepalive_requests_with_next?
46     req = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n".freeze
47     expect = {
48       "SERVER_NAME" => "example.com",
49       "HTTP_HOST" => "example.com",
50       "rack.url_scheme" => "http",
51       "REQUEST_PATH" => "/",
52       "SERVER_PROTOCOL" => "HTTP/1.1",
53       "PATH_INFO" => "/",
54       "HTTP_VERSION" => "HTTP/1.1",
55       "REQUEST_URI" => "/",
56       "SERVER_PORT" => "80",
57       "REQUEST_METHOD" => "GET",
58       "QUERY_STRING" => ""
59     }.freeze
60     100.times do |nr|
61       @parser.buf << req
62       assert_equal expect, @parser.parse
63       assert @parser.next?
64     end
65   end
67   def test_default_keepalive_is_off
68     assert ! @parser.keepalive?
69     assert ! @parser.next?
70     @parser.buf << "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
71     @parser.parse
72     assert @parser.keepalive?
73     @parser.clear
74     assert ! @parser.keepalive?
75     assert ! @parser.next?
76   end
78   def test_identity_byte_headers
79     req = @parser.env
80     str = "PUT / HTTP/1.1\r\n"
81     str << "Content-Length: 123\r\n"
82     str << "\r"
83     hdr = @parser.buf
84     str.each_byte { |byte|
85       hdr << byte.chr
86       assert_nil @parser.parse
87     }
88     hdr << "\n"
89     assert_equal req.object_id, @parser.parse.object_id
90     assert_equal '123', req['CONTENT_LENGTH']
91     assert_equal 0, hdr.size
92     assert ! @parser.keepalive?
93     assert @parser.headers?
94     assert_equal 123, @parser.content_length
95     dst = ""
96     buf = '.' * 123
97     @parser.filter_body(dst, buf)
98     assert_equal '.' * 123, dst
99     assert_equal "", buf
100     assert @parser.keepalive?
101   end
103   def test_identity_step_headers
104     req = @parser.env
105     str = @parser.buf
106     str << "PUT / HTTP/1.1\r\n"
107     assert ! @parser.parse
108     str << "Content-Length: 123\r\n"
109     assert ! @parser.parse
110     str << "\r\n"
111     assert_equal req.object_id, @parser.parse.object_id
112     assert_equal '123', req['CONTENT_LENGTH']
113     assert_equal 0, str.size
114     assert ! @parser.keepalive?
115     assert @parser.headers?
116     dst = ""
117     buf = '.' * 123
118     @parser.filter_body(dst, buf)
119     assert_equal '.' * 123, dst
120     assert_equal "", buf
121     assert @parser.keepalive?
122   end
124   def test_identity_oneshot_header
125     req = @parser.env
126     str = @parser.buf
127     str << "PUT / HTTP/1.1\r\nContent-Length: 123\r\n\r\n"
128     assert_equal req.object_id, @parser.parse.object_id
129     assert_equal '123', req['CONTENT_LENGTH']
130     assert_equal 0, str.size
131     assert ! @parser.keepalive?
132     assert @parser.headers?
133     dst = ""
134     buf = '.' * 123
135     @parser.filter_body(dst, buf)
136     assert_equal '.' * 123, dst
137     assert_equal "", buf
138   end
140   def test_identity_oneshot_header_with_body
141     body = ('a' * 123).freeze
142     req = @parser.env
143     str = @parser.buf
144     str << "PUT / HTTP/1.1\r\n" \
145            "Content-Length: #{body.length}\r\n" \
146            "\r\n#{body}"
147     assert_equal req.object_id, @parser.parse.object_id
148     assert_equal '123', req['CONTENT_LENGTH']
149     assert_equal 123, str.size
150     assert_equal body, str
151     tmp = ''
152     assert_nil @parser.filter_body(tmp, str)
153     assert_equal 0, str.size
154     assert_equal tmp, body
155     assert_equal "", @parser.filter_body(tmp, str)
156     assert @parser.keepalive?
157   end
159   def test_identity_oneshot_header_with_body_partial
160     str = @parser.buf
161     str << "PUT / HTTP/1.1\r\nContent-Length: 123\r\n\r\na"
162     assert_equal Hash, @parser.parse.class
163     assert_equal 1, str.size
164     assert_equal 'a', str
165     tmp = ''
166     assert_nil @parser.filter_body(tmp, str)
167     assert_equal "", str
168     assert_equal "a", tmp
169     str << ' ' * 122
170     rv = @parser.filter_body(tmp, str)
171     assert_equal 122, tmp.size
172     assert_nil rv
173     assert_equal "", str
174     assert_equal str.object_id, @parser.filter_body(tmp, str).object_id
175     assert @parser.keepalive?
176   end
178   def test_identity_oneshot_header_with_body_slop
179     str = @parser.buf
180     str << "PUT / HTTP/1.1\r\nContent-Length: 1\r\n\r\naG"
181     assert_equal Hash, @parser.parse.class
182     assert_equal 2, str.size
183     assert_equal 'aG', str
184     tmp = ''
185     assert_nil @parser.filter_body(tmp, str)
186     assert_equal "G", str
187     assert_equal "G", @parser.filter_body(tmp, str)
188     assert_equal 1, tmp.size
189     assert_equal "a", tmp
190     assert @parser.keepalive?
191   end
193   def test_chunked
194     str = @parser.buf
195     req = @parser.env
196     str << "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
197     assert_equal req, @parser.parse, "msg=#{str}"
198     assert_equal 0, str.size
199     tmp = ""
200     assert_nil @parser.filter_body(tmp, str << "6")
201     assert_equal 0, tmp.size
202     assert_nil @parser.filter_body(tmp, str << "\r\n")
203     assert_equal 0, str.size
204     assert_equal 0, tmp.size
205     tmp = ""
206     assert_nil @parser.filter_body(tmp, str << "..")
207     assert_equal "..", tmp
208     assert_nil @parser.filter_body(tmp, str << "abcd\r\n0\r\n")
209     assert_equal "abcd", tmp
210     assert_equal str.object_id, @parser.filter_body(tmp, str << "PUT").object_id
211     assert_equal "PUT", str
212     assert ! @parser.keepalive?
213     str << "TY: FOO\r\n\r\n"
214     assert_equal req, @parser.parse
215     assert_equal "FOO", req["HTTP_PUTTY"]
216     assert @parser.keepalive?
217   end
219   def test_chunked_empty
220     str = @parser.buf
221     req = @parser.env
222     str << "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
223     assert_equal req, @parser.parse, "msg=#{str}"
224     assert_equal 0, str.size
225     tmp = ""
226     assert_equal str, @parser.filter_body(tmp, str << "0\r\n\r\n")
227     assert_equal "", tmp
228   end
230   def test_two_chunks
231     str = @parser.buf
232     str << "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
233     req = @parser.env
234     assert_equal req, @parser.parse
235     assert_equal 0, str.size
236     tmp = ""
237     assert_nil @parser.filter_body(tmp, str << "6")
238     assert_equal 0, tmp.size
239     assert_nil @parser.filter_body(tmp, str << "\r\n")
240     assert_equal "", str
241     assert_equal 0, tmp.size
242     tmp = ""
243     assert_nil @parser.filter_body(tmp, str << "..")
244     assert_equal 2, tmp.size
245     assert_equal "..", tmp
246     assert_nil @parser.filter_body(tmp, str << "abcd\r\n1")
247     assert_equal "abcd", tmp
248     assert_nil @parser.filter_body(tmp, str << "\r")
249     assert_equal "", tmp
250     assert_nil @parser.filter_body(tmp, str << "\n")
251     assert_equal "", tmp
252     assert_nil @parser.filter_body(tmp, str << "z")
253     assert_equal "z", tmp
254     assert_nil @parser.filter_body(tmp, str << "\r\n")
255     assert_nil @parser.filter_body(tmp, str << "0")
256     assert_nil @parser.filter_body(tmp, str << "\r")
257     rv = @parser.filter_body(tmp, str << "\nGET")
258     assert_equal "GET", rv
259     assert_equal str.object_id, rv.object_id
260     assert ! @parser.keepalive?
261   end
263   def test_big_chunk
264     str = @parser.buf
265     str << "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n" \
266            "4000\r\nabcd"
267     req = @parser.env
268     assert_equal req, @parser.parse
269     tmp = ''
270     assert_nil @parser.filter_body(tmp, str)
271     assert_equal '', str
272     str << ' ' * 16300
273     assert_nil @parser.filter_body(tmp, str)
274     assert_equal '', str
275     str << ' ' * 80
276     assert_nil @parser.filter_body(tmp, str)
277     assert_equal '', str
278     assert ! @parser.body_eof?
279     assert_equal "", @parser.filter_body(tmp, str << "\r\n0\r\n")
280     assert_equal "", tmp
281     assert @parser.body_eof?
282     str << "\r\n"
283     assert_equal req, @parser.parse
284     assert_equal "", str
285     assert @parser.body_eof?
286     assert @parser.keepalive?
287   end
289   def test_two_chunks_oneshot
290     str = @parser.buf
291     req = @parser.env
292     str << "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n" \
293            "1\r\na\r\n2\r\n..\r\n0\r\n"
294     assert_equal req, @parser.parse
295     tmp = ''
296     assert_nil @parser.filter_body(tmp, str)
297     assert_equal 'a..', tmp
298     rv = @parser.filter_body(tmp, str)
299     assert_equal rv.object_id, str.object_id
300     assert ! @parser.keepalive?
301   end
303   def test_chunks_bytewise
304     chunked = "10\r\nabcdefghijklmnop\r\n11\r\n0123456789abcdefg\r\n0\r\n"
305     str = "PUT / HTTP/1.1\r\ntransfer-Encoding: chunked\r\n\r\n"
306     buf = @parser.buf
307     buf << str
308     req = @parser.env
309     assert_equal req, @parser.parse
310     assert_equal "", buf
311     tmp = ''
312     body = ''
313     str = chunked[0..-2]
314     str.each_byte { |byte|
315       assert_nil @parser.filter_body(tmp, buf << byte.chr)
316       body << tmp
317     }
318     assert_equal 'abcdefghijklmnop0123456789abcdefg', body
319     rv = @parser.filter_body(tmp, buf<< "\n")
320     assert_equal rv.object_id, buf.object_id
321     assert ! @parser.keepalive?
322   end
324   def test_trailers
325     req = @parser.env
326     str = @parser.buf
327     str << "PUT / HTTP/1.1\r\n" \
328            "Trailer: Content-MD5\r\n" \
329            "transfer-Encoding: chunked\r\n\r\n" \
330            "1\r\na\r\n2\r\n..\r\n0\r\n"
331     assert_equal req, @parser.parse
332     assert_equal 'Content-MD5', req['HTTP_TRAILER']
333     assert_nil req['HTTP_CONTENT_MD5']
334     tmp = ''
335     assert_nil @parser.filter_body(tmp, str)
336     assert_equal 'a..', tmp
337     md5_b64 = [ Digest::MD5.digest(tmp) ].pack('m').strip.freeze
338     rv = @parser.filter_body(tmp, str)
339     assert_equal rv.object_id, str.object_id
340     assert_equal '', str
341     md5_hdr = "Content-MD5: #{md5_b64}\r\n".freeze
342     str << md5_hdr
343     assert_nil @parser.trailers(req, str)
344     assert_equal md5_b64, req['HTTP_CONTENT_MD5']
345     assert_equal "CONTENT_MD5: #{md5_b64}\r\n", str
346     str << "\r"
347     assert_nil @parser.parse
348     str << "\nGET / "
349     assert_equal req, @parser.parse
350     assert_equal "GET / ", str
351     assert @parser.keepalive?
352   end
354   def test_trailers_slowly
355     str = @parser.buf
356     str << "PUT / HTTP/1.1\r\n" \
357            "Trailer: Content-MD5\r\n" \
358            "transfer-Encoding: chunked\r\n\r\n" \
359            "1\r\na\r\n2\r\n..\r\n0\r\n"
360     req = @parser.env
361     assert_equal req, @parser.parse
362     assert_equal 'Content-MD5', req['HTTP_TRAILER']
363     assert_nil req['HTTP_CONTENT_MD5']
364     tmp = ''
365     assert_nil @parser.filter_body(tmp, str)
366     assert_equal 'a..', tmp
367     md5_b64 = [ Digest::MD5.digest(tmp) ].pack('m').strip.freeze
368     rv = @parser.filter_body(tmp, str)
369     assert_equal rv.object_id, str.object_id
370     assert_equal '', str
371     assert_nil @parser.trailers(req, str)
372     md5_hdr = "Content-MD5: #{md5_b64}\r\n".freeze
373     md5_hdr.each_byte { |byte|
374       str << byte.chr
375       assert_nil @parser.trailers(req, str)
376     }
377     assert_equal md5_b64, req['HTTP_CONTENT_MD5']
378     assert_equal "CONTENT_MD5: #{md5_b64}\r\n", str
379     str << "\r"
380     assert_nil @parser.parse
381     str << "\n"
382     assert_equal req, @parser.parse
383   end
385   def test_max_chunk
386     str = @parser.buf
387     str << "PUT / HTTP/1.1\r\n" \
388            "transfer-Encoding: chunked\r\n\r\n" \
389            "#{HttpParser::CHUNK_MAX.to_s(16)}\r\na\r\n2\r\n..\r\n0\r\n"
390     req = @parser.env
391     assert_equal req, @parser.parse
392     assert_nil @parser.content_length
393     @parser.filter_body('', str)
394     assert ! @parser.keepalive?
395   end
397   def test_max_body
398     n = HttpParser::LENGTH_MAX
399     @parser.buf << "PUT / HTTP/1.1\r\nContent-Length: #{n}\r\n\r\n"
400     req = @parser.env
401     @parser.headers(req, @parser.buf)
402     assert_equal n, req['CONTENT_LENGTH'].to_i
403     assert ! @parser.keepalive?
404   end
406   def test_overflow_chunk
407     n = HttpParser::CHUNK_MAX + 1
408     str = @parser.buf
409     req = @parser.env
410     str << "PUT / HTTP/1.1\r\n" \
411            "transfer-Encoding: chunked\r\n\r\n" \
412            "#{n.to_s(16)}\r\na\r\n2\r\n..\r\n0\r\n"
413     assert_equal req, @parser.parse
414     assert_nil @parser.content_length
415     assert_raise(HttpParserError) { @parser.filter_body('', str) }
416   end
418   def test_overflow_content_length
419     n = HttpParser::LENGTH_MAX + 1
420     @parser.buf << "PUT / HTTP/1.1\r\nContent-Length: #{n}\r\n\r\n"
421     assert_raise(HttpParserError) { @parser.parse }
422   end
424   def test_bad_chunk
425     @parser.buf << "PUT / HTTP/1.1\r\n" \
426                    "transfer-Encoding: chunked\r\n\r\n" \
427                    "#zzz\r\na\r\n2\r\n..\r\n0\r\n"
428     req = @parser.env
429     assert_equal req, @parser.parse
430     assert_nil @parser.content_length
431     assert_raise(HttpParserError) { @parser.filter_body("", @parser.buf) }
432   end
434   def test_bad_content_length
435     @parser.buf << "PUT / HTTP/1.1\r\nContent-Length: 7ff\r\n\r\n"
436     assert_raise(HttpParserError) { @parser.parse }
437   end
439   def test_bad_trailers
440     str = @parser.buf
441     req = @parser.env
442     str << "PUT / HTTP/1.1\r\n" \
443            "Trailer: Transfer-Encoding\r\n" \
444            "transfer-Encoding: chunked\r\n\r\n" \
445            "1\r\na\r\n2\r\n..\r\n0\r\n"
446     assert_equal req, @parser.parse
447     assert_equal 'Transfer-Encoding', req['HTTP_TRAILER']
448     tmp = ''
449     assert_nil @parser.filter_body(tmp, str)
450     assert_equal 'a..', tmp
451     assert_equal '', str
452     str << "Transfer-Encoding: identity\r\n\r\n"
453     assert_raise(HttpParserError) { @parser.parse }
454   end
456   def test_repeat_headers
457     str = "PUT / HTTP/1.1\r\n" \
458           "Trailer: Content-MD5\r\n" \
459           "Trailer: Content-SHA1\r\n" \
460           "transfer-Encoding: chunked\r\n\r\n" \
461           "1\r\na\r\n2\r\n..\r\n0\r\n"
462     req = @parser.env
463     @parser.buf << str
464     assert_equal req, @parser.parse
465     assert_equal 'Content-MD5,Content-SHA1', req['HTTP_TRAILER']
466     assert ! @parser.keepalive?
467   end
469   def test_parse_simple_request
470     parser = HttpParser.new
471     req = parser.env
472     parser.buf << "GET /read-rfc1945-if-you-dont-believe-me\r\n"
473     assert_equal req, parser.parse
474     assert_equal '', parser.buf
475     expect = {
476       "SERVER_NAME"=>"localhost",
477       "rack.url_scheme"=>"http",
478       "REQUEST_PATH"=>"/read-rfc1945-if-you-dont-believe-me",
479       "PATH_INFO"=>"/read-rfc1945-if-you-dont-believe-me",
480       "REQUEST_URI"=>"/read-rfc1945-if-you-dont-believe-me",
481       "SERVER_PORT"=>"80",
482       "SERVER_PROTOCOL"=>"HTTP/0.9",
483       "REQUEST_METHOD"=>"GET",
484       "QUERY_STRING"=>""
485     }
486     assert_equal expect, req
487     assert ! parser.headers?
488   end
490   def test_path_info_semicolon
491     qs = "QUERY_STRING"
492     pi = "PATH_INFO"
493     req = {}
494     str = "GET %s HTTP/1.1\r\nHost: example.com\r\n\r\n"
495     {
496       "/1;a=b?c=d&e=f" => { qs => "c=d&e=f", pi => "/1;a=b" },
497       "/1?c=d&e=f" => { qs => "c=d&e=f", pi => "/1" },
498       "/1;a=b" => { qs => "", pi => "/1;a=b" },
499       "/1;a=b?" => { qs => "", pi => "/1;a=b" },
500       "/1?a=b;c=d&e=f" => { qs => "a=b;c=d&e=f", pi => "/1" },
501       "*" => { qs => "", pi => "" },
502     }.each do |uri,expect|
503       assert_equal req, @parser.headers(req.clear, str % [ uri ])
504       req = req.dup
505       @parser.clear
506       assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
507       assert_equal expect[qs], req[qs], "#{qs} mismatch"
508       assert_equal expect[pi], req[pi], "#{pi} mismatch"
509       next if uri == "*"
510       uri = URI.parse("http://example.com#{uri}")
511       assert_equal uri.query.to_s, req[qs], "#{qs} mismatch URI.parse disagrees"
512       assert_equal uri.path, req[pi], "#{pi} mismatch URI.parse disagrees"
513     end
514   end
516   def test_path_info_semicolon_absolute
517     qs = "QUERY_STRING"
518     pi = "PATH_INFO"
519     req = {}
520     str = "GET http://example.com%s HTTP/1.1\r\nHost: www.example.com\r\n\r\n"
521     {
522       "/1;a=b?c=d&e=f" => { qs => "c=d&e=f", pi => "/1;a=b" },
523       "/1?c=d&e=f" => { qs => "c=d&e=f", pi => "/1" },
524       "/1;a=b" => { qs => "", pi => "/1;a=b" },
525       "/1;a=b?" => { qs => "", pi => "/1;a=b" },
526       "/1?a=b;c=d&e=f" => { qs => "a=b;c=d&e=f", pi => "/1" },
527     }.each do |uri,expect|
528       assert_equal req, @parser.headers(req.clear, str % [ uri ])
529       req = req.dup
530       @parser.clear
531       assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
532       assert_equal "example.com", req["HTTP_HOST"], "Host: mismatch"
533       assert_equal expect[qs], req[qs], "#{qs} mismatch"
534       assert_equal expect[pi], req[pi], "#{pi} mismatch"
535     end
536   end
538   def test_negative_content_length
539     req = {}
540     str = "PUT / HTTP/1.1\r\n" \
541           "Content-Length: -1\r\n" \
542           "\r\n"
543     assert_raises(HttpParserError) do
544       @parser.headers(req, str)
545     end
546   end
548   def test_invalid_content_length
549     req = {}
550     str = "PUT / HTTP/1.1\r\n" \
551           "Content-Length: zzzzz\r\n" \
552           "\r\n"
553     assert_raises(HttpParserError) do
554       @parser.headers(req, str)
555     end
556   end
558   def test_backtrace_is_empty
559     begin
560       @parser.headers({}, "AAADFSFDSFD\r\n\r\n")
561       assert false, "should never get here line:#{__LINE__}"
562     rescue HttpParserError => e
563       assert_equal [], e.backtrace
564       return
565     end
566     assert false, "should never get here line:#{__LINE__}"
567   end
569   def test_ignore_version_header
570     @parser.buf << "GET / HTTP/1.1\r\nVersion: hello\r\n\r\n"
571     req = @parser.env
572     assert_equal req, @parser.parse
573     assert_equal '', @parser.buf
574     expect = {
575       "SERVER_NAME" => "localhost",
576       "rack.url_scheme" => "http",
577       "REQUEST_PATH" => "/",
578       "SERVER_PROTOCOL" => "HTTP/1.1",
579       "PATH_INFO" => "/",
580       "HTTP_VERSION" => "HTTP/1.1",
581       "REQUEST_URI" => "/",
582       "SERVER_PORT" => "80",
583       "REQUEST_METHOD" => "GET",
584       "QUERY_STRING" => ""
585     }
586     assert_equal expect, req
587   end
589   def test_pipelined_requests
590     host = "example.com"
591     expect = {
592       "HTTP_HOST" => host,
593       "SERVER_NAME" => host,
594       "REQUEST_PATH" => "/",
595       "rack.url_scheme" => "http",
596       "SERVER_PROTOCOL" => "HTTP/1.1",
597       "PATH_INFO" => "/",
598       "HTTP_VERSION" => "HTTP/1.1",
599       "REQUEST_URI" => "/",
600       "SERVER_PORT" => "80",
601       "REQUEST_METHOD" => "GET",
602       "QUERY_STRING" => ""
603     }
604     req1 = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
605     req2 = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"
606     @parser.buf << (req1 + req2)
607     env1 = @parser.parse.dup
608     assert_equal expect, env1
609     assert_equal req2, @parser.buf
610     assert ! @parser.env.empty?
611     assert @parser.next?
612     assert @parser.keepalive?
613     assert @parser.headers?
614     assert_equal expect, @parser.env
615     env2 = @parser.parse.dup
616     host.replace "www.example.com"
617     assert_equal "www.example.com", expect["HTTP_HOST"]
618     assert_equal "www.example.com", expect["SERVER_NAME"]
619     assert_equal expect, env2
620     assert_equal "", @parser.buf
621   end
623   def test_chunk_only
624     tmp = ""
625     assert_equal @parser, @parser.dechunk!
626     assert_nil @parser.filter_body(tmp, "6\r\n")
627     assert_equal "", tmp
628     assert_nil @parser.filter_body(tmp, "abcdef")
629     assert_equal "abcdef", tmp
630     assert_nil @parser.filter_body(tmp, "\r\n")
631     assert_equal "", tmp
632     src = "0\r\n\r\n"
633     assert_equal src.object_id, @parser.filter_body(tmp, src).object_id
634     assert_equal "", tmp
635   end
637   def test_chunk_only_bad_align
638     tmp = ""
639     assert_equal @parser, @parser.dechunk!
640     assert_nil @parser.filter_body(tmp, "6\r\na")
641     assert_equal "a", tmp
642     assert_nil @parser.filter_body(tmp, "bcde")
643     assert_equal "bcde", tmp
644     assert_nil @parser.filter_body(tmp, "f\r")
645     assert_equal "f", tmp
646     src = "\n0\r\n\r\n"
647     assert_equal src.object_id, @parser.filter_body(tmp, src).object_id
648     assert_equal "", tmp
649   end
651   def test_chunk_only_reset_ok
652     tmp = ""
653     assert_equal @parser, @parser.dechunk!
654     src = "1\r\na\r\n0\r\n\r\n"
655     assert_nil @parser.filter_body(tmp, src)
656     assert_equal "a", tmp
657     assert_equal src.object_id, @parser.filter_body(tmp, src).object_id
659     assert_equal @parser, @parser.dechunk!
660     src = "0\r\n\r\n"
661     assert_equal src.object_id, @parser.filter_body(tmp, src).object_id
662     assert_equal "", tmp
663     assert_equal src, @parser.filter_body(tmp, src)
664   end