aboutsummaryrefslogtreecommitdiff
path: root/testes/coroutine.lua
diff options
context:
space:
mode:
Diffstat (limited to 'testes/coroutine.lua')
-rw-r--r--testes/coroutine.lua86
1 files changed, 77 insertions, 9 deletions
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index abc08039..4881d964 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -1,5 +1,5 @@
1-- $Id: testes/coroutine.lua $ 1-- $Id: testes/coroutine.lua $
2-- See Copyright Notice in file all.lua 2-- See Copyright Notice in file lua.h
3 3
4print "testing coroutines" 4print "testing coroutines"
5 5
@@ -156,12 +156,12 @@ do
156 st, msg = coroutine.close(co) 156 st, msg = coroutine.close(co)
157 assert(st and msg == nil) 157 assert(st and msg == nil)
158 158
159 local main = coroutine.running()
159 160
160 -- cannot close the running coroutine 161 -- cannot close 'main'
161 local st, msg = pcall(coroutine.close, coroutine.running()) 162 local st, msg = pcall(coroutine.close, main);
162 assert(not st and string.find(msg, "running")) 163 assert(not st and string.find(msg, "main"))
163 164
164 local main = coroutine.running()
165 165
166 -- cannot close a "normal" coroutine 166 -- cannot close a "normal" coroutine
167 ;(coroutine.wrap(function () 167 ;(coroutine.wrap(function ()
@@ -169,20 +169,19 @@ do
169 assert(not st and string.find(msg, "normal")) 169 assert(not st and string.find(msg, "normal"))
170 end))() 170 end))()
171 171
172 -- cannot close a coroutine while closing it 172 do -- close a coroutine while closing it
173 do
174 local co 173 local co
175 co = coroutine.create( 174 co = coroutine.create(
176 function() 175 function()
177 local x <close> = func2close(function() 176 local x <close> = func2close(function()
178 coroutine.close(co) -- try to close it again 177 coroutine.close(co) -- close it again
179 end) 178 end)
180 coroutine.yield(20) 179 coroutine.yield(20)
181 end) 180 end)
182 local st, msg = coroutine.resume(co) 181 local st, msg = coroutine.resume(co)
183 assert(st and msg == 20) 182 assert(st and msg == 20)
184 st, msg = coroutine.close(co) 183 st, msg = coroutine.close(co)
185 assert(not st and string.find(msg, "running coroutine")) 184 assert(st and msg == nil)
186 end 185 end
187 186
188 -- to-be-closed variables in coroutines 187 -- to-be-closed variables in coroutines
@@ -289,6 +288,56 @@ do
289end 288end
290 289
291 290
291do print("coroutines closing itself")
292 global <const> coroutine, string, os
293 global <const> assert, error, pcall
294
295 local X = nil
296
297 local function new ()
298 return coroutine.create(function (what)
299
300 local <close>var = func2close(function (t, err)
301 if what == "yield" then
302 coroutine.yield()
303 elseif what == "error" then
304 error(200)
305 else
306 X = "Ok"
307 return X
308 end
309 end)
310
311 -- do an unprotected call so that coroutine becomes non-yieldable
312 string.gsub("a", "a", function ()
313 assert(not coroutine.isyieldable())
314 -- do protected calls while non-yieldable, to add recovery
315 -- entries (setjmp) to the stack
316 assert(pcall(pcall, function ()
317 -- 'close' works even while non-yieldable
318 coroutine.close() -- close itself
319 os.exit(false) -- not reacheable
320 end))
321 end)
322 end)
323 end
324
325 local co = new()
326 local st, msg = coroutine.resume(co, "ret")
327 assert(st and msg == nil)
328 assert(X == "Ok")
329
330 local co = new()
331 local st, msg = coroutine.resume(co, "error")
332 assert(not st and msg == 200)
333
334 local co = new()
335 local st, msg = coroutine.resume(co, "yield")
336 assert(not st and string.find(msg, "attempt to yield"))
337
338end
339
340
292-- yielding across C boundaries 341-- yielding across C boundaries
293 342
294local co = coroutine.wrap(function() 343local co = coroutine.wrap(function()
@@ -505,6 +554,25 @@ assert(not pcall(a, a))
505a = nil 554a = nil
506 555
507 556
557do
558 -- bug in 5.4: thread can use message handler higher in the stack
559 -- than the variable being closed
560 local c = coroutine.create(function()
561 local clo <close> = setmetatable({}, {__close=function()
562 local x = 134 -- will overwrite message handler
563 error(x)
564 end})
565 -- yields coroutine but leaves a new message handler for it,
566 -- that would be used when closing the coroutine (except that it
567 -- will be overwritten)
568 xpcall(coroutine.yield, function() return "XXX" end)
569 end)
570
571 assert(coroutine.resume(c)) -- start coroutine
572 local st, msg = coroutine.close(c)
573 assert(not st and msg == 134)
574end
575
508-- access to locals of erroneous coroutines 576-- access to locals of erroneous coroutines
509local x = coroutine.create (function () 577local x = coroutine.create (function ()
510 local a = 10 578 local a = 10