1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
require 'test/unit'
class TestFiber < Test::Unit::TestCase
def test_normal
f = Fiber.current
assert_equal(:ok2,
Fiber.new{|e|
assert_equal(:ok1, e)
assert_equal(f, Fiber.prev)
Fiber.yield :ok2
}.yield(:ok1)
)
assert_equal([:a, :b], Fiber.new{|a, b| [a, b]}.yield(:a, :b))
end
def test_term
assert_equal(:ok, Fiber.new{:ok}.yield)
assert_equal([:a, :b, :c, :d, :e],
Fiber.new{
Fiber.new{
Fiber.new{
Fiber.new{
[:a]
}.yield + [:b]
}.yield + [:c]
}.yield + [:d]
}.yield + [:e])
end
def test_many_fibers
max = 10000
assert_equal(max, max.times{
Fiber.new{}
})
assert_equal(max,
max.times{|i|
Fiber.new{
}.yield
}
)
end
def test_many_fibers_with_threads
max = 1000
@cnt = 0
(1..100).map{|ti|
Thread.new{
max.times{|i|
Fiber.new{
@cnt += 1
}.yield
}
}
}.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.yield}.join # Fiber yielding across thread
}
assert_raise(FiberError){
f = Fiber.new{}
f.yield
f.yield
}
end
def test_loop
ary = []
f2 = nil
f1 = Fiber.new{
ary << f2.yield(:foo)
:bar
}
f2 = Fiber.new{
ary << f1.yield(:baz)
:ok
}
assert_equal(:ok, f1.yield)
assert_equal([:baz, :bar], ary)
end
def test_return
assert_raise(LocalJumpError){
Fiber.new do
return
end.yield
}
end
def test_throw
assert_raise(RuntimeError){
Fiber.new do
throw :a
end.yield
}
end
def test_with_callcc
c = nil
f1 = f2 = nil
f1 = Fiber.new do
callcc do |c2|
c = c2
f2.yield
end
:ok
end
f2 = Fiber.new do
c.call
end
assert_equal(f1.yield, :ok)
end
end
|