about summary refs log tree commit homepage
path: root/test/rails/test_rails.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/rails/test_rails.rb')
-rw-r--r--test/rails/test_rails.rb247
1 files changed, 247 insertions, 0 deletions
diff --git a/test/rails/test_rails.rb b/test/rails/test_rails.rb
new file mode 100644
index 0000000..c7add20
--- /dev/null
+++ b/test/rails/test_rails.rb
@@ -0,0 +1,247 @@
+# Copyright (c) 2009 Eric Wong
+require 'test/test_helper'
+
+# don't call exit(0) since it may be run under rake (but gmake is recommended)
+do_test = true
+
+$unicorn_rails_bin = ENV['UNICORN_RAILS_TEST_BIN'] || "unicorn_rails"
+redirect_test_io { do_test = system($unicorn_rails_bin, '-v') }
+
+unless do_test
+  warn "#$unicorn_rails_bin not found in PATH=#{ENV['PATH']}, " \
+       "skipping this test"
+end
+
+unless which('git')
+  warn "git not found in PATH=#{ENV['PATH']}, skipping this test"
+  do_test = false
+end
+
+if RAILS_GIT_REPO = ENV['RAILS_GIT_REPO']
+  unless File.directory?(RAILS_GIT_REPO)
+    warn "#{RAILS_GIT_REPO} not found, create it with:\n" \
+         "\tgit clone --mirror git://github.com/rails/rails #{RAILS_GIT_REPO}" \
+         "skipping this test for now"
+    do_test = false
+  end
+else
+  warn "RAILS_GIT_REPO not defined, don't know where to git clone from"
+  do_test = false
+end
+
+unless UNICORN_RAILS_TEST_VERSION = ENV['UNICORN_RAILS_TEST_VERSION']
+  warn 'UNICORN_RAILS_TEST_VERSION not defined in environment, ' \
+       'skipping this test'
+  do_test = false
+end
+
+RAILS_ROOT = "#{File.dirname(__FILE__)}/app-#{UNICORN_RAILS_TEST_VERSION}"
+unless File.directory?(RAILS_ROOT)
+  warn "unsupported UNICORN_RAILS_TEST_VERSION=#{UNICORN_RAILS_TEST_VERSION}"
+  do_test = false
+end
+
+ROR_V = UNICORN_RAILS_TEST_VERSION.split(/\./).map { |x| x.to_i }
+RB_V = RUBY_VERSION.split(/\./).map { |x| x.to_i }
+if RB_V[0] >= 1 && RB_V[1] >= 9
+  unless ROR_V[0] >= 2 && ROR_V[1] >= 3
+    warn "skipping Ruby >=1.9 test with Rails <2.3"
+    do_test = false
+  end
+end
+
+class RailsTest < Test::Unit::TestCase
+  trap(:QUIT, 'IGNORE')
+
+  COMMON_TMP = Tempfile.new('unicorn_tmp') unless defined?(COMMON_TMP)
+
+  HEAVY_CFG = <<-EOS
+worker_processes 2
+timeout 30
+logger Logger.new('#{COMMON_TMP.path}')
+  EOS
+
+  def setup
+    @pwd = Dir.pwd
+    @tmpfile = Tempfile.new('unicorn_rails_test')
+    @tmpdir = @tmpfile.path
+    @tmpfile.close!
+    assert_nothing_raised do
+      FileUtils.cp_r(RAILS_ROOT, @tmpdir, :preserve => true)
+    end
+    Dir.chdir(@tmpdir)
+    system('git', 'clone', '-nsq', RAILS_GIT_REPO, 'vendor/rails')
+    Dir.chdir("#@tmpdir/vendor/rails") do
+      system('git', 'reset', '-q', '--hard', "v#{UNICORN_RAILS_TEST_VERSION}")
+    end
+
+    assert(system('rake', 'db:sessions:create'))
+    assert(system('rake', 'db:migrate'))
+
+    @addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
+    @port = unused_port(@addr)
+    @start_pid = $$
+    @pid = nil
+  end
+
+  def test_launcher
+    tmp_dirs = %w(cache pids sessions sockets)
+    tmp_dirs.each { |dir| assert(! File.exist?("tmp/#{dir}")) }
+    redirect_test_io { @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port" } }
+    wait_master_ready("test_stderr.#$$.log")
+
+    # temp dirs exist
+    tmp_dirs.each { |dir| assert(File.directory?("tmp/#{dir}")) }
+
+    # basic GET
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
+    assert_equal "FOO\n", res.body
+    assert_match %r{^text/html\b}, res['Content-Type']
+    assert_equal "4", res['Content-Length']
+    assert_equal "200 OK", res['Status']
+
+    # can we set cookies?
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xcookie"))
+    assert_equal "200", res.code
+    assert_equal "200 OK", res['Status']
+    cookies = res.get_fields('Set-Cookie')
+    assert_equal 2, cookies.size
+    assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
+    assert_equal 1, cookies.grep(/\Afoo=cookie/).size
+
+    # how about just a session?
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xnotice"))
+    assert_equal "200", res.code
+    assert_equal "200 OK", res['Status']
+    cookies = res.get_fields('Set-Cookie')
+    assert_equal 1, cookies.size
+    assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
+
+    # posting forms?
+    uri = URI.parse("http://#@addr:#@port/foo/xpost")
+    wait_master_ready("test_stderr.#$$.log")
+    res = Net::HTTP.post_form(uri, {"a" => "b", "c"=>"d"})
+    assert_equal "200", res.code
+    params = res.body.split(/\n/).grep(/^params:/)
+    assert_equal 1, params.size
+    params = eval(params[0].gsub!(/\Aparams:/, ''))
+    assert_equal Hash, params.class
+    assert_equal 'b', params['a']
+    assert_equal 'd', params['c']
+    assert_equal "200 OK", res['Status']
+
+    # try uploading a big file
+    tmp = Tempfile.new('random')
+    sha1 = Digest::SHA1.new
+    assert_nothing_raised do
+      File.open("/dev/urandom", "rb") do |fp|
+        256.times do
+          buf = fp.sysread(4096)
+          sha1.update(buf)
+          tmp.syswrite(buf)
+        end
+      end
+    end
+    resp = `curl -isSfN -Ffile=@#{tmp.path} http://#@addr:#@port/foo/xpost`
+    assert $?.success?
+    resp = resp.split(/\r?\n/)
+    grepped = resp.grep(/^sha1: (.{40})/)
+    assert_equal 1, grepped.size
+    assert_equal(sha1.hexdigest, /^sha1: (.{40})/.match(grepped.first)[1])
+
+    grepped = resp.grep(/^Content-Type:\s+(.+)/i)
+    assert_equal 1, grepped.size
+    assert_match %r{^text/plain}, grepped.first.split(/\s*:\s*/)[1]
+
+    assert_equal 1, resp.grep(/^Status:/i).size
+
+    # make sure we can get 403 responses, too
+    uri = URI.parse("http://#@addr:#@port/foo/xpost")
+    wait_master_ready("test_stderr.#$$.log")
+    res = Net::HTTP.get_response(uri)
+    assert_equal "403", res.code
+    assert_equal "403 Forbidden", res['Status']
+
+    # non existent controller
+    uri = URI.parse("http://#@addr:#@port/asdf")
+    res = Net::HTTP.get_response(uri)
+    assert_equal "404", res.code
+    assert_equal "404 Not Found", res['Status']
+
+    # static files
+
+    # ensure file we're about to serve is not there yet
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
+    assert_equal "404 Not Found", res['Status']
+    assert_equal '404', res.code
+
+    # can we serve text files based on suffix?
+    File.open("public/pid.txt", "wb") { |fp| fp.syswrite("#$$\n") }
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
+    assert_equal '200', res.code
+    assert_equal "200 OK", res['Status']
+    assert_match %r{^text/plain}, res['Content-Type']
+    assert_equal "#$$\n", res.body
+
+    # can we serve HTML files based on suffix?
+    assert File.exist?("public/500.html")
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500.html"))
+    assert_equal '200', res.code
+    assert_equal '200 OK', res['Status']
+    assert_match %r{^text/html}, res['Content-Type']
+    five_hundred_body = res.body
+
+    # lets try pretending 500 is a controller that got cached
+    assert ! File.exist?("public/500")
+    assert_equal five_hundred_body, File.read("public/500.html")
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500"))
+    assert_equal '200', res.code
+    assert_equal '200 OK', res['Status']
+    assert_match %r{^text/html}, res['Content-Type']
+    assert_equal five_hundred_body, res.body
+  end
+
+  def test_alt_url_root
+    # cbf to actually work on this since I never use this feature (ewong)
+    return unless ROR_V[0] >= 2 && ROR_V[1] >= 3
+    redirect_test_io do
+      @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port", '-P/poo' }
+    end
+    wait_master_ready("test_stderr.#$$.log")
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/poo/foo"))
+    # p res
+    # p res.body
+    # system 'cat', 'log/development.log'
+    assert_equal "200", res.code
+    assert_equal '200 OK', res['Status']
+    assert_equal "FOO\n", res.body
+    assert_match %r{^text/html\b}, res['Content-Type']
+    assert_equal "4", res['Content-Length']
+
+    res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
+    assert_equal "404", res.code
+    assert_equal '404 Not Found', res['Status']
+  end
+
+  def teardown
+    return if @start_pid != $$
+
+    if @pid
+      Process.kill(:QUIT, @pid)
+      pid2, status = Process.waitpid2(@pid)
+      assert status.success?
+    end
+
+    Dir.chdir(@pwd)
+    FileUtils.rmtree(@tmpdir)
+    loop do
+      Process.kill('-QUIT', 0)
+      begin
+        Process.waitpid(-1, Process::WNOHANG) or break
+      rescue Errno::ECHILD
+        break
+      end
+    end
+  end
+
+end if do_test