1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
# frozen_string_literal: true
require_relative "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
|