about summary refs log tree commit homepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/benchmark/previous.rb11
-rw-r--r--test/benchmark/simple.rb11
-rw-r--r--test/benchmark/utils.rb82
-rw-r--r--test/test_helper.rb (renamed from test/testhelp.rb)17
-rw-r--r--test/tools/trickletest.rb45
-rw-r--r--test/unit/test_cgi_wrapper.rb (renamed from test/test_cgi_wrapper.rb)2
-rw-r--r--test/unit/test_command.rb (renamed from test/test_command.rb)2
-rw-r--r--test/unit/test_conditional.rb (renamed from test/test_conditional.rb)2
-rw-r--r--test/unit/test_configurator.rb (renamed from test/test_configurator.rb)18
-rw-r--r--test/unit/test_debug.rb (renamed from test/test_debug.rb)2
-rw-r--r--test/unit/test_handlers.rb (renamed from test/test_handlers.rb)54
-rw-r--r--test/unit/test_http_parser.rb (renamed from test/test_http11.rb)128
-rw-r--r--test/unit/test_redirect_handler.rb (renamed from test/test_redirect_handler.rb)7
-rw-r--r--test/unit/test_request_progress.rb (renamed from test/test_request_progress.rb)2
-rw-r--r--test/unit/test_response.rb (renamed from test/test_response.rb)2
-rw-r--r--test/unit/test_stats.rb (renamed from test/test_stats.rb)2
-rw-r--r--test/unit/test_uriclassifier.rb (renamed from test/test_uriclassifier.rb)2
-rw-r--r--test/unit/test_ws.rb (renamed from test/test_ws.rb)6
18 files changed, 233 insertions, 162 deletions
diff --git a/test/benchmark/previous.rb b/test/benchmark/previous.rb
new file mode 100644
index 0000000..8b6182a
--- /dev/null
+++ b/test/benchmark/previous.rb
@@ -0,0 +1,11 @@
+# Benchmark to compare Mongrel performance against
+# previous Mongrel version (the one installed as a gem).
+#
+# Run with:
+#
+#  ruby previous.rb [num of request]
+#
+
+require File.dirname(__FILE__) + '/utils'
+
+benchmark "print", %w(current gem), 1000, [1, 10, 100]
diff --git a/test/benchmark/simple.rb b/test/benchmark/simple.rb
new file mode 100644
index 0000000..906f74c
--- /dev/null
+++ b/test/benchmark/simple.rb
@@ -0,0 +1,11 @@
+#
+# Simple benchmark to compare Mongrel performance against
+# other webservers supported by Rack.
+#
+
+require File.dirname(__FILE__) + '/utils'
+
+libs = %w(current gem WEBrick EMongrel Thin)
+libs = ARGV if ARGV.any?
+
+benchmark "print", libs, 1000, [1, 10, 100]
diff --git a/test/benchmark/utils.rb b/test/benchmark/utils.rb
new file mode 100644
index 0000000..feb22c1
--- /dev/null
+++ b/test/benchmark/utils.rb
@@ -0,0 +1,82 @@
+
+require 'rubygems'
+require 'rack'
+require 'rack/lobster'
+
+def run(handler_name, n=1000, c=1)
+  port = 7000
+  
+  server = fork do
+    [STDOUT, STDERR].each { |o| o.reopen "/dev/null" }
+      
+    case handler_name
+    when 'EMongrel'
+      require 'swiftcore/evented_mongrel'
+      handler_name = 'Mongrel'
+    
+    when 'Thin'
+      require 'thin'
+      hander_name = 'Thin'
+    
+    when 'gem' # Load the current Mongrel gem
+      require 'mongrel'
+      handler_name = 'Mongrel'
+    
+    when 'current' # Load the current Mongrel version under /lib
+      require File.dirname(__FILE__) + '/../lib/mongrel'
+      handler_name = 'Mongrel'
+      
+    end
+    
+    app = Rack::Lobster.new
+    
+    handler = Rack::Handler.const_get(handler_name)
+    handler.run app, :Host => '0.0.0.0', :Port => port
+  end
+
+  sleep 2
+
+  out = `nice -n20 ab -c #{c} -n #{n} http://127.0.0.1:#{port}/ 2> /dev/null`
+
+  Process.kill('SIGKILL', server)
+  Process.wait
+  
+  if requests = out.match(/^Requests.+?(\d+\.\d+)/)
+    requests[1].to_i
+  else
+    0
+  end
+end
+
+def benchmark(type, servers, request, concurrency_levels)
+  send "#{type}_benchmark", servers, request, concurrency_levels
+end
+
+def graph_benchmark(servers, request, concurrency_levels)
+  require '/usr/local/lib/ruby/gems/1.8/gems/gruff-0.2.9/lib/gruff'
+  g = Gruff::Area.new
+  g.title = "Server benchmark"
+  
+  servers.each do |server|
+    g.data(server, concurrency_levels.collect { |c| print '.'; run(server, request, c) })
+  end
+  puts
+  
+  g.x_axis_label = 'Concurrency'
+  g.y_axis_label = 'Requests / sec'
+  g.labels = {}
+  concurrency_levels.each_with_index { |c, i| g.labels[i] = c.to_s }
+  
+  g.write('bench.png')
+  `open bench.png`
+end
+
+def print_benchmark(servers, request, concurrency_levels)
+  puts 'server     request   concurrency   req/s'
+  puts '=' * 42
+  concurrency_levels.each do |c|
+    servers.each do |server|
+      puts "#{server.ljust(8)}   #{request}      #{c.to_s.ljust(4)}          #{run(server, request, c)}"
+    end
+  end
+end \ No newline at end of file
diff --git a/test/testhelp.rb b/test/test_helper.rb
index 4fe112d..7615fdd 100644
--- a/test/testhelp.rb
+++ b/test/test_helper.rb
@@ -65,10 +65,15 @@ def hit(uris)
   return results
 end
 
