close client socket after closing response body
[unicorn.git] / test / unit / test_response.rb
blobb3bc3a2fb5cb47a63bf2f151249cf13cdb122588
1 # -*- encoding: binary -*-
3 # Copyright (c) 2005 Zed A. Shaw 
4 # You can redistribute it and/or modify it under the same terms as Ruby.
6 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html 
7 # for more information.
9 require 'test/test_helper'
11 include Unicorn
13 class ResponseTest < Test::Unit::TestCase
14   
15   def test_response_headers
16     out = StringIO.new
17     HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, ["cool"]])
18     assert ! out.closed?
19     assert out.length > 0, "output didn't have data"
20   end
22   def test_response_string_status
23     out = StringIO.new
24     HttpResponse.write(out,['200', {}, []])
25     assert ! out.closed?
26     assert out.length > 0, "output didn't have data"
27     assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/).size
28   end
30   def test_response_OFS_set
31     old_ofs = $,
32     $, = "\f\v"
33     out = StringIO.new
34     HttpResponse.write(out,[200, {"X-k" => "cd","X-y" => "z"}, ["cool"]])
35     assert ! out.closed?
36     resp = out.string
37     assert ! resp.include?("\f\v"), "output didn't use $, ($OFS)"
38     ensure
39       $, = old_ofs
40   end
42   def test_response_200
43     io = StringIO.new
44     HttpResponse.write(io, [200, {}, []])
45     assert ! io.closed?
46     assert io.length > 0, "output didn't have data"
47   end
49   def test_response_with_default_reason
50     code = 400
51     io = StringIO.new
52     HttpResponse.write(io, [code, {}, []])
53     assert ! io.closed?
54     lines = io.string.split(/\r\n/)
55     assert_match(/.* Bad Request$/, lines.first,
56                  "wrong default reason phrase")
57   end
59   def test_rack_multivalue_headers
60     out = StringIO.new
61     HttpResponse.write(out,[200, {"X-Whatever" => "stuff\nbleh"}, []])
62     assert ! out.closed?
63     assert_match(/^X-Whatever: stuff\r\nX-Whatever: bleh\r\n/, out.string)
64   end
66   # Even though Rack explicitly forbids "Status" in the header hash,
67   # some broken clients still rely on it
68   def test_status_header_added
69     out = StringIO.new
70     HttpResponse.write(out,[200, {"X-Whatever" => "stuff"}, []])
71     assert ! out.closed?
72     assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
73   end
75   # we always favor the code returned by the application, since "Status"
76   # in the header hash is not allowed by Rack (but not every app is
77   # fully Rack-compliant).
78   def test_status_header_ignores_app_hash
79     out = StringIO.new
80     header_hash = {"X-Whatever" => "stuff", 'StaTus' => "666" }
81     HttpResponse.write(out,[200, header_hash, []])
82     assert ! out.closed?
83     assert_equal 1, out.string.split(/\r\n/).grep(/^Status: 200 OK/i).size
84     assert_equal 1, out.string.split(/\r\n/).grep(/^Status:/i).size
85   end
87   def test_body_closed
88     expect_body = %w(1 2 3 4).join("\n")
89     body = StringIO.new(expect_body)
90     body.rewind
91     out = StringIO.new
92     HttpResponse.write(out,[200, {}, body])
93     assert ! out.closed?
94     assert body.closed?
95     assert_match(expect_body, out.string.split(/\r\n/).last)
96   end
98   def test_unknown_status_pass_through
99     out = StringIO.new
100     HttpResponse.write(out,["666 I AM THE BEAST", {}, [] ])
101     assert ! out.closed?
102     headers = out.string.split(/\r\n\r\n/).first.split(/\r\n/)
103     assert %r{\AHTTP/\d\.\d 666 I AM THE BEAST\z}.match(headers[0])
104     status = headers.grep(/\AStatus:/i).first
105     assert status
106     assert_equal "Status: 666 I AM THE BEAST", status
107   end