Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add spec for Fiber#raise #809

Merged
merged 2 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions core/fiber/fixtures/classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module FiberSpecs

class NewFiberToRaise
def self.raise(*args)
fiber = Fiber.new { Fiber.yield }
fiber.resume
fiber.raise(*args)
end
end

class CustomError < StandardError; end
end
76 changes: 76 additions & 0 deletions core/fiber/raise_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../../shared/kernel/raise'

ruby_version_is "2.7" do
describe "Fiber#raise" do
it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise
end

describe "Fiber#raise" do
it 'raises RuntimeError by default' do
-> { FiberSpecs::NewFiberToRaise.raise }.should raise_error(RuntimeError)
end

it "raises FiberError if Fiber is not born" do
fiber = Fiber.new { true }
-> { fiber.raise }.should raise_error(FiberError, "cannot raise exception on unborn fiber")
end

it "raises FiberError if Fiber is dead" do
fiber = Fiber.new { true }
fiber.resume
-> { fiber.raise }.should raise_error(FiberError, "dead fiber called")
end

it 'accepts error class' do
-> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should raise_error(FiberSpecs::CustomError)
end

it 'accepts error message' do
-> { FiberSpecs::NewFiberToRaise.raise "error message" }.should raise_error(RuntimeError, "error message")
end

it 'does not accept array of backtrace information only' do
-> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should raise_error(TypeError)
end

it 'does not accept integer' do
-> { FiberSpecs::NewFiberToRaise.raise 100 }.should raise_error(TypeError)
end

it 'accepts error class with error message' do
-> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error')
end

it 'accepts error class with with error message and backtrace information' do
-> {
FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
}.should raise_error(FiberSpecs::CustomError) { |e|
e.message.should == 'test error'
e.backtrace.should == ['foo', 'boo']
}
end

it 'does not accept only error message and backtrace information' do
-> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should raise_error(TypeError)
end

it "raises a FiberError if invoked from a different Thread" do
fiber = Fiber.new { Fiber.yield }
fiber.resume
Thread.new do
-> {
fiber.raise
}.should raise_error(FiberError, "fiber called across threads")
end.join
end

it "kills Fiber" do
fiber = Fiber.new { Fiber.yield :first; :second }
fiber.resume
-> { fiber.raise }.should raise_error
-> { fiber.resume }.should raise_error(FiberError, "dead fiber called")
end
end
end
45 changes: 34 additions & 11 deletions shared/kernel/raise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,43 @@ def initialize
end

it "re-raises a previously rescued exception without overwriting the backtrace" do
begin
initial_raise_line = __LINE__; @object.raise 'raised'
rescue => raised
begin
raise_again_line = __LINE__; @object.raise raised
rescue => raised_again
# This spec is written using #backtrace and matching the line number
# from the string, as backtrace_locations is a more advanced
# method that is not always supported by implementations.
# This spec is written using #backtrace and matching the line number
# from the string, as backtrace_locations is a more advanced
# method that is not always supported by implementations.
#
initial_raise_line = nil
raise_again_line = nil
raised_again = nil

raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
if defined?(FiberSpecs::NewFiberToRaise) and @object == FiberSpecs::NewFiberToRaise
fiber = Fiber.new do
begin
initial_raise_line = __LINE__; Fiber.yield
rescue => raised
begin
raise_again_line = __LINE__; Fiber.yield raised
rescue => raised_again
raised_again
end
end
end
fiber.resume
raised = fiber.raise 'raised'
raised_again = fiber.raise raised
else
begin
initial_raise_line = __LINE__; @object.raise 'raised'
rescue => raised
begin
raise_again_line = __LINE__; @object.raise raised
rescue => raised_again
raised_again
end
end
end

raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
end

it "allows Exception, message, and backtrace parameters" do
Expand Down