calog/vendor/mruby/mrbgems/mruby-fiber/test/fiber2.rb
2026-07-04 20:25:00 -05:00

155 lines
4.8 KiB
Ruby
Vendored

# This file tests fiber switching crossing C functions
unless RUBY_ENGINE == "mruby"
class Fiber
alias resume_by_c_func resume
alias resume_by_c_method resume
class << self
alias yield_by_c_func yield
def yield_by_c_method(*args)
raise FiberError, "ycan't cross C function boundary"
end
end
end
def Proc.c_tunnel
yield
end
end
begin
$fiber_test_activity = __FILE__
assert('Call Fiber#resume nested with C') do
assert_equal "ok1", Fiber.new { Fiber.new { "ok1" }.resume_by_c_func }.resume_by_c_func
assert_equal "ok2", Fiber.new { Fiber.new { "ok2" }.resume_by_c_method }.resume_by_c_func
assert_equal "ok3", Fiber.new { Fiber.new { "ok3" }.resume_by_c_func }.resume_by_c_method
assert_equal "ok4", Fiber.new { Fiber.new { "ok4" }.resume_by_c_method }.resume_by_c_method
assert_equal "ok5", Fiber.new { Proc.c_tunnel { Fiber.new { "ok5" }.resume_by_c_func } }.resume_by_c_func
assert_equal "ok6", Fiber.new { Proc.c_tunnel { Fiber.new { "ok6" }.resume_by_c_method } }.resume_by_c_func
assert_equal "ok7", Fiber.new { Proc.c_tunnel { Fiber.new { "ok7" }.resume_by_c_func } }.resume_by_c_method
assert_equal "ok8", Fiber.new { Proc.c_tunnel { Fiber.new { "ok8" }.resume_by_c_method } }.resume_by_c_method
assert_equal "ok9", Fiber.new { Proc.c_tunnel { Fiber.new { "ok9" }.resume } }.resume_by_c_func
assert_equal "ok10", Fiber.new { Proc.c_tunnel { Fiber.new { "ok10" }.resume } }.resume_by_c_method
end
assert('Call Fiber#resume and Fiber.yield mixed with C.') do
assert_equal 1, Fiber.new { Fiber.yield 1 }.resume_by_c_func
assert_equal 2, Fiber.new { Fiber.yield 2 }.resume_by_c_method
assert_equal 3, Fiber.new { Fiber.yield_by_c_func 3 }.resume
assert_equal 4, Fiber.new { Fiber.yield_by_c_func 4 }.resume_by_c_func
assert_equal 5, Fiber.new { Fiber.yield_by_c_func 5 }.resume_by_c_method
assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume }
assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume_by_c_func }
assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume_by_c_method }
result = []
f1 = Fiber.new { result << Fiber.new { Fiber.yield 1; "bad" }.resume_by_c_func; 2 }
f2 = Fiber.new { result << f1.resume; 3 }
result << f2.resume
assert_equal [1, 2, 3], result
f1 = Fiber.new {
-> {
Fiber.yield 1
Fiber.yield_by_c_func 2
f2 = Fiber.new {
-> {
Fiber.yield_by_c_func 3
Fiber.yield 4
Fiber.yield_by_c_func 5
Fiber.yield 6
}.call
7
}
Fiber.yield f2.resume_by_c_func
Fiber.yield f2.resume
Fiber.yield f2.resume_by_c_method
Fiber.yield f2.resume
Fiber.yield f2.resume_by_c_func
Fiber.yield 8
}.call
Fiber.yield 9
10
}
result = []
10.times { result << f1.resume }
assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], result
end
assert('Call Fiber#resume and Fiber.yield mixed with C and raising exceptions') do
f = Fiber.new do
raise ZeroDivisionError
rescue
Fiber.yield "rescue"
"pass1"
ensure
Fiber.yield "ensure"
end
assert_equal "rescue", f.resume_by_c_method
assert_equal "ensure", f.resume_by_c_method
assert_equal "pass1", f.resume_by_c_method
assert_raise(FiberError) { f.resume_by_c_method }
f = Fiber.new do
raise ZeroDivisionError
rescue
Fiber.yield "rescue"
"pass2"
ensure
Fiber.yield "ensure"
end
assert_equal "rescue", f.resume_by_c_func
assert_equal "ensure", f.resume_by_c_func
assert_equal "pass2", f.resume_by_c_func
assert_raise(FiberError) { f.resume_by_c_func }
f2 = Fiber.new do
-> do
Fiber.yield 1
raise "3"
ensure
Fiber.yield 2
end.call
"NOT REACH 1"
end
f1 = Fiber.new do
Fiber.yield f2.resume_by_c_func
begin
Fiber.yield f2.resume
Fiber.yield f2.resume_by_c_method
Fiber.yield "NOT REACH 2"
rescue => e
Fiber.yield e.message
Fiber.yield 4
ensure
Fiber.yield 5
end
Fiber.yield 6
7
end
result = []
7.times { result << f1.resume }
assert_equal [1, 2, "3", 4, 5, 6, 7], result
end
assert('Call Fiber#transfer with C') do
assert_equal "ok1", Fiber.new { Fiber.new { "ok1" }.resume_by_c_method }.transfer
assert_equal "ok2", Fiber.new { Fiber.new { "ok2" }.resume_by_c_func }.transfer
assert_raise(FiberError) { Proc.c_tunnel { Fiber.new { "BAD!" }.transfer } }
b = Fiber.current
a = Fiber.new {
Proc.c_tunnel {
Fiber.new {
b.transfer
}.resume
}
}
assert_raise(FiberError) { a.transfer }
end
ensure
$fiber_test_activity = nil
end