diff options
Diffstat (limited to 'spec/ruby/language/rescue_spec.rb')
| -rw-r--r-- | spec/ruby/language/rescue_spec.rb | 155 |
1 files changed, 133 insertions, 22 deletions
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb index 4d164b38c6..cf16d8f6f8 100644 --- a/spec/ruby/language/rescue_spec.rb +++ b/spec/ruby/language/rescue_spec.rb @@ -52,6 +52,16 @@ describe "The rescue keyword" do RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception end + it 'using a safely navigated setter method on a nil target' do + target = nil + begin + raise SpecificExampleException, "Raising this to be handled below" + rescue SpecificExampleException => target&.captured_error + :caught + end.should == :caught + target.should == nil + end + it 'using a setter method' do RescueSpecs::SetterCaptor.should_capture_exception end @@ -61,6 +71,82 @@ describe "The rescue keyword" do end end + describe 'capturing in a local variable (that defines it)' do + it 'captures successfully in a method' do + ScratchPad.record [] + + def a + raise "message" + rescue => e + ScratchPad << e.message + end + + a + ScratchPad.recorded.should == ["message"] + end + + it 'captures successfully in a block' do + ScratchPad.record [] + + p = proc do + raise "message" + rescue => e + ScratchPad << e.message + end + + p.call + ScratchPad.recorded.should == ["message"] + end + + it 'captures successfully in a class' do + ScratchPad.record [] + + class RescueSpecs::C + raise "message" + rescue => e + ScratchPad << e.message + end + + ScratchPad.recorded.should == ["message"] + end + + it 'captures successfully in a module' do + ScratchPad.record [] + + module RescueSpecs::M + raise "message" + rescue => e + ScratchPad << e.message + end + + ScratchPad.recorded.should == ["message"] + end + + it 'captures sucpcessfully in a singleton class' do + ScratchPad.record [] + + class << Object.new + raise "message" + rescue => e + ScratchPad << e.message + end + + ScratchPad.recorded.should == ["message"] + end + + it 'captures successfully at the top-level' do + ScratchPad.record [] + loaded_features = $".dup + begin + require_relative 'fixtures/rescue/top_level' + + ScratchPad.recorded.should == ["message"] + ensure + $".replace loaded_features + end + end + end + it "returns value from `rescue` if an exception was raised" do begin raise @@ -100,7 +186,7 @@ describe "The rescue keyword" do rescue *exception_list caught_it = true end - caught_it.should be_true + caught_it.should == true caught = [] [->{raise ArbitraryException}, ->{raise SpecificExampleException}].each do |block| begin @@ -111,10 +197,22 @@ describe "The rescue keyword" do end caught.size.should == 2 exception_list.each do |exception_class| - caught.map{|e| e.class}.should include(exception_class) + caught.map{|e| e.class}.should.include?(exception_class) end end + it "converts the splatted list of exceptions using #to_a" do + exceptions = mock("to_a") + exceptions.should_receive(:to_a).and_return(exception_list) + caught_it = false + begin + raise SpecificExampleException, "not important" + rescue *exceptions + caught_it = true + end + caught_it.should == true + end + it "can combine a splatted list of exceptions with a literal list of exceptions" do caught_it = false begin @@ -122,7 +220,7 @@ describe "The rescue keyword" do rescue ArbitraryException, *exception_list caught_it = true end - caught_it.should be_true + caught_it.should == true caught = [] [->{raise ArbitraryException}, ->{raise SpecificExampleException}].each do |block| begin @@ -133,7 +231,7 @@ describe "The rescue keyword" do end caught.size.should == 2 exception_list.each do |exception_class| - caught.map{|e| e.class}.should include(exception_class) + caught.map{|e| e.class}.should.include?(exception_class) end end @@ -143,7 +241,7 @@ describe "The rescue keyword" do raise OtherCustomException, "not rescued!" rescue *exception_list end - end.should raise_error(OtherCustomException) + end.should.raise(OtherCustomException) end it "can rescue different types of exceptions in different ways" do @@ -179,7 +277,7 @@ describe "The rescue keyword" do rescue ArgumentError end rescue StandardError => e - e.backtrace.first.should include ":in `raise_standard_error'" + e.backtrace.first.should =~ /:in [`'](?:RescueSpecs\.)?raise_standard_error'/ else fail("exception wasn't handled by the correct rescue block") end @@ -247,7 +345,7 @@ describe "The rescue keyword" do ScratchPad << :else end ruby - }.should raise_error(SyntaxError, /else without rescue is useless/) + }.should.raise(SyntaxError, /else without rescue is useless/) end it "will not execute an else block if an exception was raised" do @@ -315,7 +413,7 @@ describe "The rescue keyword" do ScratchPad << :two raise SpecificExampleException, "an error from else" end - end.should raise_error(SpecificExampleException) + end.should.raise(SpecificExampleException) ScratchPad.recorded.should == [:one, :two] end @@ -347,7 +445,7 @@ describe "The rescue keyword" do rescue ScratchPad << :caught end - }.should raise_error(exception.class) + }.should.raise(exception.class) end ScratchPad.recorded.should == [] end @@ -378,7 +476,7 @@ describe "The rescue keyword" do raise "error" rescue rescuer end - }.should raise_error(TypeError) { |e| + }.should.raise(TypeError) { |e| e.message.should =~ /class or module required for rescue clause/ } end @@ -390,7 +488,7 @@ describe "The rescue keyword" do raise "error" rescue *rescuer end - }.should raise_error(TypeError) { |e| + }.should.raise(TypeError) { |e| e.message.should =~ /class or module required for rescue clause/ } end @@ -410,7 +508,7 @@ describe "The rescue keyword" do raise "from block" rescue (raise "from rescue expression") end - }.should raise_error(RuntimeError, "from rescue expression") { |e| + }.should.raise(RuntimeError, "from rescue expression") { |e| e.cause.message.should == "from block" } end @@ -444,7 +542,7 @@ describe "The rescue keyword" do :caught } ruby - }.should raise_error(SyntaxError) + }.should.raise(SyntaxError) end it "allows rescue in 'do end' block" do @@ -465,10 +563,25 @@ describe "The rescue keyword" do end it "requires the 'rescue' in method arguments to be wrapped in parens" do - -> { eval '1.+(1 rescue 1)' }.should raise_error(SyntaxError) + -> { eval '1.+(1 rescue 1)' }.should.raise(SyntaxError) eval('1.+((1 rescue 1))').should == 2 end + ruby_version_is "3.4" do + it "does not introduce extra backtrace entries" do + def foo + begin + raise "oops" + rescue + return caller(0, 2) + end + end + line = __LINE__ + foo[0].should =~ /#{__FILE__}:#{line-3}:in 'foo'/ + foo[1].should =~ /#{__FILE__}:#{line+2}:in 'block/ + end + end + describe "inline form" do it "can be inlined" do a = 1/0 rescue 1 @@ -480,7 +593,7 @@ describe "The rescue keyword" do eval <<-ruby a = 1 rescue RuntimeError 2 ruby - }.should raise_error(SyntaxError) + }.should.raise(SyntaxError) end it "rescues only StandardError and its subclasses" do @@ -489,17 +602,15 @@ describe "The rescue keyword" do -> { a = raise(Exception) rescue 1 - }.should raise_error(Exception) + }.should.raise(Exception) end - ruby_version_is "2.7" do - it "rescues with multiple assignment" do + it "rescues with multiple assignment" do - a, b = raise rescue [1, 2] + a, b = raise rescue [1, 2] - a.should == 1 - b.should == 2 - end + a.should == 1 + b.should == 2 end end end |
