1 # Copyright (c) 2009 Eric Wong
2 require 'test/test_helper'
4 # don't call exit(0) since it may be run under rake (but gmake is recommended)
7 $unicorn_rails_bin = ENV['UNICORN_RAILS_TEST_BIN'] || "unicorn_rails"
8 redirect_test_io { do_test = system($unicorn_rails_bin, '-v') }
11 warn "#$unicorn_rails_bin not found in PATH=#{ENV['PATH']}, " \
16 warn "git not found in PATH=#{ENV['PATH']}, skipping this test"
20 if RAILS_GIT_REPO = ENV['RAILS_GIT_REPO']
21 unless File.directory?(RAILS_GIT_REPO)
22 warn "#{RAILS_GIT_REPO} not found, create it with:\n" \
23 "\tgit clone --mirror git://github.com/rails/rails #{RAILS_GIT_REPO}" \
24 "skipping this test for now"
28 warn "RAILS_GIT_REPO not defined, don't know where to git clone from"
32 unless UNICORN_RAILS_TEST_VERSION = ENV['UNICORN_RAILS_TEST_VERSION']
33 warn 'UNICORN_RAILS_TEST_VERSION not defined in environment, ' \
38 RAILS_ROOT = "#{File.dirname(__FILE__)}/app-#{UNICORN_RAILS_TEST_VERSION}"
39 unless File.directory?(RAILS_ROOT)
40 warn "unsupported UNICORN_RAILS_TEST_VERSION=#{UNICORN_RAILS_TEST_VERSION}"
44 ROR_V = UNICORN_RAILS_TEST_VERSION.split(/\./).map { |x| x.to_i }
45 RB_V = RUBY_VERSION.split(/\./).map { |x| x.to_i }
46 if RB_V[0] >= 1 && RB_V[1] >= 9
47 unless ROR_V[0] >= 2 && ROR_V[1] >= 3
48 warn "skipping Ruby >=1.9 test with Rails <2.3"
53 class RailsTest < Test::Unit::TestCase
56 COMMON_TMP = Tempfile.new('unicorn_tmp') unless defined?(COMMON_TMP)
61 logger Logger.new('#{COMMON_TMP.path}')
66 @tmpfile = Tempfile.new('unicorn_rails_test')
67 @tmpdir = @tmpfile.path
69 assert_nothing_raised do
70 FileUtils.cp_r(RAILS_ROOT, @tmpdir, :preserve => true)
73 system('git', 'clone', '-nsq', RAILS_GIT_REPO, 'vendor/rails')
74 Dir.chdir("#@tmpdir/vendor/rails") do
75 system('git', 'reset', '-q', '--hard', "v#{UNICORN_RAILS_TEST_VERSION}")
78 assert(system('rake', 'db:sessions:create'))
79 assert(system('rake', 'db:migrate'))
81 @addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
82 @port = unused_port(@addr)
88 tmp_dirs = %w(cache pids sessions sockets)
89 tmp_dirs.each { |dir| assert(! File.exist?("tmp/#{dir}")) }
90 redirect_test_io { @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port" } }
91 wait_master_ready("test_stderr.#$$.log")
94 tmp_dirs.each { |dir| assert(File.directory?("tmp/#{dir}")) }
97 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
98 assert_equal "FOO\n", res.body
99 assert_match %r{^text/html\b}, res['Content-Type']
100 assert_equal "4", res['Content-Length']
101 assert_equal "200 OK", res['Status']
103 # can we set cookies?
104 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xcookie"))
105 assert_equal "200", res.code
106 assert_equal "200 OK", res['Status']
107 cookies = res.get_fields('Set-Cookie')
108 assert_equal 2, cookies.size
109 assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
110 assert_equal 1, cookies.grep(/\Afoo=cookie/).size
112 # how about just a session?
113 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xnotice"))
114 assert_equal "200", res.code
115 assert_equal "200 OK", res['Status']
116 cookies = res.get_fields('Set-Cookie')
117 assert_equal 1, cookies.size
118 assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
121 uri = URI.parse("http://#@addr:#@port/foo/xpost")
122 wait_master_ready("test_stderr.#$$.log")
123 res = Net::HTTP.post_form(uri, {"a" => "b", "c"=>"d"})
124 assert_equal "200", res.code
125 params = res.body.split(/\n/).grep(/^params:/)
126 assert_equal 1, params.size
127 params = eval(params[0].gsub!(/\Aparams:/, ''))
128 assert_equal Hash, params.class
129 assert_equal 'b', params['a']
130 assert_equal 'd', params['c']
131 assert_equal "200 OK", res['Status']
133 # try uploading a big file
134 tmp = Tempfile.new('random')
135 sha1 = Digest::SHA1.new
136 assert_nothing_raised do
137 File.open("/dev/urandom", "rb") do |fp|
139 buf = fp.sysread(4096)
145 resp = `curl -isSfN -Ffile=@#{tmp.path} http://#@addr:#@port/foo/xpost`
147 resp = resp.split(/\r?\n/)
148 grepped = resp.grep(/^sha1: (.{40})/)
149 assert_equal 1, grepped.size
150 assert_equal(sha1.hexdigest, /^sha1: (.{40})/.match(grepped.first)[1])
152 grepped = resp.grep(/^Content-Type:\s+(.+)/i)
153 assert_equal 1, grepped.size
154 assert_match %r{^text/plain}, grepped.first.split(/\s*:\s*/)[1]
156 assert_equal 1, resp.grep(/^Status:/i).size
158 # make sure we can get 403 responses, too
159 uri = URI.parse("http://#@addr:#@port/foo/xpost")
160 wait_master_ready("test_stderr.#$$.log")
161 res = Net::HTTP.get_response(uri)
162 assert_equal "403", res.code
163 assert_equal "403 Forbidden", res['Status']
165 # non existent controller
166 uri = URI.parse("http://#@addr:#@port/asdf")
167 res = Net::HTTP.get_response(uri)
168 assert_equal "404", res.code
169 assert_equal "404 Not Found", res['Status']
173 # ensure file we're about to serve is not there yet
174 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
175 assert_equal "404 Not Found", res['Status']
176 assert_equal '404', res.code
178 # can we serve text files based on suffix?
179 File.open("public/pid.txt", "wb") { |fp| fp.syswrite("#$$\n") }
180 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
181 assert_equal '200', res.code
182 assert_equal "200 OK", res['Status']
183 assert_match %r{^text/plain}, res['Content-Type']
184 assert_equal "#$$\n", res.body
186 # can we serve HTML files based on suffix?
187 assert File.exist?("public/500.html")
188 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500.html"))
189 assert_equal '200', res.code
190 assert_equal '200 OK', res['Status']
191 assert_match %r{^text/html}, res['Content-Type']
192 five_hundred_body = res.body
194 # lets try pretending 500 is a controller that got cached
195 assert ! File.exist?("public/500")
196 assert_equal five_hundred_body, File.read("public/500.html")
197 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500"))
198 assert_equal '200', res.code
199 assert_equal '200 OK', res['Status']
200 assert_match %r{^text/html}, res['Content-Type']
201 assert_equal five_hundred_body, res.body
204 def test_alt_url_root
205 # cbf to actually work on this since I never use this feature (ewong)
206 return unless ROR_V[0] >= 2 && ROR_V[1] >= 3
208 @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port", '-P/poo' }
210 wait_master_ready("test_stderr.#$$.log")
211 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/poo/foo"))
214 # system 'cat', 'log/development.log'
215 assert_equal "200", res.code
216 assert_equal '200 OK', res['Status']
217 assert_equal "FOO\n", res.body
218 assert_match %r{^text/html\b}, res['Content-Type']
219 assert_equal "4", res['Content-Length']
221 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
222 assert_equal "404", res.code
223 assert_equal '404 Not Found', res['Status']
227 return if @start_pid != $$
230 Process.kill(:QUIT, @pid)
231 pid2, status = Process.waitpid2(@pid)
232 assert status.success?
236 FileUtils.rmtree(@tmpdir)
238 Process.kill('-QUIT', 0)
240 Process.waitpid(-1, Process::WNOHANG) or break