vendor/rails/railties/test/fcgi_dispatcher_test.rb in radiant-0.6.4 vs vendor/rails/railties/test/fcgi_dispatcher_test.rb in radiant-0.6.5
- old
+ new
@@ -1,259 +1,241 @@
require File.dirname(__FILE__) + "/abstract_unit"
-begin # rescue LoadError
+uses_mocha 'fcgi dispatcher tests' do
-require 'mocha'
-require 'stubba'
-
-$:.unshift File.dirname(__FILE__) + "/mocks"
-
-require 'stringio'
-
-# Stubs
require 'fcgi_handler'
-require 'routes'
-require 'stubbed_breakpoint'
-require 'stubbed_kernel'
-class RailsFCGIHandler
- attr_reader :exit_code
- attr_reader :reloaded
- attr_accessor :thread
- attr_reader :gc_runs
+module ActionController; module Routing; module Routes; end end end
- def trap(signal, handler, &block)
- handler ||= block
- (@signal_handlers ||= Hash.new)[signal] = handler
- end
-
- def exit(code=0)
- @exit_code = code
- (thread || Thread.current).exit
- end
-
- def send_signal(which)
- @signal_handlers[which].call(which)
- end
-
- def breakpoint
- end
-
- alias_method :old_run_gc!, :run_gc!
- def run_gc!
- @gc_runs ||= 0
- @gc_runs += 1
- old_run_gc!
- end
-end
-
class RailsFCGIHandlerTest < Test::Unit::TestCase
def setup
@log = StringIO.new
@handler = RailsFCGIHandler.new(@log)
- FCGI.time_to_sleep = nil
- FCGI.raise_exception = nil
- Dispatcher.time_to_sleep = nil
- Dispatcher.raise_exception = nil
end
def test_process_restart
- @handler.stubs(:when_ready).returns(:restart)
-
- @handler.expects(:close_connection)
+ cgi = mock
+ FCGI.stubs(:each_cgi).yields(cgi)
+
+ @handler.expects(:process_request).once
+ @handler.expects(:dispatcher_error).never
+
+ @handler.expects(:when_ready).returns(:restart)
+ @handler.expects(:close_connection).with(cgi)
+ @handler.expects(:reload!).never
@handler.expects(:restart!)
+
@handler.process!
end
-
+
def test_process_exit
- @handler.stubs(:when_ready).returns(:exit)
-
- @handler.expects(:close_connection)
+ cgi = mock
+ FCGI.stubs(:each_cgi).yields(cgi)
+
+ @handler.expects(:process_request).once
+ @handler.expects(:dispatcher_error).never
+
+ @handler.expects(:when_ready).returns(:exit)
+ @handler.expects(:close_connection).with(cgi)
+ @handler.expects(:reload!).never
+ @handler.expects(:restart!).never
+
@handler.process!
end
-
- def test_process_breakpoint
- @handler.stubs(:when_ready).returns(:breakpoint)
-
- @handler.expects(:close_connection)
- @handler.expects(:breakpoint!)
- @handler.process!
- end
-
+
def test_process_with_system_exit_exception
- @handler.stubs(:process_request).raises(SystemExit)
-
- @handler.expects(:dispatcher_log).with(:info, "terminated by explicit exit")
+ cgi = mock
+ FCGI.stubs(:each_cgi).yields(cgi)
+
+ @handler.expects(:process_request).once.raises(SystemExit)
+ @handler.stubs(:dispatcher_log)
+ @handler.expects(:dispatcher_log).with(:info, regexp_matches(/^stopping/))
+ @handler.expects(:dispatcher_error).never
+
+ @handler.expects(:when_ready).never
+ @handler.expects(:close_connection).never
+ @handler.expects(:reload!).never
+ @handler.expects(:restart!).never
+
@handler.process!
end
-
+
def test_restart_handler
@handler.expects(:dispatcher_log).with(:info, "asked to restart ASAP")
-
+
@handler.send(:restart_handler, nil)
assert_equal :restart, @handler.when_ready
end
-
- def test_breakpoint_handler
- @handler.expects(:dispatcher_log).with(:info, "asked to breakpoint ASAP")
- @handler.send(:breakpoint_handler, nil)
- assert_equal :breakpoint, @handler.when_ready
- end
-
def test_install_signal_handler_should_log_on_bad_signal
@handler.stubs(:trap).raises(ArgumentError)
@handler.expects(:dispatcher_log).with(:warn, "Ignoring unsupported signal CHEESECAKE.")
@handler.send(:install_signal_handler, "CHEESECAKE", nil)
end
-
+
def test_reload
@handler.expects(:restore!)
@handler.expects(:dispatcher_log).with(:info, "reloaded")
@handler.send(:reload!)
assert_nil @handler.when_ready
end
-
-
+
+
def test_reload_runs_gc_when_gc_request_period_set
@handler.expects(:run_gc!)
@handler.expects(:restore!)
@handler.expects(:dispatcher_log).with(:info, "reloaded")
@handler.gc_request_period = 10
@handler.send(:reload!)
end
-
+
def test_reload_doesnt_run_gc_if_gc_request_period_isnt_set
@handler.expects(:run_gc!).never
@handler.expects(:restore!)
@handler.expects(:dispatcher_log).with(:info, "reloaded")
@handler.send(:reload!)
end
-
+
def test_restart!
@handler.expects(:dispatcher_log).with(:info, "restarted")
- assert_equal true, @handler.send(:restart!), "Exec wasn't run"
+ @handler.expects(:exec).returns('restarted')
+ assert_equal 'restarted', @handler.send(:restart!)
end
-
+
def test_restore!
$".expects(:replace)
Dispatcher.expects(:reset_application!)
ActionController::Routing::Routes.expects(:reload)
@handler.send(:restore!)
end
- def test_breakpoint!
- @handler.expects(:require).with('breakpoint')
- Breakpoint.expects(:activate_drb)
- @handler.expects(:breakpoint)
- @handler.expects(:dispatcher_log).with(:info, "breakpointing")
- @handler.send(:breakpoint!)
- assert_nil @handler.when_ready
- end
-
def test_uninterrupted_processing
+ cgi = mock
+ FCGI.expects(:each_cgi).yields(cgi)
+ @handler.expects(:process_request).with(cgi)
+
@handler.process!
- assert_nil @handler.exit_code
+
assert_nil @handler.when_ready
end
+end
+
+class RailsFCGIHandlerSignalsTest < Test::Unit::TestCase
+ def setup
+ @log = StringIO.new
+ @handler = RailsFCGIHandler.new(@log)
+ end
+
def test_interrupted_via_HUP_when_not_in_request
- @handler.expects(:reload!)
- FCGI.time_to_sleep = 1
- @handler.thread = Thread.new { @handler.process! }
- sleep 0.1 # let the thread get started
- @handler.send_signal("HUP")
- @handler.thread.join
- assert_nil @handler.exit_code
+ cgi = mock
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ @handler.expects(:gc_countdown).returns { Process.kill 'HUP', $$ }
+
+ @handler.expects(:reload!).once
+ @handler.expects(:close_connection).never
+ @handler.expects(:exit).never
+
+ @handler.process!
assert_equal :reload, @handler.when_ready
end
def test_interrupted_via_HUP_when_in_request
- @handler.expects(:reload!)
-
- Dispatcher.time_to_sleep = 1
- @handler.thread = Thread.new { @handler.process! }
- sleep 0.1 # let the thread get started
- @handler.send_signal("HUP")
- @handler.thread.join
- assert_nil @handler.exit_code
+ cgi = mock
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ Dispatcher.expects(:dispatch).with(cgi).returns { Process.kill 'HUP', $$ }
+
+ @handler.expects(:reload!).once
+ @handler.expects(:close_connection).never
+ @handler.expects(:exit).never
+
+ @handler.process!
assert_equal :reload, @handler.when_ready
end
def test_interrupted_via_USR1_when_not_in_request
- FCGI.time_to_sleep = 1
- @handler.thread = Thread.new { @handler.process! }
- sleep 0.1 # let the thread get started
- @handler.send_signal("USR1")
- @handler.thread.join
- assert_nil @handler.exit_code
- assert_equal :exit, @handler.when_ready
+ cgi = mock
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ @handler.expects(:gc_countdown).returns { Process.kill 'USR1', $$ }
+ @handler.expects(:exit_handler).never
+
+ @handler.expects(:reload!).never
+ @handler.expects(:close_connection).with(cgi).once
+ @handler.expects(:exit).never
+
+ @handler.process!
+ assert_nil @handler.when_ready
end
def test_interrupted_via_USR1_when_in_request
- Dispatcher.time_to_sleep = 1
- @handler.thread = Thread.new { @handler.process! }
- sleep 0.1 # let the thread get started
- @handler.send_signal("USR1")
- @handler.thread.join
- assert_nil @handler.exit_code
+ cgi = mock
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ Dispatcher.expects(:dispatch).with(cgi).returns { Process.kill 'USR1', $$ }
+
+ @handler.expects(:reload!).never
+ @handler.expects(:close_connection).with(cgi).once
+ @handler.expects(:exit).never
+
+ @handler.process!
assert_equal :exit, @handler.when_ready
end
-
+
def test_interrupted_via_TERM
- Dispatcher.time_to_sleep = 1
- @handler.thread = Thread.new { @handler.process! }
- sleep 0.1 # let the thread get started
- @handler.send_signal("TERM")
- @handler.thread.join
- assert_equal 0, @handler.exit_code
+ cgi = mock
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ Dispatcher.expects(:dispatch).with(cgi).returns { Process.kill 'TERM', $$ }
+
+ @handler.expects(:reload!).never
+ @handler.expects(:close_connection).never
+
+ @handler.process!
assert_nil @handler.when_ready
end
- %w(RuntimeError SignalException).each do |exception|
- define_method("test_#{exception}_in_fcgi") do
- FCGI.raise_exception = Object.const_get(exception)
- @handler.process!
- assert_match %r{Dispatcher failed to catch}, @log.string
- case exception
- when "RuntimeError"
- assert_match %r{almost killed}, @log.string
- when "SignalException"
- assert_match %r{^killed}, @log.string
- end
- end
+ def test_runtime_exception_in_fcgi
+ error = RuntimeError.new('foo')
+ FCGI.expects(:each_cgi).times(2).raises(error)
+ @handler.expects(:dispatcher_error).with(error, regexp_matches(/^retrying/))
+ @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
+ @handler.process!
+ end
- define_method("test_#{exception}_in_dispatcher") do
- Dispatcher.raise_exception = Object.const_get(exception)
- @handler.process!
- assert_match %r{Dispatcher failed to catch}, @log.string
- case exception
- when "RuntimeError"
- assert_no_match %r{killed}, @log.string
- when "SignalException"
- assert_match %r{^killed}, @log.string
- end
- end
+ def test_runtime_error_in_dispatcher
+ cgi = mock
+ error = RuntimeError.new('foo')
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ Dispatcher.expects(:dispatch).once.with(cgi).raises(error)
+ @handler.expects(:dispatcher_error).with(error, regexp_matches(/^unhandled/))
+ @handler.process!
end
+
+ def test_signal_exception_in_fcgi
+ error = SignalException.new('USR2')
+ FCGI.expects(:each_cgi).once.raises(error)
+ @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
+ @handler.process!
+ end
+
+ def test_signal_exception_in_dispatcher
+ cgi = mock
+ error = SignalException.new('USR2')
+ FCGI.expects(:each_cgi).once.yields(cgi)
+ Dispatcher.expects(:dispatch).once.with(cgi).raises(error)
+ @handler.expects(:dispatcher_error).with(error, regexp_matches(/^stopping/))
+ @handler.process!
+ end
end
+
class RailsFCGIHandlerPeriodicGCTest < Test::Unit::TestCase
def setup
@log = StringIO.new
- FCGI.time_to_sleep = nil
- FCGI.raise_exception = nil
- FCGI.each_cgi_count = nil
- Dispatcher.time_to_sleep = nil
- Dispatcher.raise_exception = nil
- Dispatcher.dispatch_hook = nil
end
def teardown
- FCGI.each_cgi_count = nil
- Dispatcher.dispatch_hook = nil
GC.enable
end
def test_normal_gc
@handler = RailsFCGIHandler.new(@log)
@@ -262,33 +244,22 @@
# When GC is enabled, GC.disable disables and returns false.
assert_equal false, GC.disable
end
def test_periodic_gc
- Dispatcher.dispatch_hook = lambda do |cgi|
- # When GC is disabled, GC.enable enables and returns true.
- assert_equal true, GC.enable
- GC.disable
- end
-
@handler = RailsFCGIHandler.new(@log, 10)
assert_equal 10, @handler.gc_request_period
- FCGI.each_cgi_count = 1
- @handler.process!
- assert_equal 1, @handler.gc_runs
- FCGI.each_cgi_count = 10
- @handler.process!
- assert_equal 3, @handler.gc_runs
+ cgi = mock
+ FCGI.expects(:each_cgi).times(10).yields(cgi)
+ Dispatcher.expects(:dispatch).times(10).with(cgi)
- FCGI.each_cgi_count = 25
+ @handler.expects(:run_gc!).never
+ 9.times { @handler.process! }
+ @handler.expects(:run_gc!).once
@handler.process!
- assert_equal 6, @handler.gc_runs
- assert_nil @handler.exit_code
assert_nil @handler.when_ready
end
end
-rescue LoadError
- $stderr.puts "Skipping dispatcher tests. `gem install mocha` and try again."
-end
\ No newline at end of file
+end # uses_mocha