begin $fiber_test_activity = __FILE__ assert('Fiber.new') do f = Fiber.new{} assert_kind_of Fiber, f end assert('Fiber#resume') do f = Fiber.new{|x| x } assert_equal 2, f.resume(2) end assert('Fiber#transfer') do ary = [] f2 = nil f1 = Fiber.new{ ary << f2.transfer(:foo) :ok } f2 = Fiber.new{ ary << f1.transfer(:baz) :ng } assert_equal(:ok, f1.transfer) assert_equal([:baz], ary) assert_false f1.alive? end assert('Fiber#alive?') do f = Fiber.new{ Fiber.yield } f.resume assert_true f.alive? f.resume assert_false f.alive? end assert('Fiber#==') do root = Fiber.current assert_equal root, root assert_equal root, Fiber.current assert_false root != Fiber.current f = Fiber.new { assert_false root == Fiber.current } f.resume assert_false f == root assert_true f != root end assert('Fiber.yield') do f = Fiber.new{|x| Fiber.yield x } assert_equal 3, f.resume(3) assert_true f.alive? end assert('FiberError') do assert_equal StandardError, FiberError.superclass end assert('Fiber iteration') do f1 = Fiber.new{ [1,2,3].each{|x| Fiber.yield(x)} } f2 = Fiber.new{ [9,8,7].each{|x| Fiber.yield(x)} } a = [] 3.times { a << f1.resume a << f2.resume } assert_equal [1,9,2,8,3,7], a end assert('Fiber with splat in the block argument list') { assert_equal([1], Fiber.new{|*x|x}.resume(1)) } assert('Fiber raises on resume when dead') do assert_raise(FiberError) do f = Fiber.new{} f.resume assert_false f.alive? f.resume end end assert('Yield raises when called on root fiber') do assert_raise(FiberError) { Fiber.yield } end assert('Double resume of Fiber') do f1 = Fiber.new {} f2 = Fiber.new { f1.resume assert_raise(FiberError) { f2.resume } Fiber.yield 0 } assert_equal 0, f2.resume f2.resume assert_false f1.alive? assert_false f2.alive? end assert('Recursive resume of Fiber') do f1, f2 = nil, nil f1 = Fiber.new { assert_raise(FiberError) { f2.resume } } f2 = Fiber.new { f1.resume Fiber.yield 0 } f3 = Fiber.new { f2.resume } assert_equal 0, f3.resume f2.resume assert_false f1.alive? assert_false f2.alive? assert_false f3.alive? end assert('Root fiber resume') do root = Fiber.current assert_raise(FiberError) { root.resume } f = Fiber.new { assert_raise(FiberError) { root.resume } } f.resume assert_false f.alive? end assert('Fiber without block') do assert_raise(ArgumentError) { Fiber.new } end assert('Transfer to self.') do result = [] f = Fiber.new { result << :start; f.transfer; result << :end } f.transfer assert_equal [:start, :end], result result = [] f = Fiber.new { result << :start; f.transfer; result << :end } f.resume assert_equal [:start, :end], result end assert('Resume transferred fiber') do f = Fiber.new { assert_raise(FiberError) { f.resume } } f.transfer end assert('Root fiber transfer.') do result = nil root = Fiber.current f = Fiber.new { result = :ok root.transfer } f.transfer assert_true f.alive? assert_equal :ok, result end assert('Break nested fiber with root fiber transfer') do root = Fiber.current result = nil f2 = nil f1 = Fiber.new { root.transfer(f2.transfer) result = :f1 } f2 = Fiber.new { result = :to_root root.transfer :from_f2 result = :f2 } assert_equal :from_f2, f1.transfer assert_equal :to_root, result assert_equal :f2, f2.transfer assert_equal :f2, result assert_false f2.alive? assert_equal nil, f1.transfer assert_equal :f1, f1.transfer assert_equal :f1, result assert_false f1.alive? end assert('CRuby Fiber#transfer test.') do ary = [] f2 = nil f1 = Fiber.new{ ary << f2.transfer(:foo) :ok } f2 = Fiber.new{ ary << f1.transfer(:baz) :ng } assert_equal :ok, f1.transfer assert_equal [:baz], ary end ensure $fiber_test_activity = nil end