-# process_based_port provides a port number, usable for TCP and UDP
-# connections based on $$ and with a 5000 as base.
-# this is required if you perform several builds of mongrel in parallel
-# (like continuous integration systems)
-def process_based_port
-  5000 + $$ % 1000
+# process_based_port provides a port number, usable for TCP and UDP  
+# connections based on $$ and with a 5000 as base.
+# this is required if you perform several builds of mongrel in parallel
+# (like continuous integration systems)
+def process_based_port
+  5000 + $$ % 1000
+end
+
+# Platform check helper ;-)
+def windows?
+  result = RUBY_PLATFORM =~ /djgpp|(cyg|ms|bcc)win|mingw/
 end \ No newline at end of file
diff --git a/test/tools/trickletest.rb b/test/tools/trickletest.rb
new file mode 100644
index 0000000..e19ed71
--- /dev/null
+++ b/test/tools/trickletest.rb
@@ -0,0 +1,45 @@
+require 'socket'
+require 'stringio'
+
+def do_test(st, chunk)
+  s = TCPSocket.new('127.0.0.1',ARGV[0].to_i);
+  req = StringIO.new(st)
+  nout = 0
+  randstop = rand(st.length / 10)
+  STDERR.puts "stopping after: #{randstop}"
+
+  begin
+    while data = req.read(chunk)
+      nout += s.write(data)
+      s.flush
+      sleep 0.1
+      if nout > randstop
+        STDERR.puts "BANG! after #{nout} bytes."
+        break
+      end
+    end
+  rescue Object => e
+    STDERR.puts "ERROR: #{e}"
+  ensure
+    s.close
+  end
+end
+
+content = "-" * (1024 * 240)
+st = "GET / HTTP/1.1\r\nHost: www.zedshaw.com\r\nContent-Type: text/plain\r\nContent-Length: #{content.length}\r\n\r\n#{content}"
+
+puts "length: #{content.length}"
+
+threads = []
+ARGV[1].to_i.times do
+  t = Thread.new do
+    size = 100
+    puts ">>>> #{size} sized chunks"
+    do_test(st, size)
+  end
+
+  t.abort_on_exception = true
+  threads << t
+end
+
+threads.each {|t|  t.join}
diff --git a/test/test_cgi_wrapper.rb b/test/unit/test_cgi_wrapper.rb
index 449f6d0..a494655 100644
--- a/test/test_cgi_wrapper.rb
+++ b/test/unit/test_cgi_wrapper.rb
@@ -1,5 +1,5 @@
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class MockHttpRequest
   attr_reader :body
