Froze rails gems
[depot.git] / vendor / rails / actionpack / test / controller / rescue_test.rb
diff --git a/vendor/rails/actionpack/test/controller/rescue_test.rb b/vendor/rails/actionpack/test/controller/rescue_test.rb
new file mode 100644 (file)
index 0000000..32c6c01
--- /dev/null
@@ -0,0 +1,513 @@
+require 'abstract_unit'
+
+uses_mocha 'rescue' do
+
+class RescueController < ActionController::Base
+  class NotAuthorized < StandardError
+  end
+  class NotAuthorizedToRescueAsString < StandardError
+  end
+
+  class RecordInvalid < StandardError
+  end
+  class RecordInvalidToRescueAsString < StandardError
+  end
+
+  class NotAllowed < StandardError
+  end
+  class NotAllowedToRescueAsString < StandardError
+  end
+
+  class InvalidRequest < StandardError
+  end
+  class InvalidRequestToRescueAsString < StandardError
+  end
+
+  class BadGateway < StandardError
+  end
+  class BadGatewayToRescueAsString < StandardError
+  end
+
+  class ResourceUnavailable < StandardError
+  end
+  class ResourceUnavailableToRescueAsString < StandardError
+  end
+
+  # We use a fully-qualified name in some strings, and a relative constant
+  # name in some other to test correct handling of both cases.
+
+  rescue_from NotAuthorized, :with => :deny_access
+  rescue_from 'RescueController::NotAuthorizedToRescueAsString', :with => :deny_access
+
+  rescue_from RecordInvalid, :with => :show_errors
+  rescue_from 'RescueController::RecordInvalidToRescueAsString', :with => :show_errors
+
+  rescue_from NotAllowed, :with => proc { head :forbidden }
+  rescue_from 'RescueController::NotAllowedToRescueAsString', :with => proc { head :forbidden }
+
+  rescue_from InvalidRequest, :with => proc { |exception| render :text => exception.message }
+  rescue_from 'InvalidRequestToRescueAsString', :with => proc { |exception| render :text => exception.message }
+
+  rescue_from BadGateway do
+    head :status => 502
+  end
+  rescue_from 'BadGatewayToRescueAsString' do
+    head :status => 502
+  end
+
+  rescue_from ResourceUnavailable do |exception|
+    render :text => exception.message
+  end
+  rescue_from 'ResourceUnavailableToRescueAsString' do |exception|
+    render :text => exception.message
+  end
+
+  # This is a Dispatcher exception and should be in ApplicationController.
+  rescue_from ActionController::RoutingError do
+    render :text => 'no way'
+  end
+
+  def raises
+    render :text => 'already rendered'
+    raise "don't panic!"
+  end
+
+  def method_not_allowed
+    raise ActionController::MethodNotAllowed.new(:get, :head, :put)
+  end
+
+  def not_implemented
+    raise ActionController::NotImplemented.new(:get, :put)
+  end
+
+  def not_authorized
+    raise NotAuthorized
+  end
+  def not_authorized_raise_as_string
+    raise NotAuthorizedToRescueAsString
+  end
+
+  def not_allowed
+    raise NotAllowed
+  end
+  def not_allowed_raise_as_string
+    raise NotAllowedToRescueAsString
+  end
+
+  def invalid_request
+    raise InvalidRequest
+  end
+  def invalid_request_raise_as_string
+    raise InvalidRequestToRescueAsString
+  end
+
+  def record_invalid
+    raise RecordInvalid
+  end
+  def record_invalid_raise_as_string
+    raise RecordInvalidToRescueAsString
+  end
+
+  def bad_gateway
+    raise BadGateway
+  end
+  def bad_gateway_raise_as_string
+    raise BadGatewayToRescueAsString
+  end
+
+  def resource_unavailable
+    raise ResourceUnavailable
+  end
+  def resource_unavailable_raise_as_string
+    raise ResourceUnavailableToRescueAsString
+  end
+
+  def missing_template
+  end
+
+  protected
+    def deny_access
+      head :forbidden
+    end
+
+    def show_errors(exception)
+      head :unprocessable_entity
+    end
+end
+
+class RescueControllerTest < ActionController::TestCase
+  FIXTURE_PUBLIC = "#{File.dirname(__FILE__)}/../fixtures".freeze
+
+  setup :set_all_requests_local
+  setup :populate_exception_object
+
+  def set_all_requests_local
+    RescueController.consider_all_requests_local = true
+    @request.remote_addr = '1.2.3.4'
+    @request.host = 'example.com'
+  end
+
+  def populate_exception_object
+    begin
+      raise 'foo'
+    rescue => @exception
+    end
+  end
+
+  def test_rescue_action_locally_if_all_requests_local
+    @controller.expects(:local_request?).never
+    @controller.expects(:rescue_action_locally).with(@exception)
+    @controller.expects(:rescue_action_in_public).never
+
+    with_all_requests_local do
+      @controller.send :rescue_action, @exception
+    end
+  end
+
+  def test_rescue_action_locally_if_remote_addr_is_localhost
+    @controller.expects(:local_request?).returns(true)
+    @controller.expects(:rescue_action_locally).with(@exception)
+    @controller.expects(:rescue_action_in_public).never
+
+    with_all_requests_local false do
+      @controller.send :rescue_action, @exception
+    end
+  end
+
+  def test_rescue_action_in_public_otherwise
+    @controller.expects(:local_request?).returns(false)
+    @controller.expects(:rescue_action_locally).never
+    @controller.expects(:rescue_action_in_public).with(@exception)
+
+    with_all_requests_local false do
+      @controller.send :rescue_action, @exception
+    end
+  end
+
+  def test_rescue_action_in_public_with_error_file
+    with_rails_root FIXTURE_PUBLIC do
+      with_all_requests_local false do
+        get :raises
+      end
+    end
+
+    assert_response :internal_server_error
+    body = File.read("#{FIXTURE_PUBLIC}/public/500.html")
+    assert_equal body, @response.body
+  end
+
+  def test_rescue_action_in_public_without_error_file
+    with_rails_root '/tmp' do
+      with_all_requests_local false do
+        get :raises
+      end
+    end
+
+    assert_response :internal_server_error
+    assert_equal ' ', @response.body
+  end
+
+  def test_rescue_unknown_action_in_public_with_error_file
+    with_rails_root FIXTURE_PUBLIC do
+      with_all_requests_local false do
+        get :foobar_doesnt_exist
+      end
+    end
+
+    assert_response :not_found
+    body = File.read("#{FIXTURE_PUBLIC}/public/404.html")
+    assert_equal body, @response.body
+  end
+
+  def test_rescue_unknown_action_in_public_without_error_file
+    with_rails_root '/tmp' do
+      with_all_requests_local false do
+        get :foobar_doesnt_exist
+      end
+    end
+
+    assert_response :not_found
+    assert_equal ' ', @response.body
+  end
+
+  def test_rescue_missing_template_in_public
+    with_rails_root FIXTURE_PUBLIC do
+      with_all_requests_local true do
+        get :missing_template
+      end
+    end
+
+    assert_response :internal_server_error
+    assert @response.body.include?('missing_template'), "Response should include the template name."
+  end
+
+  def test_rescue_action_locally
+    get :raises
+    assert_response :internal_server_error
+    assert_template 'diagnostics.erb'
+    assert @response.body.include?('RescueController#raises'), "Response should include controller and action."
+    assert @response.body.include?("don't panic"), "Response should include exception message."
+  end
+
+  def test_local_request_when_remote_addr_is_localhost
+    @controller.expects(:request).returns(@request).at_least_once
+    with_remote_addr '127.0.0.1' do
+      assert @controller.send(:local_request?)
+    end
+  end
+
+  def test_local_request_when_remote_addr_isnt_locahost
+    @controller.expects(:request).returns(@request)
+    with_remote_addr '1.2.3.4' do
+      assert !@controller.send(:local_request?)
+    end
+  end
+
+  def test_rescue_responses
+    responses = ActionController::Base.rescue_responses
+
+    assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses.default
+    assert_equal ActionController::Rescue::DEFAULT_RESCUE_RESPONSE, responses[Exception.new]
+
+    assert_equal :not_found, responses[ActionController::RoutingError.name]
+    assert_equal :not_found, responses[ActionController::UnknownAction.name]
+    assert_equal :not_found, responses['ActiveRecord::RecordNotFound']
+    assert_equal :conflict, responses['ActiveRecord::StaleObjectError']
+    assert_equal :unprocessable_entity, responses['ActiveRecord::RecordInvalid']
+    assert_equal :unprocessable_entity, responses['ActiveRecord::RecordNotSaved']
+    assert_equal :method_not_allowed, responses['ActionController::MethodNotAllowed']
+    assert_equal :not_implemented, responses['ActionController::NotImplemented']
+  end
+
+  def test_rescue_templates
+    templates = ActionController::Base.rescue_templates
+
+    assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates.default
+    assert_equal ActionController::Rescue::DEFAULT_RESCUE_TEMPLATE, templates[Exception.new]
+
+    assert_equal 'missing_template',  templates[ActionView::MissingTemplate.name]
+    assert_equal 'routing_error',     templates[ActionController::RoutingError.name]
+    assert_equal 'unknown_action',    templates[ActionController::UnknownAction.name]
+    assert_equal 'template_error',    templates[ActionView::TemplateError.name]
+  end
+
+  def test_clean_backtrace
+    with_rails_root nil do
+      # No action if RAILS_ROOT isn't set.
+      cleaned = @controller.send(:clean_backtrace, @exception)
+      assert_equal @exception.backtrace, cleaned
+    end
+
+    with_rails_root Dir.pwd do
+      # RAILS_ROOT is removed from backtrace.
+      cleaned = @controller.send(:clean_backtrace, @exception)
+      expected = @exception.backtrace.map { |line| line.sub(RAILS_ROOT, '') }
+      assert_equal expected, cleaned
+
+      # No action if backtrace is nil.
+      assert_nil @controller.send(:clean_backtrace, Exception.new)
+    end
+  end
+
+  def test_not_implemented
+    with_all_requests_local false do
+      with_rails_public_path(".") do
+        head :not_implemented
+      end
+    end
+    assert_response :not_implemented
+    assert_equal "GET, PUT", @response.headers['Allow']
+  end
+
+  def test_method_not_allowed
+    with_all_requests_local false do
+      with_rails_public_path(".") do
+        get :method_not_allowed
+      end
+    end
+    assert_response :method_not_allowed
+    assert_equal "GET, HEAD, PUT", @response.headers['Allow']
+  end
+
+  def test_rescue_handler
+    get :not_authorized
+    assert_response :forbidden
+  end
+  def test_rescue_handler_string
+    get :not_authorized_raise_as_string
+    assert_response :forbidden
+  end
+
+  def test_rescue_handler_with_argument
+    @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) }
+    get :record_invalid
+  end
+  def test_rescue_handler_with_argument_as_string
+    @controller.expects(:show_errors).once.with { |e| e.is_a?(Exception) }
+    get :record_invalid_raise_as_string
+  end
+
+  def test_proc_rescue_handler
+    get :not_allowed
+    assert_response :forbidden
+  end
+  def test_proc_rescue_handler_as_string
+    get :not_allowed_raise_as_string
+    assert_response :forbidden
+  end
+
+  def test_proc_rescue_handle_with_argument
+    get :invalid_request
+    assert_equal "RescueController::InvalidRequest", @response.body
+  end
+  def test_proc_rescue_handle_with_argument_as_string
+    get :invalid_request_raise_as_string
+    assert_equal "RescueController::InvalidRequestToRescueAsString", @response.body
+  end
+
+  def test_block_rescue_handler
+    get :bad_gateway
+    assert_response 502
+  end
+  def test_block_rescue_handler_as_string
+    get :bad_gateway_raise_as_string
+    assert_response 502
+  end
+
+  def test_block_rescue_handler_with_argument
+    get :resource_unavailable
+    assert_equal "RescueController::ResourceUnavailable", @response.body
+  end
+
+  def test_block_rescue_handler_with_argument_as_string
+    get :resource_unavailable_raise_as_string
+    assert_equal "RescueController::ResourceUnavailableToRescueAsString", @response.body
+  end
+
+  def test_rescue_dispatcher_exceptions
+    RescueController.process_with_exception(@request, @response, ActionController::RoutingError.new("Route not found"))
+    assert_equal "no way", @response.body
+  end
+
+  protected
+    def with_all_requests_local(local = true)
+      old_local, ActionController::Base.consider_all_requests_local =
+        ActionController::Base.consider_all_requests_local, local
+      yield
+    ensure
+      ActionController::Base.consider_all_requests_local = old_local
+    end
+
+    def with_remote_addr(addr)
+      old_remote_addr, @request.remote_addr = @request.remote_addr, addr
+      yield
+    ensure
+      @request.remote_addr = old_remote_addr
+    end
+
+    def with_rails_public_path(rails_root)
+      old_rails = Object.const_get(:Rails) rescue nil
+      mod = Object.const_set(:Rails, Module.new)
+      (class << mod; self; end).instance_eval do
+        define_method(:public_path) { "#{rails_root}/public" }
+      end
+      yield
+    ensure
+      Object.module_eval { remove_const(:Rails) } if defined?(Rails)
+      Object.const_set(:Rails, old_rails) if old_rails
+    end
+
+    def with_rails_root(path = nil,&block)
+      old_rails_root = RAILS_ROOT if defined?(RAILS_ROOT)
+      if path
+        silence_warnings { Object.const_set(:RAILS_ROOT, path) }
+      else
+        Object.remove_const(:RAILS_ROOT) rescue nil
+      end
+
+      with_rails_public_path(path, &block)
+
+    ensure
+      if old_rails_root
+        silence_warnings { Object.const_set(:RAILS_ROOT, old_rails_root) }
+      else
+        Object.remove_const(:RAILS_ROOT) rescue nil
+      end
+    end
+end
+
+class ExceptionInheritanceRescueController < ActionController::Base
+
+  class ParentException < StandardError
+  end
+
+  class ChildException < ParentException
+  end
+
+  class GrandchildException < ChildException
+  end
+
+  rescue_from ChildException,      :with => lambda { head :ok }
+  rescue_from ParentException,     :with => lambda { head :created }
+  rescue_from GrandchildException, :with => lambda { head :no_content }
+
+  def raise_parent_exception
+    raise ParentException
+  end
+
+  def raise_child_exception
+    raise ChildException
+  end
+
+  def raise_grandchild_exception
+    raise GrandchildException
+  end
+end
+
+class ExceptionInheritanceRescueControllerTest < ActionController::TestCase
+  def test_bottom_first
+    get :raise_grandchild_exception
+    assert_response :no_content
+  end
+
+  def test_inheritance_works
+    get :raise_child_exception
+    assert_response :created
+  end
+end
+
+class ControllerInheritanceRescueController < ExceptionInheritanceRescueController
+  class FirstExceptionInChildController < StandardError
+  end
+
+  class SecondExceptionInChildController < StandardError
+  end
+
+  rescue_from FirstExceptionInChildController, 'SecondExceptionInChildController', :with => lambda { head :gone }
+
+  def raise_first_exception_in_child_controller
+    raise FirstExceptionInChildController
+  end
+
+  def raise_second_exception_in_child_controller
+    raise SecondExceptionInChildController
+  end
+end
+
+class ControllerInheritanceRescueControllerTest < ActionController::TestCase
+  def test_first_exception_in_child_controller
+    get :raise_first_exception_in_child_controller
+    assert_response :gone
+  end
+
+  def test_second_exception_in_child_controller
+    get :raise_second_exception_in_child_controller
+    assert_response :gone
+  end
+
+  def test_exception_in_parent_controller
+    get :raise_parent_exception
+    assert_response :created
+  end
+end
+end # uses_mocha