about summary refs log tree commit homepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/exec/test_exec.rb22
-rw-r--r--test/test_helper.rb13
-rw-r--r--test/unit/test_http_parser.rb3
-rw-r--r--test/unit/test_request.rb82
-rw-r--r--test/unit/test_response.rb7
-rw-r--r--test/unit/test_upload.rb28
6 files changed, 149 insertions, 6 deletions
diff --git a/test/exec/test_exec.rb b/test/exec/test_exec.rb
index 712037c..ea9fc7c 100644
--- a/test/exec/test_exec.rb
+++ b/test/exec/test_exec.rb
@@ -283,6 +283,7 @@ end
     results = retry_hit(["http://#{@addr}:#{@port}/"])
     assert_equal String, results[0].class
     wait_master_ready(COMMON_TMP.path)
+    wait_workers_ready(COMMON_TMP.path, 4)
     bf = File.readlines(COMMON_TMP.path).grep(/\bbefore_fork: worker=/)
     assert_equal 4, bf.size
     rotate = Tempfile.new('unicorn_rotate')
@@ -299,7 +300,7 @@ end
       sleep DEFAULT_RES
       log = File.readlines(rotate.path)
     end
-    assert_equal 4, log.grep(/rotating logs\.\.\./).size
+    assert_equal 4, log.grep(/worker=\d+ rotating logs\.\.\./).size
     assert_equal 0, log.grep(/done rotating logs/).size
 
     tries = DEFAULT_TRIES
@@ -308,7 +309,7 @@ end
       sleep DEFAULT_RES
       log = File.readlines(COMMON_TMP.path)
     end
-    assert_equal 4, log.grep(/done rotating logs/).size
+    assert_equal 4, log.grep(/worker=\d+ done rotating logs/).size
     assert_equal 0, log.grep(/rotating logs\.\.\./).size
     assert_nothing_raised { Process.kill('QUIT', pid) }
     status = nil
@@ -496,6 +497,21 @@ end
       assert status.success?, "exited successfully"
     end
 
+    def wait_workers_ready(path, nr_workers)
+      tries = DEFAULT_TRIES
+      lines = []
+      while (tries -= 1) > 0
+        begin
+          lines = File.readlines(path).grep(/worker=\d+ spawned/)
+          lines.size == nr_workers and return
+        rescue Errno::ENOENT
+        end
+        sleep DEFAULT_RES
+      end
+      raise "#{nr_workers} workers never became ready:" \
+            "\n\t#{lines.join("\n\t")}\n"
+    end
+
     def wait_master_ready(master_log)
       tries = DEFAULT_TRIES
       while (tries -= 1) > 0
@@ -555,7 +571,7 @@ end
       while (tries -= 1) > 0 && ! File.exist?(path)
         sleep DEFAULT_RES
       end
-      assert File.exist?(path), "path=#{path} exists"
+      assert File.exist?(path), "path=#{path} exists #{caller.inspect}"
     end
 
     def xfork(&block)
diff --git a/test/test_helper.rb b/test/test_helper.rb
index f809af3..4243606 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -41,7 +41,18 @@ def redirect_test_io
     STDOUT.reopen(orig_out)
   end
 end
-    
+
+# which(1) exit codes cannot be trusted on some systems
+# We use UNIX shell utilities in some tests because we don't trust
+# ourselves to write Ruby 100% correctly :)
+def which(bin)
+  ex = ENV['PATH'].split(/:/).detect do |x|
+    x << "/#{bin}"
+    File.executable?(x)
+  end or warn "`#{bin}' not found in PATH=#{ENV['PATH']}"
+  ex
+end
+
 # Either takes a string to do a get request against, or a tuple of [URI, HTTP] where
 # HTTP is some kind of Net::HTTP request object (POST, HEAD, etc.)
 def hit(uris)
diff --git a/test/unit/test_http_parser.rb b/test/unit/test_http_parser.rb
index ca1cd01..fc75990 100644
--- a/test/unit/test_http_parser.rb
+++ b/test/unit/test_http_parser.rb
@@ -25,11 +25,10 @@ class HttpParserTest < Test::Unit::TestCase
     assert_equal '/', req['REQUEST_PATH']
     assert_equal 'HTTP/1.1', req['HTTP_VERSION']
     assert_equal '/', req['REQUEST_URI']
-    assert_equal 'CGI/1.2', req['GATEWAY_INTERFACE']
     assert_equal 'GET', req['REQUEST_METHOD']    
     assert_nil req['FRAGMENT']
     assert_nil req['QUERY_STRING']
-    
+
     parser.reset
     assert parser.nread == 0, "Number read after reset should be 0"
   end
