move all #gets logic to tee_input out of chunked_reader
[unicorn.git] / test / unit / test_chunked_reader.rb
bloba1323e922ba4f942fcf73199ec657ba648f24e27
1 require 'test/unit'
2 require 'unicorn'
3 require 'unicorn_http'
4 require 'tempfile'
5 require 'io/nonblock'
6 require 'digest/sha1'
8 class TestChunkedReader < Test::Unit::TestCase
10   def setup
11     @env = {}
12     @rd, @wr = IO.pipe
13     @rd.binmode
14     @wr.binmode
15     @rd.sync = @wr.sync = true
16     @start_pid = $$
17   end
19   def teardown
20     return if $$ != @start_pid
21     @rd.close rescue nil
22     @wr.close rescue nil
23     begin
24       Process.wait
25     rescue Errno::ECHILD
26       break
27     end while true
28   end
30   def test_error
31     cr = bin_reader("8\r\nasdfasdf\r\n8\r\nasdfasdfa#{'a' * 1024}")
32     a = nil
33     assert_nothing_raised { a = cr.readpartial(8192) }
34     assert_equal 'asdfasdf', a
35     assert_nothing_raised { a = cr.readpartial(8192) }
36     assert_equal 'asdfasdf', a
37     assert_raises(Unicorn::HttpParserError) { cr.readpartial(8192) }
38   end
40   def test_eof1
41     cr = bin_reader("0\r\n")
42     assert_raises(EOFError) { cr.readpartial(8192) }
43   end
45   def test_eof2
46     cr = bin_reader("0\r\n\r\n")
47     assert_raises(EOFError) { cr.readpartial(8192) }
48   end
50   def test_readpartial1
51     cr = bin_reader("4\r\nasdf\r\n0\r\n")
52     assert_equal 'asdf', cr.readpartial(8192)
53     assert_raises(EOFError) { cr.readpartial(8192) }
54   end
56   def test_dd
57     cr = bin_reader("6\r\nhello\n\r\n")
58     tmp = Tempfile.new('test_dd')
59     tmp.sync = true
61     pid = fork {
62       crd, cwr = IO.pipe
63       crd.binmode
64       cwr.binmode
65       crd.sync = cwr.sync = true
67       pid = fork {
68         STDOUT.reopen(cwr)
69         crd.close
70         cwr.close
71         exec('dd', 'if=/dev/urandom', 'bs=93390', 'count=16')
72       }
73       cwr.close
74       begin
75         buf = crd.readpartial(16384)
76         tmp.write(buf)
77         @wr.write("#{'%x' % buf.size}\r\n#{buf}\r\n")
78       rescue EOFError
79         @wr.write("0\r\n\r\n")
80         Process.waitpid(pid)
81         exit 0
82       end while true
83     }
84     assert_equal "hello\n", cr.readpartial(6)
85     sha1 = Digest::SHA1.new
86     buf = Unicorn::Z.dup
87     begin
88       cr.readpartial(16384, buf)
89       sha1.update(buf)
90     rescue EOFError
91       break
92     end while true
94     assert_nothing_raised { Process.waitpid(pid) }
95     sha1_file = Digest::SHA1.new
96     File.open(tmp.path, 'rb') { |fp|
97       while fp.read(16384, buf)
98         sha1_file.update(buf)
99       end
100     }
101     assert_equal sha1_file.hexdigest, sha1.hexdigest
102   end
104   def test_trailer
105     @env['HTTP_TRAILER'] = 'Content-MD5'
106     pid = fork { @wr.syswrite("Content-MD5: asdf\r\n") }
107     cr = bin_reader("8\r\nasdfasdf\r\n8\r\nasdfasdf\r\n0\r\n")
108     assert_equal 'asdfasdf', cr.readpartial(4096)
109     assert_equal 'asdfasdf', cr.readpartial(4096)
110     assert_raises(EOFError) { cr.readpartial(4096) }
111     pid, status = Process.waitpid2(pid)
112     assert status.success?
113     assert_equal 'asdf', @env['HTTP_CONTENT_MD5']
114   end
116 private
118   def bin_reader(buf)
119     buf.force_encoding(Encoding::BINARY) if buf.respond_to?(:force_encoding)
120     Unicorn::ChunkedReader.new(@env, @rd, buf)
121   end