1assert('Fiber.new') do
2  f = Fiber.new{}
3  assert_kind_of Fiber, f
4end
5
6assert('Fiber#resume') do
7  f = Fiber.new{|x| x }
8  assert_equal 2, f.resume(2)
9end
10
11assert('Fiber#transfer') do
12  f2 = nil
13  f1 = Fiber.new do |v|
14    Fiber.yield v
15    f2.transfer
16  end
17  f2 = Fiber.new do
18    f1.transfer(1)
19    f1.transfer(1)
20    Fiber.yield 2
21  end
22  assert_equal 1, f2.resume
23  assert_raise(FiberError) { f2.resume }
24  assert_equal 2, f2.transfer
25  assert_raise(FiberError) { f1.resume }
26  f1.transfer
27  f2.resume
28  assert_false f1.alive?
29  assert_false f2.alive?
30end
31
32assert('Fiber#alive?') do
33  f = Fiber.new{ Fiber.yield }
34  f.resume
35  assert_true f.alive?
36  f.resume
37  assert_false f.alive?
38end
39
40assert('Fiber#==') do
41  root = Fiber.current
42  assert_equal root, root
43  assert_equal root, Fiber.current
44  assert_false root != Fiber.current
45  f = Fiber.new {
46    assert_false root == Fiber.current
47  }
48  f.resume
49  assert_false f == root
50  assert_true f != root
51end
52
53assert('Fiber.yield') do
54  f = Fiber.new{|x| Fiber.yield x }
55  assert_equal 3, f.resume(3)
56  assert_true f.alive?
57end
58
59assert('FiberError') do
60  assert_equal StandardError, FiberError.superclass
61end
62
63assert('Fiber iteration') do
64  f1 = Fiber.new{
65    [1,2,3].each{|x| Fiber.yield(x)}
66  }
67  f2 = Fiber.new{
68    [9,8,7].each{|x| Fiber.yield(x)}
69  }
70  a = []
71  3.times {
72    a << f1.resume
73    a << f2.resume
74  }
75  assert_equal [1,9,2,8,3,7], a
76end
77
78assert('Fiber with splat in the block argument list') {
79  Fiber.new{|*x|x}.resume(1) == [1]
80}
81
82assert('Fiber raises on resume when dead') do
83  assert_raise(FiberError) do
84    f = Fiber.new{}
85    f.resume
86    assert_false f.alive?
87    f.resume
88  end
89end
90
91assert('Yield raises when called on root fiber') do
92  assert_raise(FiberError) { Fiber.yield }
93end
94
95assert('Double resume of Fiber') do
96  f1 = Fiber.new {}
97  f2 = Fiber.new {
98    f1.resume
99    assert_raise(FiberError) { f2.resume }
100    Fiber.yield 0
101  }
102  assert_equal 0, f2.resume
103  f2.resume
104  assert_false f1.alive?
105  assert_false f2.alive?
106end
107
108assert('Recursive resume of Fiber') do
109  f1, f2 = nil, nil
110  f1 = Fiber.new { assert_raise(FiberError) { f2.resume } }
111  f2 = Fiber.new {
112    f1.resume
113    Fiber.yield 0
114  }
115  f3 = Fiber.new {
116    f2.resume
117  }
118  assert_equal 0, f3.resume
119  f2.resume
120  assert_false f1.alive?
121  assert_false f2.alive?
122  assert_false f3.alive?
123end
124
125assert('Root fiber resume') do
126  root = Fiber.current
127  assert_raise(FiberError) { root.resume }
128  f = Fiber.new {
129    assert_raise(FiberError) { root.resume }
130  }
131  f.resume
132  assert_false f.alive?
133end
134
135assert('Fiber without block') do
136  assert_raise(ArgumentError) { Fiber.new }
137end
138
139
140assert('Transfer to self.') do
141  result = []
142  f = Fiber.new { result << :start; f.transfer; result << :end  }
143  f.transfer
144  assert_equal [:start, :end], result
145
146  result = []
147  f = Fiber.new { result << :start; f.transfer; result << :end  }
148  f.resume
149  assert_equal [:start, :end], result
150end
151
152assert('Resume transferred fiber') do
153  f = Fiber.new {
154    assert_raise(FiberError) { f.resume }
155  }
156  f.transfer
157end
158
159assert('Root fiber transfer.') do
160  result = nil
161  root = Fiber.current
162  f = Fiber.new {
163    result = :ok
164    root.transfer
165  }
166  f.resume
167  assert_true f.alive?
168  assert_equal :ok, result
169end
170
171assert('Break nested fiber with root fiber transfer') do
172  root = Fiber.current
173
174  result = nil
175  f2 = nil
176  f1 = Fiber.new {
177    Fiber.yield f2.resume
178    result = :f1
179  }
180  f2 = Fiber.new {
181    result = :to_root
182    root.transfer :from_f2
183    result = :f2
184  }
185  assert_equal :from_f2, f1.resume
186  assert_equal :to_root, result
187  assert_equal :f2, f2.transfer
188  assert_equal :f2, result
189  assert_false f2.alive?
190  assert_equal :f1, f1.resume
191  assert_equal :f1, result
192  assert_false f1.alive?
193end
194
195assert('CRuby Fiber#transfer test.') do
196  ary = []
197  f2 = nil
198  f1 = Fiber.new{
199    ary << f2.transfer(:foo)
200    :ok
201  }
202  f2 = Fiber.new{
203    ary << f1.transfer(:baz)
204    :ng
205  }
206  assert_equal :ok, f1.transfer
207  assert_equal [:baz], ary
208end
209