diff --git a/test/unit/test_request.rb b/test/unit/test_request.rb
new file mode 100644
index 0000000..37fbb14
--- /dev/null
+++ b/test/unit/test_request.rb
@@ -0,0 +1,82 @@
+# Copyright (c) 2009 Eric Wong
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+if RUBY_VERSION =~ /1\.9/
+  warn "#$0 current broken under Ruby 1.9 with Rack"
+  exit 0
+end
+
+require 'test/test_helper'
+begin
+  require 'rack'
+  require 'rack/lint'
+rescue LoadError
+  warn "Unable to load rack, skipping test"
+  exit 0
+end
+
+include Unicorn
+
+class RequestTest < Test::Unit::TestCase
+
+  class MockRequest < StringIO
+    def unicorn_peeraddr
+      '666.666.666.666'
+    end
+  end
+
+  def setup
+    @request = HttpRequest.new(Logger.new($stderr))
+    @app = lambda do |env|
+      [ 200, { 'Content-Length' => '0', 'Content-Type' => 'text/plain' }, [] ]
+    end
+    @lint = Rack::Lint.new(@app)
+  end
+
+  def test_rack_lint_get
+    client = MockRequest.new("GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
+    res = env = nil
+    assert_nothing_raised { env = @request.read(client) }
+    assert_equal '666.666.666.666', env['REMOTE_ADDR']
+    assert_nothing_raised { res = @lint.call(env) }
+  end
+
+  def test_rack_lint_put
+    client = MockRequest.new(
+      "PUT / HTTP/1.1\r\n" \
+      "Host: foo\r\n" \
+      "Content-Length: 5\r\n" \
+      "\r\n" \
+      "abcde")
+    res = env = nil
+    assert_nothing_raised { env = @request.read(client) }
+    assert_nothing_raised { res = @lint.call(env) }
+  end
+
+  def test_rack_lint_big_put
+    count = 100
+    bs = 0x10000
+    buf = (' ' * bs).freeze
+    length = bs * count
+    client = Tempfile.new('big_put')
+    def client.unicorn_peeraddr
+      '1.1.1.1'
+    end
+    client.syswrite(
+      "PUT / HTTP/1.1\r\n" \
+      "Host: foo\r\n" \
+      "Content-Length: #{length}\r\n" \
+      "\r\n")
+    count.times { assert_equal bs, client.syswrite(buf) }
+    assert_equal 0, client.sysseek(0)
+    res = env = nil
+    assert_nothing_raised { env = @request.read(client) }
+    assert_equal length, env['rack.input'].size
+    count.times { assert_equal buf, env['rack.input'].read(bs) }
+    assert_nil env['rack.input'].read(bs)
+    assert_nothing_raised { env['rack.input'].rewind }
+    assert_nothing_raised { res = @lint.call(env) }
+  end
+
+end
+
diff --git a/test/unit/test_response.rb b/test/unit/test_response.rb
index c30a141..4c7423b 100644
--- a/test/unit/test_response.rb
+++ b/test/unit/test_response.rb
@@ -41,5 +41,12 @@ class ResponseTest < Test::Unit::TestCase
     io.rewind
     assert_match(/.* #{HTTP_STATUS_CODES[code]}$/, io.readline.chomp, "wrong default reason phrase")
   end
+
+  def test_rack_multivalue_headers
+    out = StringIO.new
+    HttpResponse.write(out,[200, {"X-Whatever" => "stuff\nbleh"}, []])
+    assert_match(/^X-Whatever: stuff\r\nX-Whatever: bleh\r\n/, out.string)
+  end
+
 end
 
diff --git a/test/unit/test_upload.rb b/test/unit/test_upload.rb
index edc94da..41fc473 100644
--- a/test/unit/test_upload.rb
+++ b/test/unit/test_upload.rb
@@ -135,6 +135,34 @@ class UploadTest < Test::Unit::TestCase
     assert_equal resp[:size], new_tmp.stat.size
   end
 
+  # Despite reading numerous articles and inspecting the 1.9.1-p0 C
+  # source, Eric Wong will never trust that we're always handling
+  # encoding-aware IO objects correctly.  Thus this test uses shell
+  # utilities that should always operate on files/sockets on a
+  # byte-level.
+  def test_uncomfortable_with_onenine_encodings
+    # POSIX doesn't require all of these to be present on a system
+    which('curl') or return
+    which('sha1sum') or return
+    which('dd') or return
+
+    start_server(@sha1_app)
+
+    tmp = Tempfile.new('dd_dest')
+    assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
+                        "bs=#{@bs}", "count=#{@count}"),
+           "dd #@random to #{tmp}")
+    sha1_re = %r!\b([a-f0-9]{40})\b!
+    sha1_out = `sha1sum #{tmp.path}`
+    assert $?.success?, 'sha1sum ran OK'
+
+    assert_match(sha1_re, sha1_out)
+    sha1 = sha1_re.match(sha1_out)[1]
+    resp = `curl -isSfN -T#{tmp.path} http://#@addr:#@port/`
+    assert $?.success?, 'curl ran OK'
+    assert_match(%r!\b#{sha1}\b!, resp)
+  end
+
   private
 
   def length