Skip to content

Commit f84b436

Browse files
Add specs for Fiber.schedule and Fiber.current_scheduler (#1388)
Fiber.schedule and Fiber.current_scheduler had no specs. Cover the RuntimeError raised when no scheduler is set, that the scheduler's #fiber hook is called and its return value is what Fiber.schedule hands back, and that Fiber.schedule works from inside a non-blocking Fiber. Fiber.current_scheduler returns the scheduler only when the current Fiber is non-blocking, which is what separates it from Fiber.scheduler. Cover the root Fiber, blocking and non-blocking Fibers.
1 parent 0f44fd5 commit f84b436

3 files changed

Lines changed: 141 additions & 0 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
require_relative '../../spec_helper'
2+
require_relative 'fixtures/scheduler'
3+
4+
describe "Fiber.current_scheduler" do
5+
it "returns nil when no scheduler is set" do
6+
Fiber.scheduler.should == nil
7+
Fiber.current_scheduler.should == nil
8+
end
9+
10+
describe "when a scheduler is set" do
11+
before :each do
12+
@scheduler = FiberSpecs::LoggingScheduler.new
13+
Fiber.set_scheduler(@scheduler)
14+
end
15+
16+
after :each do
17+
Fiber.set_scheduler(nil)
18+
end
19+
20+
it "returns nil on the root Fiber, which is blocking" do
21+
Fiber.current_scheduler.should == nil
22+
end
23+
24+
it "returns the scheduler inside a non-blocking Fiber" do
25+
seen = nil
26+
Fiber.new(blocking: false) { seen = Fiber.current_scheduler }.resume
27+
seen.should.equal?(@scheduler)
28+
end
29+
30+
it "returns nil inside a blocking Fiber, where Fiber.scheduler still returns the scheduler" do
31+
seen = nil
32+
Fiber.new(blocking: true) { seen = [Fiber.scheduler, Fiber.current_scheduler] }.resume
33+
seen.should == [@scheduler, nil]
34+
end
35+
36+
it "returns nil inside a blocking Fiber nested in a non-blocking Fiber" do
37+
seen = nil
38+
Fiber.new(blocking: false) do
39+
Fiber.new(blocking: true) { seen = Fiber.current_scheduler }.resume
40+
end.resume
41+
seen.should == nil
42+
end
43+
44+
it "returns the scheduler inside a non-blocking Fiber nested in a blocking Fiber" do
45+
seen = nil
46+
Fiber.new(blocking: true) do
47+
Fiber.new(blocking: false) { seen = Fiber.current_scheduler }.resume
48+
end.resume
49+
seen.should.equal?(@scheduler)
50+
end
51+
52+
it "returns nil inside Fiber.blocking in a non-blocking Fiber" do
53+
seen = nil
54+
Fiber.new(blocking: false) { Fiber.blocking { seen = Fiber.current_scheduler } }.resume
55+
seen.should == nil
56+
end
57+
58+
it "returns the scheduler again after Fiber.blocking returns" do
59+
seen = nil
60+
Fiber.new(blocking: false) do
61+
Fiber.blocking { }
62+
seen = Fiber.current_scheduler
63+
end.resume
64+
seen.should.equal?(@scheduler)
65+
end
66+
end
67+
end

core/fiber/fixtures/scheduler.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ def block(*args)
1111
Fiber.yield
1212
end
1313

14+
def fiber(*args, &block)
15+
@events << { event: :fiber, fiber: Fiber.current, args: args }
16+
Fiber.new(blocking: false, &block).tap(&:resume)
17+
end
18+
1419
def io_wait(*args)
1520
@events << { event: :io_wait, fiber: Fiber.current, args: args }
1621
Fiber.yield

core/fiber/schedule_spec.rb

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
require_relative '../../spec_helper'
2+
require_relative 'fixtures/scheduler'
3+
4+
describe "Fiber.schedule" do
5+
describe "when no scheduler is set" do
6+
it "raises a RuntimeError" do
7+
Fiber.scheduler.should == nil
8+
9+
-> {
10+
Fiber.schedule { }
11+
}.should.raise(RuntimeError)
12+
end
13+
end
14+
15+
describe "when a scheduler is set" do
16+
before :each do
17+
@scheduler = FiberSpecs::LoggingScheduler.new
18+
Fiber.set_scheduler(@scheduler)
19+
end
20+
21+
after :each do
22+
Fiber.set_scheduler(nil)
23+
end
24+
25+
it "calls the scheduler's #fiber hook" do
26+
Fiber.schedule { }
27+
@scheduler.events.map { |event| event[:event] }.should == [:fiber]
28+
end
29+
30+
it "returns the Fiber which runs the block" do
31+
scheduled = nil
32+
fiber = Fiber.schedule { scheduled = Fiber.current }
33+
fiber.should.equal?(scheduled)
34+
end
35+
36+
it "can be called from inside a non-blocking Fiber" do
37+
inner = nil
38+
39+
outer = Fiber.new(blocking: false) do
40+
inner = Fiber.schedule { }
41+
end
42+
outer.resume
43+
44+
inner.should.is_a?(Fiber)
45+
end
46+
47+
it "uses the scheduler of the Thread owning the Fiber it is called from" do
48+
seen = nil
49+
50+
outer = Fiber.new(blocking: false) do
51+
Fiber.schedule { seen = Fiber.scheduler }
52+
end
53+
outer.resume
54+
55+
seen.should.equal?(@scheduler)
56+
end
57+
58+
it "runs the block in a Fiber which sees the scheduler as its current scheduler" do
59+
seen = nil
60+
61+
outer = Fiber.new(blocking: false) do
62+
Fiber.schedule { seen = Fiber.current_scheduler }
63+
end
64+
outer.resume
65+
66+
seen.should.equal?(@scheduler)
67+
end
68+
end
69+
end

0 commit comments

Comments
 (0)