diff --git a/test/test_command.rb b/test/unit/test_command.rb
index 3cb9643..2e49ff2 100644
--- a/test/test_command.rb
+++ b/test/unit/test_command.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class TestCommand < GemPlugin::Plugin "/commands"
   include Mongrel::Command::Base
diff --git a/test/test_conditional.rb b/test/unit/test_conditional.rb
index 792a880..64517db 100644
--- a/test/test_conditional.rb
+++ b/test/unit/test_conditional.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 include Mongrel
 
diff --git a/test/test_configurator.rb b/test/unit/test_configurator.rb
index fde2682..dc9713a 100644
--- a/test/test_configurator.rb
+++ b/test/unit/test_configurator.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 $test_plugin_fired = 0
 
@@ -29,12 +29,12 @@ end
 class ConfiguratorTest < Test::Unit::TestCase
 
   def test_base_handler_config
-    port = process_based_port
+    @port = process_based_port
     @config = nil
 
     redirect_test_io do
       @config = Mongrel::Configurator.new :host => "localhost" do
-        listener :port => port do
+        listener :port => process_based_port do
           # 2 in front should run, but the sentinel shouldn't since dirhandler processes the request
           uri "/", :handler => plugin("/handlers/testplugin")
           uri "/", :handler => plugin("/handlers/testplugin")
@@ -49,14 +49,14 @@ class ConfiguratorTest < Test::Unit::TestCase
           debug "/"
           setup_signals
 
-          run_config(File.dirname(__FILE__) + "/../test/mongrel.conf")
-          load_mime_map(File.dirname(__FILE__) + "/../test/mime.yaml")
+          run_config(HERE + "/mongrel.conf")
+          load_mime_map(HERE + "/mime.yaml")
 
           run
         end
       end
     end
-
+    
     # pp @config.listeners.values.first.classifier.routes
 
     @config.listeners.each do |host,listener|
@@ -65,12 +65,12 @@ class ConfiguratorTest < Test::Unit::TestCase
       assert listener.classifier.uris.include?("/test"), "/test not registered"
     end
 
-    res = Net::HTTP.get(URI.parse("http://localhost:#{port}/test"))
+    res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/test"))
     assert res != nil, "Didn't get a response"
     assert $test_plugin_fired == 3, "Test filter plugin didn't run 3 times."
 
     redirect_test_io do
-      res = Net::HTTP.get(URI.parse("http://localhost:#{port}/"))
+      res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/"))
 
       assert res != nil, "Didn't get a response"
       assert $test_plugin_fired == 6, "Test filter plugin didn't run 6 times."
@@ -81,7 +81,7 @@ class ConfiguratorTest < Test::Unit::TestCase
     end
 
     assert_raise Errno::EBADF, Errno::ECONNREFUSED do
-      res = Net::HTTP.get(URI.parse("http://localhost:#{port}/"))
+      res = Net::HTTP.get(URI.parse("http://localhost:#{@port}/"))
     end
   end
 
diff --git a/test/test_debug.rb b/test/unit/test_debug.rb
index 2f7be24..05d92d8 100644
--- a/test/test_debug.rb
+++ b/test/unit/test_debug.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 require 'mongrel/debug'
 
 class MongrelDbgTest < Test::Unit::TestCase
diff --git a/test/test_handlers.rb b/test/unit/test_handlers.rb
index dc7667c..66bf010 100644
--- a/test/test_handlers.rb
+++ b/test/unit/test_handlers.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class SimpleHandler < Mongrel::HttpHandler
   def process(request, response)
@@ -34,11 +34,11 @@ end
 class HandlersTest < Test::Unit::TestCase
 
   def setup
-    stats = Mongrel::StatisticsFilter.new(:sample_rate => 1)
     @port = process_based_port
-    
-    @config = Mongrel::Configurator.new :host => '127.0.0.1', :port => @port do
-      listener do
+    stats = Mongrel::StatisticsFilter.new(:sample_rate => 1)
+
+    @config = Mongrel::Configurator.new :host => '127.0.0.1' do
+      listener :port => process_based_port do
         uri "/", :handler => SimpleHandler.new
         uri "/", :handler => stats
         uri "/404", :handler => Mongrel::Error404Handler.new("Not found")
