1 # -*- encoding: binary -*-
3 # Copyright (c) 2009 Eric Wong
4 require 'test/test_helper'
6 # don't call exit(0) since it may be run under rake (but gmake is recommended)
9 $unicorn_rails_bin = ENV['UNICORN_RAILS_TEST_BIN'] || "unicorn_rails"
10 redirect_test_io { do_test = system($unicorn_rails_bin, '-v') }
13 warn "#$unicorn_rails_bin not found in PATH=#{ENV['PATH']}, " \
18 warn "git not found in PATH=#{ENV['PATH']}, skipping this test"
22 if RAILS_GIT_REPO = ENV['RAILS_GIT_REPO']
23 unless File.directory?(RAILS_GIT_REPO)
24 warn "#{RAILS_GIT_REPO} not found, create it with:\n" \
25 "\tgit clone --mirror git://github.com/rails/rails #{RAILS_GIT_REPO}" \
26 "skipping this test for now"
30 warn "RAILS_GIT_REPO not defined, don't know where to git clone from"
34 unless UNICORN_RAILS_TEST_VERSION = ENV['UNICORN_RAILS_TEST_VERSION']
35 warn 'UNICORN_RAILS_TEST_VERSION not defined in environment, ' \
40 RAILS_ROOT = "#{File.dirname(__FILE__)}/app-#{UNICORN_RAILS_TEST_VERSION}"
41 unless File.directory?(RAILS_ROOT)
42 warn "unsupported UNICORN_RAILS_TEST_VERSION=#{UNICORN_RAILS_TEST_VERSION}"
46 ROR_V = UNICORN_RAILS_TEST_VERSION.split(/\./).map { |x| x.to_i }
47 RB_V = RUBY_VERSION.split(/\./).map { |x| x.to_i }
48 if RB_V[0] >= 1 && RB_V[1] >= 9
49 unless ROR_V[0] >= 2 && ROR_V[1] >= 3
50 warn "skipping Ruby >=1.9 test with Rails <2.3"
55 class RailsTest < Test::Unit::TestCase
58 COMMON_TMP = Tempfile.new('unicorn_tmp') unless defined?(COMMON_TMP)
63 logger Logger.new('#{COMMON_TMP.path}')
68 @tmpfile = Tempfile.new('unicorn_rails_test')
69 @tmpdir = @tmpfile.path
71 assert_nothing_raised do
72 FileUtils.cp_r(RAILS_ROOT, @tmpdir, :preserve => true)
75 system('git', 'clone', '-nsq', RAILS_GIT_REPO, 'vendor/rails')
76 Dir.chdir("#@tmpdir/vendor/rails") do
77 system('git', 'reset', '-q', '--hard', "v#{UNICORN_RAILS_TEST_VERSION}")
80 assert(system('rake', 'db:sessions:create'))
81 assert(system('rake', 'db:migrate'))
83 @addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
84 @port = unused_port(@addr)
90 tmp_dirs = %w(cache pids sessions sockets)
91 tmp_dirs.each { |dir| assert(! File.exist?("tmp/#{dir}")) }
92 redirect_test_io { @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port" } }
93 wait_master_ready("test_stderr.#$$.log")
96 tmp_dirs.each { |dir| assert(File.directory?("tmp/#{dir}")) }
99 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
100 assert_equal "FOO\n", res.body
101 assert_match %r{^text/html\b}, res['Content-Type']
102 assert_equal "4", res['Content-Length']
103 assert_equal "200 OK", res['Status']
105 # can we set cookies?
106 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xcookie"))
107 assert_equal "200", res.code
108 assert_equal "200 OK", res['Status']
109 cookies = res.get_fields('Set-Cookie')
110 assert_equal 2, cookies.size
111 assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
112 assert_equal 1, cookies.grep(/\Afoo=cookie/).size
114 # how about just a session?
115 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo/xnotice"))
116 assert_equal "200", res.code
117 assert_equal "200 OK", res['Status']
118 cookies = res.get_fields('Set-Cookie')
119 assert_equal 1, cookies.size
120 assert_equal 1, cookies.grep(/\A_unicorn_rails_test\./).size
123 uri = URI.parse("http://#@addr:#@port/foo/xpost")
124 wait_master_ready("test_stderr.#$$.log")
125 res = Net::HTTP.post_form(uri, {"a" => "b", "c"=>"d"})
126 assert_equal "200", res.code
127 params = res.body.split(/\n/).grep(/^params:/)
128 assert_equal 1, params.size
129 params = eval(params[0].gsub!(/\Aparams:/, ''))
130 assert_equal Hash, params.class
131 assert_equal 'b', params['a']
132 assert_equal 'd', params['c']
133 assert_equal "200 OK", res['Status']
135 # try uploading a big file
136 tmp = Tempfile.new('random')
137 sha1 = Digest::SHA1.new
138 assert_nothing_raised do
139 File.open("/dev/urandom", "rb") do |fp|
141 buf = fp.sysread(4096)
148 # fixed in Rack commit 44ed4640f077504a49b7f1cabf8d6ad7a13f6441,
149 # no released version of Rails or Rack has this fix
150 if RB_V[0] >= 1 && RB_V[1] >= 9
151 warn "multipart broken with Rack 1.0.0 and Rails 2.3.2.1 under 1.9"
153 resp = `curl -isSfN -Ffile=@#{tmp.path} http://#@addr:#@port/foo/xpost`
155 resp = resp.split(/\r?\n/)
156 grepped = resp.grep(/^sha1: (.{40})/)
157 assert_equal 1, grepped.size
158 assert_equal(sha1.hexdigest, /^sha1: (.{40})/.match(grepped.first)[1])
160 grepped = resp.grep(/^Content-Type:\s+(.+)/i)
161 assert_equal 1, grepped.size
162 assert_match %r{^text/plain}, grepped.first.split(/\s*:\s*/)[1]
163 assert_equal 1, resp.grep(/^Status:/i).size
166 # make sure we can get 403 responses, too
167 uri = URI.parse("http://#@addr:#@port/foo/xpost")
168 wait_master_ready("test_stderr.#$$.log")
169 res = Net::HTTP.get_response(uri)
170 assert_equal "403", res.code
171 assert_equal "403 Forbidden", res['Status']
173 # non existent controller
174 uri = URI.parse("http://#@addr:#@port/asdf")
175 res = Net::HTTP.get_response(uri)
176 assert_equal "404", res.code
177 assert_equal "404 Not Found", res['Status']
181 # ensure file we're about to serve is not there yet
182 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
183 assert_equal "404 Not Found", res['Status']
184 assert_equal '404', res.code
186 # can we serve text files based on suffix?
187 File.open("public/pid.txt", "wb") { |fp| fp.syswrite("#$$\n") }
188 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/pid.txt"))
189 assert_equal '200', res.code
190 assert_equal "200 OK", res['Status']
191 assert_match %r{^text/plain}, res['Content-Type']
192 assert_equal "#$$\n", res.body
194 # can we serve HTML files based on suffix?
195 assert File.exist?("public/500.html")
196 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500.html"))
197 assert_equal '200', res.code
198 assert_equal '200 OK', res['Status']
199 assert_match %r{^text/html}, res['Content-Type']
200 five_hundred_body = res.body
202 # lets try pretending 500 is a controller that got cached
203 assert ! File.exist?("public/500")
204 assert_equal five_hundred_body, File.read("public/500.html")
205 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/500"))
206 assert_equal '200', res.code
207 assert_equal '200 OK', res['Status']
208 assert_match %r{^text/html}, res['Content-Type']
209 assert_equal five_hundred_body, res.body
212 def test_alt_url_root
213 # cbf to actually work on this since I never use this feature (ewong)
214 return unless ROR_V[0] >= 2 && ROR_V[1] >= 3
216 @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port", '-P/poo' }
218 wait_master_ready("test_stderr.#$$.log")
219 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/poo/foo"))
222 # system 'cat', 'log/development.log'
223 assert_equal "200", res.code
224 assert_equal '200 OK', res['Status']
225 assert_equal "FOO\n", res.body
226 assert_match %r{^text/html\b}, res['Content-Type']
227 assert_equal "4", res['Content-Length']
229 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
230 assert_equal "404", res.code
231 assert_equal '404 Not Found', res['Status']
234 def test_alt_url_root_config_env
235 # cbf to actually work on this since I never use this feature (ewong)
236 return unless ROR_V[0] >= 2 && ROR_V[1] >= 3
237 tmp = Tempfile.new(nil)
238 tmp.syswrite("ENV['RAILS_RELATIVE_URL_ROOT'] = '/poo'\n")
240 @pid = fork { exec 'unicorn_rails', "-l#@addr:#@port", "-c", tmp.path }
242 wait_master_ready("test_stderr.#$$.log")
243 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/poo/foo"))
244 assert_equal "200", res.code
245 assert_equal '200 OK', res['Status']
246 assert_equal "FOO\n", res.body
247 assert_match %r{^text/html\b}, res['Content-Type']
248 assert_equal "4", res['Content-Length']
250 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/foo"))
251 assert_equal "404", res.code
252 assert_equal '404 Not Found', res['Status']
254 res = Net::HTTP.get_response(URI.parse("http://#@addr:#@port/poo/x.txt"))
255 assert_equal "200", res.code
256 assert_equal "HELLO\n", res.body
260 return if @start_pid != $$
263 Process.kill(:QUIT, @pid)
264 pid2, status = Process.waitpid2(@pid)
265 assert status.success?
269 FileUtils.rmtree(@tmpdir)
271 Process.kill('-QUIT', 0)
273 Process.waitpid(-1, Process::WNOHANG) or break