aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/rescuable_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/test/rescuable_test.rb')
-rw-r--r--activesupport/test/rescuable_test.rb176
1 files changed, 176 insertions, 0 deletions
diff --git a/activesupport/test/rescuable_test.rb b/activesupport/test/rescuable_test.rb
new file mode 100644
index 0000000000..b1b8a25c5b
--- /dev/null
+++ b/activesupport/test/rescuable_test.rb
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+require "abstract_unit"
+
+class WraithAttack < StandardError
+end
+
+class MadRonon < StandardError
+end
+
+class CoolError < StandardError
+end
+
+module WeirdError
+ def self.===(other)
+ Exception === other && other.respond_to?(:weird?)
+ end
+end
+
+class Stargate
+ # Nest this so the 'NuclearExplosion' handler needs a lexical const_get
+ # to find it.
+ class NuclearExplosion < StandardError; end
+
+ attr_accessor :result
+
+ include ActiveSupport::Rescuable
+
+ rescue_from WraithAttack, with: :sos_first
+
+ rescue_from WraithAttack, with: :sos
+
+ rescue_from "NuclearExplosion" do
+ @result = "alldead"
+ end
+
+ rescue_from MadRonon do |e|
+ @result = e.message
+ end
+
+ rescue_from WeirdError do
+ @result = "weird"
+ end
+
+ def dispatch(method)
+ send(method)
+ rescue Exception => e
+ unless rescue_with_handler(e)
+ @result = "unhandled"
+ end
+ end
+
+ def attack
+ raise WraithAttack
+ end
+
+ def nuke
+ raise NuclearExplosion
+ end
+
+ def ronanize
+ raise MadRonon.new("dex")
+ end
+
+ def crash
+ raise "unhandled RuntimeError"
+ end
+
+ def looped_crash
+ ex1 = StandardError.new("error 1")
+ ex2 = StandardError.new("error 2")
+ begin
+ begin
+ raise ex1
+ rescue
+ # sets the cause on ex2 to be ex1
+ raise ex2
+ end
+ rescue
+ # sets the cause on ex1 to be ex2
+ raise ex1
+ end
+ end
+
+ def fall_back_to_cause
+ # This exception is the cause and has a handler.
+ ronanize
+ rescue
+ # This is the exception we'll handle that doesn't have a cause.
+ raise "unhandled RuntimeError with a handleable cause"
+ end
+
+ def weird
+ StandardError.new.tap do |exc|
+ def exc.weird?
+ true
+ end
+
+ raise exc
+ end
+ end
+
+ def sos
+ @result = "killed"
+ end
+
+ def sos_first
+ @result = "sos_first"
+ end
+end
+
+class CoolStargate < Stargate
+ attr_accessor :result
+
+ include ActiveSupport::Rescuable
+
+ rescue_from CoolError, with: :sos_cool_error
+
+ def sos_cool_error
+ @result = "sos_cool_error"
+ end
+end
+
+class RescuableTest < ActiveSupport::TestCase
+ def setup
+ @stargate = Stargate.new
+ @cool_stargate = CoolStargate.new
+ end
+
+ def test_rescue_from_with_method
+ @stargate.dispatch :attack
+ assert_equal "killed", @stargate.result
+ end
+
+ def test_rescue_from_with_block
+ @stargate.dispatch :nuke
+ assert_equal "alldead", @stargate.result
+ end
+
+ def test_rescue_from_with_block_with_args
+ @stargate.dispatch :ronanize
+ assert_equal "dex", @stargate.result
+ end
+
+ def test_rescue_from_error_dispatchers_with_case_operator
+ @stargate.dispatch :weird
+ assert_equal "weird", @stargate.result
+ end
+
+ def test_rescues_defined_later_are_added_at_end_of_the_rescue_handlers_array
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError"]
+ result = @stargate.send(:rescue_handlers).collect(&:first)
+ assert_equal expected, result
+ end
+
+ def test_children_should_inherit_rescue_definitions_from_parents_and_child_rescue_should_be_appended
+ expected = ["WraithAttack", "WraithAttack", "NuclearExplosion", "MadRonon", "WeirdError", "CoolError"]
+ result = @cool_stargate.send(:rescue_handlers).collect(&:first)
+ assert_equal expected, result
+ end
+
+ def test_rescue_falls_back_to_exception_cause
+ @stargate.dispatch :fall_back_to_cause
+ assert_equal "dex", @stargate.result
+ end
+
+ def test_unhandled_exceptions
+ @stargate.dispatch(:crash)
+ assert_equal "unhandled", @stargate.result
+ end
+
+ def test_rescue_handles_loops_in_exception_cause_chain
+ @stargate.dispatch :looped_crash
+ assert_equal "unhandled", @stargate.result
+ end
+end