@@ -50,11 +50,29 @@ class HandlersTest < Test::Unit::TestCase
         uri "/relative", :handler => Mongrel::DirHandler.new(nil, listing_allowed=false, index_html="none")
       end
     end
+    
+    unless windows?
+      File.open('/tmp/testfile', 'w') do
+        # Do nothing
+      end
+    end
+    
     @config.run
   end
 
   def teardown
     @config.stop(false, true)
+    File.delete '/tmp/testfile' unless windows?
+  end
+  
+  def test_registration_exception_is_not_lost
+    assert_raises(Mongrel::URIClassifier::RegistrationError) do      
+      @config = Mongrel::Configurator.new do
+        listener do
+          uri "bogus", :handler => SimpleHandler.new
+        end
+      end
+    end
   end
 
   def test_more_web_server
@@ -67,14 +85,29 @@ class HandlersTest < Test::Unit::TestCase
           "http://localhost:#{@port}/files_nodir/rdoc/",
           "http://localhost:#{@port}/status",
     ])
-
-    # XXX This can't possibly have good coverage.
     check_status res, String
   end
+  
+  def test_nil_dirhandler
+    return if windows?
+    # Camping uses this internally
+    handler = Mongrel::DirHandler.new(nil, false)  
+    assert handler.can_serve("/tmp/testfile")
+    # Not a bug! A nil @file parameter is the only circumstance under which
+    # we are allowed to serve any existing file
+    assert handler.can_serve("../../../../../../../../../../tmp/testfile")
+  end
+  
+  def test_non_nil_dirhandler_is_not_vulnerable_to_path_traversal
+    # The famous security bug of Mongrel 1.1.2
+    handler = Mongrel::DirHandler.new("/doc", false)
+    assert_nil handler.can_serve("/tmp/testfile")
+    assert_nil handler.can_serve("../../../../../../../../../../tmp/testfile")
+  end
 
   def test_deflate
     Net::HTTP.start("localhost", @port) do |h|
