ruby--ruby/test/ruby/test_fiber.rb

165 lines
3.2 KiB
Ruby

require 'test/unit'
require 'fiber'
require 'continuation'
class TestFiber < Test::Unit::TestCase
def test_normal
f = Fiber.current
assert_equal(:ok2,
Fiber.new{|e|
assert_equal(:ok1, e)
Fiber.yield :ok2
}.resume(:ok1)
)
assert_equal([:a, :b], Fiber.new{|a, b| [a, b]}.resume(:a, :b))
end
def test_term
assert_equal(:ok, Fiber.new{:ok}.resume)
assert_equal([:a, :b, :c, :d, :e],
Fiber.new{
Fiber.new{
Fiber.new{
Fiber.new{
[:a]
}.resume + [:b]
}.resume + [:c]
}.resume + [:d]
}.resume + [:e])
end
def test_many_fibers
max = 10000
assert_equal(max, max.times{
Fiber.new{}
})
assert_equal(max,
max.times{|i|
Fiber.new{
}.resume
}
)
end
def test_many_fibers_with_threads
max = 1000
@cnt = 0
(1..100).map{|ti|
Thread.new{
max.times{|i|
Fiber.new{
@cnt += 1
}.resume
}
}
}.each{|t|
t.join
}
assert_equal(:ok, :ok)
end
def test_error
assert_raise(ArgumentError){
Fiber.new # Fiber without block
}
assert_raise(FiberError){
f = Fiber.new{}
Thread.new{f.resume}.join # Fiber yielding across thread
}
assert_raise(FiberError){
f = Fiber.new{}
f.resume
f.resume
}
assert_raise(RuntimeError){
f = Fiber.new{
@c = callcc{|c| @c = c}
}.resume
@c.call # cross fiber callcc
}
assert_raise(RuntimeError){
Fiber.new{
raise
}.resume
}
assert_raise(FiberError){
Fiber.yield
}
assert_raise(FiberError){
fib = Fiber.new{
fib.resume
}
fib.resume
}
assert_raise(FiberError){
fib = Fiber.new{
Fiber.new{
fib.resume
}.resume
}
fib.resume
}
end
def test_return
assert_raise(LocalJumpError){
Fiber.new do
return
end.resume
}
end
def test_throw
assert_raise(ArgumentError){
Fiber.new do
throw :a
end.resume
}
end
def test_transfer
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
def test_tls
#
def tvar(var, val)
old = Thread.current[var]
begin
Thread.current[var] = val
yield
ensure
Thread.current[var] = old
end
end
fb = Fiber.new {
assert_equal(nil, Thread.current[:v]); tvar(:v, :x) {
assert_equal(:x, Thread.current[:v]); Fiber.yield
assert_equal(:x, Thread.current[:v]); }
assert_equal(nil, Thread.current[:v]); Fiber.yield
raise # unreachable
}
assert_equal(nil, Thread.current[:v]); tvar(:v,1) {
assert_equal(1, Thread.current[:v]); tvar(:v,3) {
assert_equal(3, Thread.current[:v]); fb.resume
assert_equal(3, Thread.current[:v]); }
assert_equal(1, Thread.current[:v]); }
assert_equal(nil, Thread.current[:v]); fb.resume
assert_equal(nil, Thread.current[:v]);
end
end