mongrel 1.2.0.pre2-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +55 -0
- data/History.txt +68 -0
- data/LICENSE +55 -0
- data/Manifest.txt +69 -0
- data/README.txt +80 -0
- data/Rakefile +8 -0
- data/TODO +5 -0
- data/bin/mongrel_rails +284 -0
- data/examples/builder.rb +29 -0
- data/examples/camping/README +3 -0
- data/examples/camping/blog.rb +294 -0
- data/examples/camping/tepee.rb +149 -0
- data/examples/httpd.conf +474 -0
- data/examples/mime.yaml +3 -0
- data/examples/mongrel.conf +9 -0
- data/examples/monitrc +57 -0
- data/examples/random_thrash.rb +19 -0
- data/examples/simpletest.rb +52 -0
- data/examples/webrick_compare.rb +20 -0
- data/ext/http11/Http11Service.java +13 -0
- data/ext/http11/ext_help.h +15 -0
- data/ext/http11/extconf.rb +6 -0
- data/ext/http11/http11.c +534 -0
- data/ext/http11/http11_parser.c +1243 -0
- data/ext/http11/http11_parser.h +49 -0
- data/ext/http11/http11_parser.java.rl +159 -0
- data/ext/http11/http11_parser.rl +153 -0
- data/ext/http11/http11_parser_common.rl +54 -0
- data/ext/http11/org/jruby/mongrel/Http11.java +241 -0
- data/ext/http11/org/jruby/mongrel/Http11Parser.java +486 -0
- data/lib/1.8/http11.so +0 -0
- data/lib/1.9/http11.so +0 -0
- data/lib/mongrel.rb +366 -0
- data/lib/mongrel/camping.rb +107 -0
- data/lib/mongrel/cgi.rb +181 -0
- data/lib/mongrel/command.rb +220 -0
- data/lib/mongrel/configurator.rb +388 -0
- data/lib/mongrel/const.rb +110 -0
- data/lib/mongrel/debug.rb +203 -0
- data/lib/mongrel/gems.rb +22 -0
- data/lib/mongrel/handlers.rb +468 -0
- data/lib/mongrel/header_out.rb +28 -0
- data/lib/mongrel/http_request.rb +155 -0
- data/lib/mongrel/http_response.rb +166 -0
- data/lib/mongrel/init.rb +10 -0
- data/lib/mongrel/mime_types.yml +616 -0
- data/lib/mongrel/rails.rb +185 -0
- data/lib/mongrel/stats.rb +89 -0
- data/lib/mongrel/tcphack.rb +18 -0
- data/lib/mongrel/uri_classifier.rb +76 -0
- data/setup.rb +1585 -0
- data/tasks/gem.rake +28 -0
- data/tasks/native.rake +24 -0
- data/tasks/ragel.rake +20 -0
- data/test/mime.yaml +3 -0
- data/test/mongrel.conf +1 -0
- data/test/test_cgi_wrapper.rb +26 -0
- data/test/test_command.rb +86 -0
- data/test/test_conditional.rb +107 -0
- data/test/test_configurator.rb +87 -0
- data/test/test_debug.rb +25 -0
- data/test/test_handlers.rb +135 -0
- data/test/test_http11.rb +156 -0
- data/test/test_redirect_handler.rb +44 -0
- data/test/test_request_progress.rb +99 -0
- data/test/test_response.rb +127 -0
- data/test/test_stats.rb +35 -0
- data/test/test_uriclassifier.rb +261 -0
- data/test/test_ws.rb +117 -0
- data/test/testhelp.rb +71 -0
- data/tools/trickletest.rb +45 -0
- metadata +197 -0
data/test/test_http11.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/testhelp'
|
8
|
+
|
9
|
+
include Mongrel
|
10
|
+
|
11
|
+
class HttpParserTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_parse_simple
|
14
|
+
parser = HttpParser.new
|
15
|
+
req = {}
|
16
|
+
http = "GET / HTTP/1.1\r\n\r\n"
|
17
|
+
nread = parser.execute(req, http, 0)
|
18
|
+
|
19
|
+
assert nread == http.length, "Failed to parse the full HTTP request"
|
20
|
+
assert parser.finished?, "Parser didn't finish"
|
21
|
+
assert !parser.error?, "Parser had error"
|
22
|
+
assert nread == parser.nread, "Number read returned from execute does not match"
|
23
|
+
|
24
|
+
assert_equal 'HTTP/1.1', req['SERVER_PROTOCOL']
|
25
|
+
assert_equal '/', req['REQUEST_PATH']
|
26
|
+
assert_equal 'HTTP/1.1', req['HTTP_VERSION']
|
27
|
+
assert_equal '/', req['REQUEST_URI']
|
28
|
+
assert_equal 'CGI/1.2', req['GATEWAY_INTERFACE']
|
29
|
+
assert_equal 'GET', req['REQUEST_METHOD']
|
30
|
+
assert_nil req['FRAGMENT']
|
31
|
+
assert_nil req['QUERY_STRING']
|
32
|
+
|
33
|
+
parser.reset
|
34
|
+
assert parser.nread == 0, "Number read after reset should be 0"
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_parse_dumbfuck_headers
|
38
|
+
parser = HttpParser.new
|
39
|
+
req = {}
|
40
|
+
should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
|
41
|
+
nread = parser.execute(req, should_be_good, 0)
|
42
|
+
assert_equal should_be_good.length, nread
|
43
|
+
assert parser.finished?
|
44
|
+
assert !parser.error?
|
45
|
+
|
46
|
+
nasty_pound_header = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n"
|
47
|
+
parser = HttpParser.new
|
48
|
+
req = {}
|
49
|
+
#nread = parser.execute(req, nasty_pound_header, 0)
|
50
|
+
#assert_equal nasty_pound_header.length, nread
|
51
|
+
#assert parser.finished?
|
52
|
+
#assert !parser.error?
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_parse_error
|
56
|
+
parser = HttpParser.new
|
57
|
+
req = {}
|
58
|
+
bad_http = "GET / SsUTF/1.1"
|
59
|
+
|
60
|
+
error = false
|
61
|
+
begin
|
62
|
+
nread = parser.execute(req, bad_http, 0)
|
63
|
+
rescue => details
|
64
|
+
error = true
|
65
|
+
end
|
66
|
+
|
67
|
+
assert error, "failed to throw exception"
|
68
|
+
assert !parser.finished?, "Parser shouldn't be finished"
|
69
|
+
assert parser.error?, "Parser SHOULD have error"
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_fragment_in_uri
|
73
|
+
parser = HttpParser.new
|
74
|
+
req = {}
|
75
|
+
get = "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
|
76
|
+
assert_nothing_raised do
|
77
|
+
parser.execute(req, get, 0)
|
78
|
+
end
|
79
|
+
assert parser.finished?
|
80
|
+
assert_equal '/forums/1/topics/2375?page=1', req['REQUEST_URI']
|
81
|
+
assert_equal 'posts-17408', req['FRAGMENT']
|
82
|
+
end
|
83
|
+
|
84
|
+
# lame random garbage maker
|
85
|
+
def rand_data(min, max, readable=true)
|
86
|
+
count = min + ((rand(max)+1) *10).to_i
|
87
|
+
res = count.to_s + "/"
|
88
|
+
|
89
|
+
if readable
|
90
|
+
res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
|
91
|
+
else
|
92
|
+
res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20)
|
93
|
+
end
|
94
|
+
|
95
|
+
return res
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def test_horrible_queries
|
100
|
+
parser = HttpParser.new
|
101
|
+
|
102
|
+
# then that large header names are caught
|
103
|
+
10.times do |c|
|
104
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
|
105
|
+
assert_raises Mongrel::HttpParserError do
|
106
|
+
parser.execute({}, get, 0)
|
107
|
+
parser.reset
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# then that large mangled field values are caught
|
112
|
+
10.times do |c|
|
113
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
114
|
+
assert_raises Mongrel::HttpParserError do
|
115
|
+
parser.execute({}, get, 0)
|
116
|
+
parser.reset
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# then large headers are rejected too
|
121
|
+
get = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
|
122
|
+
get << "X-Test: test\r\n" * (80 * 1024)
|
123
|
+
assert_raises Mongrel::HttpParserError do
|
124
|
+
parser.execute({}, get, 0)
|
125
|
+
parser.reset
|
126
|
+
end
|
127
|
+
|
128
|
+
# finally just that random garbage gets blocked all the time
|
129
|
+
10.times do |c|
|
130
|
+
get = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
|
131
|
+
assert_raises Mongrel::HttpParserError do
|
132
|
+
parser.execute({}, get, 0)
|
133
|
+
parser.reset
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
def test_query_parse
|
142
|
+
res = HttpRequest.query_parse("zed=1&frank=#{HttpRequest.escape('&&& ')}")
|
143
|
+
assert res["zed"], "didn't get the request right"
|
144
|
+
assert res["frank"], "no frank"
|
145
|
+
assert_equal "1", res["zed"], "wrong result"
|
146
|
+
assert_equal "&&& ", HttpRequest.unescape(res["frank"]), "wrong result"
|
147
|
+
|
148
|
+
res = HttpRequest.query_parse("zed=1&zed=2&zed=3&frank=11;zed=45")
|
149
|
+
assert res["zed"], "didn't get the request right"
|
150
|
+
assert res["frank"], "no frank"
|
151
|
+
assert_equal 4,res["zed"].length, "wrong number for zed"
|
152
|
+
assert_equal "11",res["frank"], "wrong number for frank"
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/testhelp'
|
8
|
+
|
9
|
+
class RedirectHandlerTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
redirect_test_io do
|
13
|
+
@server = Mongrel::HttpServer.new('127.0.0.1', 9998)
|
14
|
+
end
|
15
|
+
@server.run
|
16
|
+
@client = Net::HTTP.new('127.0.0.1', 9998)
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
@server.stop(true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_simple_redirect
|
24
|
+
tester = Mongrel::RedirectHandler.new('/yo')
|
25
|
+
@server.register("/test", tester)
|
26
|
+
|
27
|
+
sleep(1)
|
28
|
+
res = @client.request_get('/test')
|
29
|
+
assert res != nil, "Didn't get a response"
|
30
|
+
assert_equal ['/yo'], res.get_fields('Location')
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_rewrite
|
34
|
+
tester = Mongrel::RedirectHandler.new(/(\w+)/, '+\1+')
|
35
|
+
@server.register("/test", tester)
|
36
|
+
|
37
|
+
sleep(1)
|
38
|
+
res = @client.request_get('/test/something')
|
39
|
+
assert_equal ['/+test+/+something+'], res.get_fields('Location')
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/testhelp'
|
8
|
+
|
9
|
+
class UploadBeginHandler < Mongrel::HttpHandler
|
10
|
+
attr_reader :request_began, :request_progressed, :request_processed
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@request_notify = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@request_began = false
|
18
|
+
@request_progressed = false
|
19
|
+
@request_processed = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def request_begins(params)
|
23
|
+
@request_began = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def request_progress(params,len,total)
|
27
|
+
@request_progressed = true
|
28
|
+
end
|
29
|
+
|
30
|
+
def process(request, response)
|
31
|
+
@request_processed = true
|
32
|
+
response.start do |head,body|
|
33
|
+
body.write("test")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
class RequestProgressTest < Test::Unit::TestCase
|
40
|
+
def setup
|
41
|
+
redirect_test_io do
|
42
|
+
@server = Mongrel::HttpServer.new("127.0.0.1", 9998)
|
43
|
+
end
|
44
|
+
@handler = UploadBeginHandler.new
|
45
|
+
@server.register("/upload", @handler)
|
46
|
+
@server.run
|
47
|
+
end
|
48
|
+
|
49
|
+
def teardown
|
50
|
+
@server.stop(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_begin_end_progress
|
54
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
55
|
+
assert @handler.request_began
|
56
|
+
assert @handler.request_progressed
|
57
|
+
assert @handler.request_processed
|
58
|
+
end
|
59
|
+
|
60
|
+
def call_and_assert_handlers_in_turn(handlers)
|
61
|
+
# reset all handlers
|
62
|
+
handlers.each { |h| h.reset }
|
63
|
+
|
64
|
+
# make the call
|
65
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
66
|
+
|
67
|
+
# assert that each one was fired
|
68
|
+
handlers.each { |h|
|
69
|
+
assert h.request_began && h.request_progressed && h.request_processed,
|
70
|
+
"Callbacks NOT fired for #{h}"
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_more_than_one_begin_end_progress
|
75
|
+
handlers = [@handler]
|
76
|
+
|
77
|
+
second = UploadBeginHandler.new
|
78
|
+
@server.register("/upload", second)
|
79
|
+
handlers << second
|
80
|
+
call_and_assert_handlers_in_turn(handlers)
|
81
|
+
|
82
|
+
# check three handlers
|
83
|
+
third = UploadBeginHandler.new
|
84
|
+
@server.register("/upload", third)
|
85
|
+
handlers << third
|
86
|
+
call_and_assert_handlers_in_turn(handlers)
|
87
|
+
|
88
|
+
# remove handlers to make sure they've all gone away
|
89
|
+
@server.unregister("/upload")
|
90
|
+
handlers.each { |h| h.reset }
|
91
|
+
Net::HTTP.get("localhost", "/upload", 9998)
|
92
|
+
handlers.each { |h|
|
93
|
+
assert !h.request_began && !h.request_progressed && !h.request_processed
|
94
|
+
}
|
95
|
+
|
96
|
+
# re-register upload to the state before this test
|
97
|
+
@server.register("/upload", @handler)
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/testhelp'
|
8
|
+
|
9
|
+
include Mongrel
|
10
|
+
|
11
|
+
class ResponseTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_response_headers
|
14
|
+
out = StringIO.new
|
15
|
+
resp = HttpResponse.new(out)
|
16
|
+
resp.status = 200
|
17
|
+
resp.header["Accept"] = "text/plain"
|
18
|
+
resp.header["X-Whatever"] = "stuff"
|
19
|
+
resp.body.write("test")
|
20
|
+
resp.finished
|
21
|
+
|
22
|
+
assert out.length > 0, "output didn't have data"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_response_200
|
26
|
+
io = StringIO.new
|
27
|
+
resp = HttpResponse.new(io)
|
28
|
+
resp.start do |head,out|
|
29
|
+
head["Accept"] = "text/plain"
|
30
|
+
out.write("tested")
|
31
|
+
out.write("hello!")
|
32
|
+
end
|
33
|
+
|
34
|
+
resp.finished
|
35
|
+
assert io.length > 0, "output didn't have data"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_response_duplicate_header_squash
|
39
|
+
io = StringIO.new
|
40
|
+
resp = HttpResponse.new(io)
|
41
|
+
resp.start do |head,out|
|
42
|
+
head["Content-Length"] = 30
|
43
|
+
head["Content-Length"] = 0
|
44
|
+
end
|
45
|
+
|
46
|
+
resp.finished
|
47
|
+
|
48
|
+
assert_equal io.length, 95, "too much output"
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def test_response_some_duplicates_allowed
|
53
|
+
allowed_duplicates = ["Set-Cookie", "Set-Cookie2", "Warning", "WWW-Authenticate"]
|
54
|
+
io = StringIO.new
|
55
|
+
resp = HttpResponse.new(io)
|
56
|
+
resp.start do |head,out|
|
57
|
+
allowed_duplicates.each do |dup|
|
58
|
+
10.times do |i|
|
59
|
+
head[dup] = i
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
resp.finished
|
65
|
+
|
66
|
+
assert_equal io.length, 734, "wrong amount of output"
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_response_404
|
70
|
+
io = StringIO.new
|
71
|
+
|
72
|
+
resp = HttpResponse.new(io)
|
73
|
+
resp.start(404) do |head,out|
|
74
|
+
head['Accept'] = "text/plain"
|
75
|
+
out.write("NOT FOUND")
|
76
|
+
end
|
77
|
+
|
78
|
+
resp.finished
|
79
|
+
assert io.length > 0, "output didn't have data"
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_response_file
|
83
|
+
contents = "PLAIN TEXT\r\nCONTENTS\r\n"
|
84
|
+
require 'tempfile'
|
85
|
+
tmpf = Tempfile.new("test_response_file")
|
86
|
+
tmpf.binmode
|
87
|
+
tmpf.write(contents)
|
88
|
+
tmpf.rewind
|
89
|
+
|
90
|
+
io = StringIO.new
|
91
|
+
resp = HttpResponse.new(io)
|
92
|
+
resp.start(200) do |head,out|
|
93
|
+
head['Content-Type'] = 'text/plain'
|
94
|
+
resp.send_header
|
95
|
+
resp.send_file(tmpf.path)
|
96
|
+
end
|
97
|
+
io.rewind
|
98
|
+
tmpf.close
|
99
|
+
|
100
|
+
assert io.length > 0, "output didn't have data"
|
101
|
+
assert io.read[-contents.length..-1] == contents, "output doesn't end with file payload"
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_response_with_custom_reason
|
105
|
+
reason = "You made a bad request"
|
106
|
+
io = StringIO.new
|
107
|
+
resp = HttpResponse.new(io)
|
108
|
+
resp.start(400, false, reason) { |head,out| }
|
109
|
+
resp.finished
|
110
|
+
|
111
|
+
io.rewind
|
112
|
+
assert_match(/.* #{reason}$/, io.readline.chomp, "wrong custom reason phrase")
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_response_with_default_reason
|
116
|
+
code = 400
|
117
|
+
io = StringIO.new
|
118
|
+
resp = HttpResponse.new(io)
|
119
|
+
resp.start(code) { |head,out| }
|
120
|
+
resp.finished
|
121
|
+
|
122
|
+
io.rewind
|
123
|
+
assert_match(/.* #{HTTP_STATUS_CODES[code]}$/, io.readline.chomp, "wrong default reason phrase")
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
data/test/test_stats.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# You can redistribute it and/or modify it under the same terms as Ruby.
|
3
|
+
#
|
4
|
+
# Additional work donated by contributors. See http://mongrel.rubyforge.org/attributions.html
|
5
|
+
# for more information.
|
6
|
+
|
7
|
+
require 'test/testhelp'
|
8
|
+
|
9
|
+
class StatsTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def test_sampling_speed
|
12
|
+
out = StringIO.new
|
13
|
+
|
14
|
+
s = Mongrel::Stats.new("test")
|
15
|
+
t = Mongrel::Stats.new("time")
|
16
|
+
|
17
|
+
100.times { s.sample(rand(20)); t.tick }
|
18
|
+
|
19
|
+
s.dump("FIRST", out)
|
20
|
+
t.dump("FIRST", out)
|
21
|
+
|
22
|
+
old_mean = s.mean
|
23
|
+
old_sd = s.sd
|
24
|
+
|
25
|
+
s.reset
|
26
|
+
t.reset
|
27
|
+
100.times { s.sample(rand(30)); t.tick }
|
28
|
+
|
29
|
+
s.dump("SECOND", out)
|
30
|
+
t.dump("SECOND", out)
|
31
|
+
assert_not_equal old_mean, s.mean
|
32
|
+
assert_not_equal old_mean, s.sd
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|