diff options
Diffstat (limited to 'spec/ruby/core/fiber/resume_spec.rb')
| -rw-r--r-- | spec/ruby/core/fiber/resume_spec.rb | 127 |
1 files changed, 78 insertions, 49 deletions
diff --git a/spec/ruby/core/fiber/resume_spec.rb b/spec/ruby/core/fiber/resume_spec.rb index 3fd3aed8fa..e183cc10d9 100644 --- a/spec/ruby/core/fiber/resume_spec.rb +++ b/spec/ruby/core/fiber/resume_spec.rb @@ -1,54 +1,83 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../../../shared/fiber/resume', __FILE__) - -with_feature :fiber do - describe "Fiber#resume" do - it_behaves_like :fiber_resume, :resume - end - - describe "Fiber#resume" do - it "returns control to the calling Fiber if called from one" do - fiber1 = Fiber.new { :fiber1 } - fiber2 = Fiber.new { fiber1.resume; :fiber2 } - fiber2.resume.should == :fiber2 - end - - with_feature :fork do - # Redmine #595 - it "executes the ensure clause" do - rd, wr = IO.pipe - - pid = Kernel::fork do - rd.close - f = Fiber.new do - begin - Fiber.yield - ensure - wr.write "executed" - end - end - - # The apparent issue is that when Fiber.yield executes, control - # "leaves" the "ensure block" and so the ensure clause should run. But - # control really does NOT leave the ensure block when Fiber.yield - # executes. It merely pauses there. To require ensure to run when a - # Fiber is suspended then makes ensure-in-a-Fiber-context different - # than ensure-in-a-Thread-context and this would be very confusing. - f.resume - - # When we execute the second #resume call, the ensure block DOES exit, - # the ensure clause runs. This is Ruby behavior as of 2.3.1. - f.resume - - exit 0 - end +require_relative '../../spec_helper' +require_relative 'shared/resume' + +describe "Fiber#resume" do + it_behaves_like :fiber_resume, :resume +end + +describe "Fiber#resume" do + it "runs until Fiber.yield" do + obj = mock('obj') + obj.should_not_receive(:do) + fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do } + fiber.resume + end + + it "resumes from the last call to Fiber.yield on subsequent invocations" do + fiber = Fiber.new { Fiber.yield :first; :second } + fiber.resume.should == :first + fiber.resume.should == :second + end + + it "sets the block parameters to its arguments on the first invocation" do + first = mock('first') + first.should_receive(:arg).with(:first).twice + + fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; } + fiber.resume :first + fiber.resume :second + end + + it "raises a FiberError if the Fiber tries to resume itself" do + fiber = Fiber.new { fiber.resume } + -> { fiber.resume }.should.raise(FiberError, /current fiber/) + end - wr.close - Process.waitpid pid + it "returns control to the calling Fiber if called from one" do + fiber1 = Fiber.new { :fiber1 } + fiber2 = Fiber.new { fiber1.resume; :fiber2 } + fiber2.resume.should == :fiber2 + end - rd.read.should == "executed" - rd.close + # Redmine #595 + it "executes the ensure clause" do + code = <<-RUBY + f = Fiber.new do + begin + Fiber.yield + ensure + puts "ensure executed" + end end - end + + # The apparent issue is that when Fiber.yield executes, control + # "leaves" the "ensure block" and so the ensure clause should run. But + # control really does NOT leave the ensure block when Fiber.yield + # executes. It merely pauses there. To require ensure to run when a + # Fiber is suspended then makes ensure-in-a-Fiber-context different + # than ensure-in-a-Thread-context and this would be very confusing. + f.resume + + # When we execute the second #resume call, the ensure block DOES exit, + # the ensure clause runs. + f.resume + + exit 0 + RUBY + + ruby_exe(code).should == "ensure executed\n" + end + + it "can work with Fiber#transfer" do + fiber1 = Fiber.new { true } + fiber2 = Fiber.new { fiber1.transfer; Fiber.yield 10 ; Fiber.yield 20; raise } + fiber2.resume.should == 10 + fiber2.resume.should == 20 + end + + it "raises a FiberError if the Fiber attempts to resume a resuming fiber" do + root_fiber = Fiber.current + fiber1 = Fiber.new { root_fiber.resume } + -> { fiber1.resume }.should.raise(FiberError, /attempt to resume a resuming fiber/) end end |