-      # test that no accept-encoding returns a non-deflated response
+      # Test that no accept-encoding returns a non-deflated response
       req = h.get("/dumb")
       assert(
         !req['Content-Encoding'] ||
@@ -91,9 +124,9 @@ class HandlersTest < Test::Unit::TestCase
 
   # TODO: find out why this fails on win32 but nowhere else
   #def test_posting_fails_dirhandler
-  #  req = Net::HTTP::Post.new("http://localhost:9998/files/rdoc/")
+  #  req = Net::HTTP::Post.new("http://localhost:#{@port}/files/rdoc/")
   #  req.set_form_data({'from'=>'2005-01-01', 'to'=>'2005-03-31'}, ';')
-  #  res = hit [["http://localhost:9998/files/rdoc/",req]]
+  #  res = hit [["http://localhost:#{@port}/files/rdoc/",req]]
   #  check_status res, Net::HTTPNotFound
   #end
 
@@ -101,4 +134,3 @@ class HandlersTest < Test::Unit::TestCase
     @config.listeners["127.0.0.1:#{@port}"].unregister("/")
   end
 end
-
diff --git a/test/test_http11.rb b/test/unit/test_http_parser.rb
index 64fe19b..d8f3fe8 100644
--- a/test/test_http11.rb
+++ b/test/unit/test_http_parser.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 include Mongrel
 
@@ -34,7 +34,7 @@ class HttpParserTest < Test::Unit::TestCase
     assert parser.nread == 0, "Number read after reset should be 0"
   end
 
-  def test_parse_dumbfuck_headers
+  def test_parse_strange_headers
     parser = HttpParser.new
     req = {}
     should_be_good = "GET / HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
@@ -42,33 +42,14 @@ class HttpParserTest < Test::Unit::TestCase
     assert_equal should_be_good.length, nread
     assert parser.finished?
     assert !parser.error?
-    assert_equal "++++++++++", req["HTTP_AAAAAAAAAAAAA"]
 
     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"
     parser = HttpParser.new
     req = {}
-    #nread = parser.execute(req, nasty_pound_header, 0)
-    #assert_equal nasty_pound_header.length, nread
-    #assert parser.finished?
-    #assert !parser.error?
-  end
-
-  def test_parse_ie6_urls
-    %w(/some/random/path"
-       /some/random/path>
-       /some/random/path<
-       /we/love/you/ie6?q=<"">
-       /url?<="&>="
-       /mal"formed"?
-    ).each do |path|
-      parser = HttpParser.new
-      req = {}
-      sorta_safe = %(GET #{path} HTTP/1.1\r\n\r\n)
-      nread = parser.execute(req, sorta_safe, 0)
-      assert_equal sorta_safe.length, nread
-      assert parser.finished?
-      assert !parser.error?
-    end
+    nread = parser.execute(req, nasty_pound_header, 0)
+    assert_equal nasty_pound_header.length, nread
+    assert parser.finished?
+    assert !parser.error?
   end
   
   def test_parse_error
@@ -88,103 +69,6 @@ class HttpParserTest < Test::Unit::TestCase
     assert parser.error?, "Parser SHOULD have error"
   end
 
-  def test_parse_like_optimized_header
-    parser = HttpParser.new
-    req = {}
-    should_be_good = "GET / HTTP/1.1\r\nAuthorizationn: zz\r\n\r\n"
-    nread = parser.execute(req, should_be_good, 0)
-    assert_equal should_be_good.length, nread
-    assert parser.finished?
-    assert !parser.error?
-    assert_equal "zz", req["HTTP_AUTHORIZATIONN"]
-    assert ! req["HTTP_AUTHORIZATION"]
-  end
-
-  def test_parse_twin_lookalike_optimized_headers
-    parser = HttpParser.new
-    req = {}
-    should_be_good = "GET / HTTP/1.1\r\n" \
-                     "Accept-Encoding: abcdef\r\n" \
-                     "Accept-Language: zyxvut\r\n" \
-                     "\r\n"
-    nread = parser.execute(req, should_be_good, 0)
-    assert_equal should_be_good.length, nread
-    assert parser.finished?
-    assert !parser.error?
-    assert_equal "abcdef", req["HTTP_ACCEPT_ENCODING"]
-    assert_equal "zyxvut", req["HTTP_ACCEPT_LANGUAGE"]
-  end
-
-  if RUBY_PLATFORM !~ /java/
-    # as of now, the Java version does not have the same global-object
-    # reuse optimization the C version does
-
-    def test_parse_optimized_headers_global_objects_used
-      parser = HttpParser.new
-      req = {}
-      should_be_good = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
-      nread = parser.execute(req, should_be_good, 0)
-      assert_equal should_be_good.length, nread
-      assert parser.finished?
-      assert !parser.error?
-      assert_equal "example.com", req["HTTP_HOST"]
-
-      frozen_host_a = nil
-      req.each { |k,v| k == "HTTP_HOST" && frozen_host_a = k }
-
-      parser = HttpParser.new
-      req = {}
-      should_be_good = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
-      nread = parser.execute(req, should_be_good, 0)
-      assert_equal should_be_good.length, nread
-      assert parser.finished?
-      assert !parser.error?
-
-      frozen_host_b = nil
-      req.each { |k,v| k == "HTTP_HOST" && frozen_host_b = k }
-      assert_equal "HTTP_HOST", frozen_host_a
-      assert_equal "HTTP_HOST", frozen_host_b
-      assert_equal frozen_host_a.object_id, frozen_host_b.object_id
-    end
-  end
-
-  def test_host_port_parsing
-    parser = HttpParser.new
-    req = {}
-    should_be_good = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
-    nread = parser.execute(req, should_be_good, 0)
-    assert_equal should_be_good.length, nread
-    assert parser.finished?
-    assert !parser.error?
-    assert_equal "example.com", req["HTTP_HOST"]
-    assert_equal "example.com", req["SERVER_NAME"]
-    assert_equal "80", req["SERVER_PORT"]
-
-    parser = HttpParser.new
-    req = {}
-    should_be_good = "GET / HTTP/1.1\r\nHost: example.com:123\r\n\r\n"
-    nread = parser.execute(req, should_be_good, 0)
-    assert_equal should_be_good.length, nread
-    assert parser.finished?
-    assert !parser.error?
-    assert_equal "example.com:123", req["HTTP_HOST"]
-    assert_equal "example.com", req["SERVER_NAME"]
-    assert_equal "123", req["SERVER_PORT"]
-
-    # null character in domain name is never actually valid, but if it
-    # becomes valid in Web 3.0, we'll be ready for it.
-    parser = HttpParser.new
-    req = {}
-    should_be_good = "GET / HTTP/1.1\r\nHost: example.com\0:123\r\n\r\n"
-    nread = parser.execute(req, should_be_good, 0)
-    assert_equal should_be_good.length, nread
-    assert parser.finished?
-    assert !parser.error?
-    assert_equal "example.com\0:123", req["HTTP_HOST"]
-    assert_equal "example.com\0", req["SERVER_NAME"]
-    assert_equal "123", req["SERVER_PORT"]
-  end
-
   def test_fragment_in_uri
     parser = HttpParser.new
     req = {}
diff --git a/test/test_redirect_handler.rb b/test/unit/test_redirect_handler.rb
index a4c5056..e990427 100644
--- a/test/test_redirect_handler.rb
+++ b/test/unit/test_redirect_handler.rb
@@ -4,16 +4,17 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class RedirectHandlerTest < Test::Unit::TestCase
 
   def setup
+    @port = process_based_port
     redirect_test_io do
-      @server = Mongrel::HttpServer.new('127.0.0.1', process_based_port)
+      @server = Mongrel::HttpServer.new('127.0.0.1', @port)
     end
     @server.run
-    @client = Net::HTTP.new('127.0.0.1', process_based_port)
+    @client = Net::HTTP.new('127.0.0.1', @port)
   end
 
   def teardown
diff --git a/test/test_request_progress.rb b/test/unit/test_request_progress.rb
index 4be9d16..a100426 100644
--- a/test/test_request_progress.rb
+++ b/test/unit/test_request_progress.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class UploadBeginHandler < Mongrel::HttpHandler
   attr_reader :request_began, :request_progressed, :request_processed
diff --git a/test/test_response.rb b/test/unit/test_response.rb
index 123ed98..b49c9df 100644
--- a/test/test_response.rb
+++ b/test/unit/test_response.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 include Mongrel
 
diff --git a/test/test_stats.rb b/test/unit/test_stats.rb
index 404870a..012c6a5 100644
--- a/test/test_stats.rb
+++ b/test/unit/test_stats.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 class StatsTest < Test::Unit::TestCase
 
diff --git a/test/test_uriclassifier.rb b/test/unit/test_uriclassifier.rb
index 28af72c..a438065 100644
--- a/test/test_uriclassifier.rb
+++ b/test/unit/test_uriclassifier.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 include Mongrel
 
diff --git a/test/test_ws.rb b/test/unit/test_ws.rb
index 237aa54..9de8a45 100644
--- a/test/test_ws.rb
+++ b/test/unit/test_ws.rb
@@ -4,7 +4,7 @@
 # Additional work donated by contributors.  See http://mongrel.rubyforge.org/attributions.html
 # for more information.
 
-require 'test/testhelp'
+require 'test/test_helper'
 
 include Mongrel
 
@@ -21,8 +21,8 @@ end
 class WebServerTest < Test::Unit::TestCase
 
   def setup
-    @port = process_based_port
     @valid_request = "GET / HTTP/1.1\r\nHost: www.zedshaw.com\r\nContent-Type: text/plain\r\n\r\n"
+    @port = process_based_port
     
     redirect_test_io do
       # We set num_processors=1 so that we can test the reaping code
@@ -95,7 +95,7 @@ class WebServerTest < Test::Unit::TestCase
 
   def test_num_processors_overload
     redirect_test_io do
-      assert_raises Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EINVAL do
+      assert_raises Errno::ECONNRESET, Errno::EPIPE, Errno::ECONNABORTED, Errno::EINVAL, IOError do
         tests = [
           Thread.new { do_test(@valid_request, 1) },
           Thread.new { do_test(@valid_request, 10) },