lua

A copy of the Lua development repository
Log | Files | Refs | README

coroutine.lua (32796B)


      1 -- $Id: testes/coroutine.lua $
      2 -- See Copyright Notice in file all.lua
      3 
      4 print "testing coroutines"
      5 
      6 local debug = require'debug'
      7 
      8 local f
      9 
     10 local main, ismain = coroutine.running()
     11 assert(type(main) == "thread" and ismain)
     12 assert(not coroutine.resume(main))
     13 assert(not coroutine.isyieldable(main) and not coroutine.isyieldable())
     14 assert(not pcall(coroutine.yield))
     15 
     16 
     17 -- trivial errors
     18 assert(not pcall(coroutine.resume, 0))
     19 assert(not pcall(coroutine.status, 0))
     20 
     21 
     22 -- tests for multiple yield/resume arguments
     23 
     24 local function eqtab (t1, t2)
     25   assert(#t1 == #t2)
     26   for i = 1, #t1 do
     27     local v = t1[i]
     28     assert(t2[i] == v)
     29   end
     30 end
     31 
     32 _G.x = nil   -- declare x
     33 _G.f = nil   -- declare f
     34 local function foo (a, ...)
     35   local x, y = coroutine.running()
     36   assert(x == f and y == false)
     37   -- next call should not corrupt coroutine (but must fail,
     38   -- as it attempts to resume the running coroutine)
     39   assert(coroutine.resume(f) == false)
     40   assert(coroutine.status(f) == "running")
     41   local arg = {...}
     42   assert(coroutine.isyieldable(x))
     43   for i=1,#arg do
     44     _G.x = {coroutine.yield(table.unpack(arg[i]))}
     45   end
     46   return table.unpack(a)
     47 end
     48 
     49 f = coroutine.create(foo)
     50 assert(coroutine.isyieldable(f))
     51 assert(type(f) == "thread" and coroutine.status(f) == "suspended")
     52 assert(string.find(tostring(f), "thread"))
     53 local s,a,b,c,d
     54 s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
     55 assert(coroutine.isyieldable(f))
     56 assert(s and a == nil and coroutine.status(f) == "suspended")
     57 s,a,b,c,d = coroutine.resume(f)
     58 eqtab(_G.x, {})
     59 assert(s and a == 1 and b == nil)
     60 assert(coroutine.isyieldable(f))
     61 s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
     62 eqtab(_G.x, {1, 2, 3})
     63 assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
     64 s,a,b,c,d = coroutine.resume(f, "xuxu")
     65 eqtab(_G.x, {"xuxu"})
     66 assert(s and a == 1 and b == 2 and c == 3 and d == nil)
     67 assert(coroutine.status(f) == "dead")
     68 s, a = coroutine.resume(f, "xuxu")
     69 assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
     70 
     71 _G.f = nil
     72 
     73 -- yields in tail calls
     74 local function foo (i) return coroutine.yield(i) end
     75 local f = coroutine.wrap(function ()
     76   for i=1,10 do
     77     assert(foo(i) == _G.x)
     78   end
     79   return 'a'
     80 end)
     81 for i=1,10 do _G.x = i; assert(f(i) == i) end
     82 _G.x = 'xuxu'; assert(f('xuxu') == 'a')
     83 
     84 _G.x = nil
     85 
     86 -- recursive
     87 local function pf (n, i)
     88   coroutine.yield(n)
     89   pf(n*i, i+1)
     90 end
     91 
     92 f = coroutine.wrap(pf)
     93 local s=1
     94 for i=1,10 do
     95   assert(f(1, 1) == s)
     96   s = s*i
     97 end
     98 
     99 -- sieve
    100 local function gen (n)
    101   return coroutine.wrap(function ()
    102     for i=2,n do coroutine.yield(i) end
    103   end)
    104 end
    105 
    106 
    107 local function filter (p, g)
    108   return coroutine.wrap(function ()
    109     while 1 do
    110       local n = g()
    111       if n == nil then return end
    112       if math.fmod(n, p) ~= 0 then coroutine.yield(n) end
    113     end
    114   end)
    115 end
    116 
    117 local x = gen(80)
    118 local a = {}
    119 while 1 do
    120   local n = x()
    121   if n == nil then break end
    122   table.insert(a, n)
    123   x = filter(n, x)
    124 end
    125 
    126 assert(#a == 22 and a[#a] == 79)
    127 x, a = nil
    128 
    129 
    130 do   -- "bug" in 5.4.2
    131   local function foo () foo () end    -- just create a stack overflow
    132   local co = coroutine.create(foo)
    133   -- running this coroutine would overflow the unsigned short 'nci', the
    134   -- counter of CallInfo structures available to the thread.
    135   -- (The issue only manifests in an 'assert'.)
    136   local st, msg = coroutine.resume(co)
    137   assert(string.find(msg, "stack overflow"))
    138   assert(coroutine.status(co) == "dead")
    139 end
    140 
    141 
    142 print("to-be-closed variables in coroutines")
    143 
    144 local function func2close (f)
    145   return setmetatable({}, {__close = f})
    146 end
    147 
    148 do
    149   -- ok to close a dead coroutine
    150   local co = coroutine.create(print)
    151   assert(coroutine.resume(co, "testing 'coroutine.close'"))
    152   assert(coroutine.status(co) == "dead")
    153   local st, msg = coroutine.close(co)
    154   assert(st and msg == nil)
    155   -- also ok to close it again
    156   st, msg = coroutine.close(co)
    157   assert(st and msg == nil)
    158 
    159 
    160   -- cannot close the running coroutine
    161   local st, msg = pcall(coroutine.close, coroutine.running())
    162   assert(not st and string.find(msg, "running"))
    163 
    164   local main = coroutine.running()
    165 
    166   -- cannot close a "normal" coroutine
    167   ;(coroutine.wrap(function ()
    168     local st, msg = pcall(coroutine.close, main)
    169     assert(not st and string.find(msg, "normal"))
    170   end))()
    171 
    172   -- cannot close a coroutine while closing it
    173   do
    174     local co
    175     co = coroutine.create(
    176       function()
    177         local x <close> = func2close(function()
    178             coroutine.close(co)   -- try to close it again
    179          end)
    180         coroutine.yield(20)
    181       end)
    182     local st, msg = coroutine.resume(co)
    183     assert(st and msg == 20)
    184     st, msg = coroutine.close(co)
    185     assert(not st and string.find(msg, "running coroutine"))
    186   end
    187 
    188   -- to-be-closed variables in coroutines
    189   local X
    190 
    191   -- closing a coroutine after an error
    192   local co = coroutine.create(error)
    193   local st, msg = coroutine.resume(co, 100)
    194   assert(not st and msg == 100)
    195   st, msg = coroutine.close(co)
    196   assert(not st and msg == 100)
    197   -- after closing, no more errors
    198   st, msg = coroutine.close(co)
    199   assert(st and msg == nil)
    200 
    201   co = coroutine.create(function ()
    202     local x <close> = func2close(function (self, err)
    203       assert(err == nil); X = false
    204     end)
    205     X = true
    206     coroutine.yield()
    207   end)
    208   coroutine.resume(co)
    209   assert(X)
    210   assert(coroutine.close(co))
    211   assert(not X and coroutine.status(co) == "dead")
    212 
    213   -- error closing a coroutine
    214   local x = 0
    215   co = coroutine.create(function()
    216     local y <close> = func2close(function (self,err)
    217       assert(err == 111)
    218       x = 200
    219       error(200)
    220     end)
    221     local x <close> = func2close(function (self, err)
    222       assert(err == nil); error(111)
    223     end)
    224     coroutine.yield()
    225   end)
    226   coroutine.resume(co)
    227   assert(x == 0)
    228   local st, msg = coroutine.close(co)
    229   assert(st == false and coroutine.status(co) == "dead" and msg == 200)
    230   assert(x == 200)
    231   -- after closing, no more errors
    232   st, msg = coroutine.close(co)
    233   assert(st and msg == nil)
    234 end
    235 
    236 do
    237   -- <close> versus pcall in coroutines
    238   local X = false
    239   local Y = false
    240   local function foo ()
    241     local x <close> = func2close(function (self, err)
    242       Y = debug.getinfo(2)
    243       X = err
    244     end)
    245     error(43)
    246   end
    247   local co = coroutine.create(function () return pcall(foo) end)
    248   local st1, st2, err = coroutine.resume(co)
    249   assert(st1 and not st2 and err == 43)
    250   assert(X == 43 and Y.what == "C")
    251 
    252   -- recovering from errors in __close metamethods
    253   local track = {}
    254 
    255   local function h (o)
    256     local hv <close> = o
    257     return 1
    258   end
    259 
    260   local function foo ()
    261     local x <close> = func2close(function(_,msg)
    262       track[#track + 1] = msg or false
    263       error(20)
    264     end)
    265     local y <close> = func2close(function(_,msg)
    266       track[#track + 1] = msg or false
    267       return 1000
    268     end)
    269     local z <close> = func2close(function(_,msg)
    270       track[#track + 1] = msg or false
    271       error(10)
    272     end)
    273     coroutine.yield(1)
    274     h(func2close(function(_,msg)
    275         track[#track + 1] = msg or false
    276         error(2)
    277       end))
    278   end
    279 
    280   local co = coroutine.create(pcall)
    281 
    282   local st, res = coroutine.resume(co, foo)    -- call 'foo' protected
    283   assert(st and res == 1)   -- yield 1
    284   local st, res1, res2 = coroutine.resume(co)   -- continue
    285   assert(coroutine.status(co) == "dead")
    286   assert(st and not res1 and res2 == 20)   -- last error (20)
    287   assert(track[1] == false and track[2] == 2 and track[3] == 10 and
    288          track[4] == 10)
    289 end
    290 
    291 
    292 -- yielding across C boundaries
    293 
    294 local co = coroutine.wrap(function()
    295        assert(not pcall(table.sort,{1,2,3}, coroutine.yield))
    296        assert(coroutine.isyieldable())
    297        coroutine.yield(20)
    298        return 30
    299      end)
    300 
    301 assert(co() == 20)
    302 assert(co() == 30)
    303 
    304 
    305 local f = function (s, i) return coroutine.yield(i) end
    306 
    307 local f1 = coroutine.wrap(function ()
    308              return xpcall(pcall, function (...) return ... end,
    309                function ()
    310                  local s = 0
    311                  for i in f, nil, 1 do pcall(function () s = s + i end) end
    312                  error({s})
    313                end)
    314            end)
    315 
    316 f1()
    317 for i = 1, 10 do assert(f1(i) == i) end
    318 local r1, r2, v = f1(nil)
    319 assert(r1 and not r2 and v[1] ==  (10 + 1)*10/2)
    320 
    321 
    322 local function f (a, b) a = coroutine.yield(a);  error{a + b} end
    323 local function g(x) return x[1]*2 end
    324 
    325 co = coroutine.wrap(function ()
    326        coroutine.yield(xpcall(f, g, 10, 20))
    327      end)
    328 
    329 assert(co() == 10)
    330 local r, msg = co(100)
    331 assert(not r and msg == 240)
    332 
    333 
    334 -- unyieldable C call
    335 do
    336   local function f (c)
    337           assert(not coroutine.isyieldable())
    338           return c .. c
    339         end
    340 
    341   local co = coroutine.wrap(function (c)
    342                assert(coroutine.isyieldable())
    343                local s = string.gsub("a", ".", f)
    344                return s
    345              end)
    346   assert(co() == "aa")
    347 end
    348 
    349 
    350 
    351 do   -- testing single trace of coroutines
    352   local X
    353   local co = coroutine.create(function ()
    354     coroutine.yield(10)
    355     return 20;
    356   end)
    357   local trace = {}
    358   local function dotrace (event)
    359     trace[#trace + 1] = event
    360   end
    361   debug.sethook(co, dotrace, "clr")
    362   repeat until not coroutine.resume(co)
    363   local correcttrace = {"call", "line", "call", "return", "line", "return"}
    364   assert(#trace == #correcttrace)
    365   for k, v in pairs(trace) do
    366     assert(v == correcttrace[k])
    367   end
    368 end
    369 
    370 -- errors in coroutines
    371 function foo ()
    372   assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
    373   assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
    374   coroutine.yield(3)
    375   error(foo)
    376 end
    377 
    378 function goo() foo() end
    379 x = coroutine.wrap(goo)
    380 assert(x() == 3)
    381 local a,b = pcall(x)
    382 assert(not a and b == foo)
    383 
    384 x = coroutine.create(goo)
    385 a,b = coroutine.resume(x)
    386 assert(a and b == 3)
    387 a,b = coroutine.resume(x)
    388 assert(not a and b == foo and coroutine.status(x) == "dead")
    389 a,b = coroutine.resume(x)
    390 assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
    391 
    392 goo = nil
    393 
    394 -- co-routines x for loop
    395 local function all (a, n, k)
    396   if k == 0 then coroutine.yield(a)
    397   else
    398     for i=1,n do
    399       a[k] = i
    400       all(a, n, k-1)
    401     end
    402   end
    403 end
    404 
    405 local a = 0
    406 for t in coroutine.wrap(function () all({}, 5, 4) end) do
    407   a = a+1
    408 end
    409 assert(a == 5^4)
    410 
    411 
    412 -- access to locals of collected corroutines
    413 local C = {}; setmetatable(C, {__mode = "kv"})
    414 local x = coroutine.wrap (function ()
    415             local a = 10
    416             local function f () a = a+10; return a end
    417             while true do
    418               a = a+1
    419               coroutine.yield(f)
    420             end
    421           end)
    422 
    423 C[1] = x;
    424 
    425 local f = x()
    426 assert(f() == 21 and x()() == 32 and x() == f)
    427 x = nil
    428 collectgarbage()
    429 assert(C[1] == undef)
    430 assert(f() == 43 and f() == 53)
    431 
    432 
    433 -- old bug: attempt to resume itself
    434 
    435 local function co_func (current_co)
    436   assert(coroutine.running() == current_co)
    437   assert(coroutine.resume(current_co) == false)
    438   coroutine.yield(10, 20)
    439   assert(coroutine.resume(current_co) == false)
    440   coroutine.yield(23)
    441   return 10
    442 end
    443 
    444 local co = coroutine.create(co_func)
    445 local a,b,c = coroutine.resume(co, co)
    446 assert(a == true and b == 10 and c == 20)
    447 a,b = coroutine.resume(co, co)
    448 assert(a == true and b == 23)
    449 a,b = coroutine.resume(co, co)
    450 assert(a == true and b == 10)
    451 assert(coroutine.resume(co, co) == false)
    452 assert(coroutine.resume(co, co) == false)
    453 
    454 
    455 -- other old bug when attempting to resume itself
    456 -- (trigger C-code assertions)
    457 do
    458   local A = coroutine.running()
    459   local B = coroutine.create(function() return coroutine.resume(A) end)
    460   local st, res = coroutine.resume(B)
    461   assert(st == true and res == false)
    462 
    463   local X = false
    464   A = coroutine.wrap(function()
    465     local _ <close> = func2close(function () X = true end)
    466     return pcall(A, 1)
    467   end)
    468   st, res = A()
    469   assert(not st and string.find(res, "non%-suspended") and X == true)
    470 end
    471 
    472 
    473 -- bug in 5.4.1
    474 do
    475   -- coroutine ran close metamethods with invalid status during a
    476   -- reset.
    477   local co
    478   co = coroutine.wrap(function()
    479     local x <close> = func2close(function() return pcall(co) end)
    480     error(111)
    481   end)
    482   local st, errobj = pcall(co)
    483   assert(not st and errobj == 111)
    484   st, errobj = pcall(co)
    485   assert(not st and string.find(errobj, "dead coroutine"))
    486 end
    487 
    488 
    489 -- attempt to resume 'normal' coroutine
    490 local co1, co2
    491 co1 = coroutine.create(function () return co2() end)
    492 co2 = coroutine.wrap(function ()
    493         assert(coroutine.status(co1) == 'normal')
    494         assert(not coroutine.resume(co1))
    495         coroutine.yield(3)
    496       end)
    497 
    498 a,b = coroutine.resume(co1)
    499 assert(a and b == 3)
    500 assert(coroutine.status(co1) == 'dead')
    501 
    502 -- infinite recursion of coroutines
    503 a = function(a) coroutine.wrap(a)(a) end
    504 assert(not pcall(a, a))
    505 a = nil
    506 
    507 
    508 -- access to locals of erroneous coroutines
    509 local x = coroutine.create (function ()
    510             local a = 10
    511             _G.F = function () a=a+1; return a end
    512             error('x')
    513           end)
    514 
    515 assert(not coroutine.resume(x))
    516 -- overwrite previous position of local `a'
    517 assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
    518 assert(_G.F() == 11)
    519 assert(_G.F() == 12)
    520 _G.F = nil
    521 
    522 
    523 if not T then
    524   (Message or print)
    525       ('\n >>> testC not active: skipping coroutine API tests <<<\n')
    526 else
    527   print "testing yields inside hooks"
    528 
    529   local turn
    530 
    531   local function fact (t, x)
    532     assert(turn == t)
    533     if x == 0 then return 1
    534     else return x*fact(t, x-1)
    535     end
    536   end
    537 
    538   local A, B = 0, 0
    539 
    540   local x = coroutine.create(function ()
    541     T.sethook("yield 0", "", 2)
    542     A = fact("A", 6)
    543   end)
    544 
    545   local y = coroutine.create(function ()
    546     T.sethook("yield 0", "", 3)
    547     B = fact("B", 7)
    548   end)
    549 
    550   while A==0 or B==0 do    -- A ~= 0 when 'x' finishes (similar for 'B','y')
    551     if A==0 then turn = "A"; assert(T.resume(x)) end
    552     if B==0 then turn = "B"; assert(T.resume(y)) end
    553 
    554     -- check that traceback works correctly after yields inside hooks
    555     debug.traceback(x)
    556     debug.traceback(y)
    557   end
    558 
    559   assert(B // A == 7)    -- fact(7) // fact(6)
    560 
    561   do   -- hooks vs. multiple values
    562     local done
    563     local function test (n)
    564       done = false
    565       return coroutine.wrap(function ()
    566         local a = {}
    567         for i = 1, n do a[i] = i end
    568         -- 'pushint' just to perturb the stack
    569         T.sethook("pushint 10; yield 0", "", 1)   -- yield at each op.
    570         local a1 = {table.unpack(a)}   -- must keep top between ops.
    571         assert(#a1 == n)
    572         for i = 1, n do assert(a[i] == i) end
    573         done = true
    574       end)
    575     end
    576     -- arguments to the coroutine are just to perturb its stack
    577     local co = test(0); while not done do co(30) end
    578     co = test(1); while not done do co(20, 10) end
    579     co = test(3); while not done do co() end
    580     co = test(100); while not done do co() end
    581   end
    582 
    583   local line = debug.getinfo(1, "l").currentline + 2    -- get line number
    584   local function foo ()
    585     local x = 10    --<< this line is 'line'
    586     x = x + 10
    587     _G.XX = x
    588   end
    589 
    590   -- testing yields in line hook
    591   local co = coroutine.wrap(function ()
    592     T.sethook("setglobal X; yield 0", "l", 0); foo(); return 10 end)
    593 
    594   _G.XX = nil;
    595   _G.X = nil; co(); assert(_G.X == line)
    596   _G.X = nil; co(); assert(_G.X == line + 1)
    597   _G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil)
    598   _G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20)
    599   assert(co() == 10)
    600   _G.X = nil
    601 
    602   -- testing yields in count hook
    603   co = coroutine.wrap(function ()
    604     T.sethook("yield 0", "", 1); foo(); return 10 end)
    605 
    606   _G.XX = nil;
    607   local c = 0
    608   repeat c = c + 1; local a = co() until a == 10
    609   assert(_G.XX == 20 and c >= 5)
    610 
    611   co = coroutine.wrap(function ()
    612     T.sethook("yield 0", "", 2); foo(); return 10 end)
    613 
    614   _G.XX = nil;
    615   local c = 0
    616   repeat c = c + 1; local a = co() until a == 10
    617   assert(_G.XX == 20 and c >= 5)
    618   _G.X = nil; _G.XX = nil
    619 
    620   do
    621     -- testing debug library on a coroutine suspended inside a hook
    622     -- (bug in 5.2/5.3)
    623     c = coroutine.create(function (a, ...)
    624       T.sethook("yield 0", "l")   -- will yield on next two lines
    625       local b = a
    626       return ...
    627     end)
    628 
    629     assert(coroutine.resume(c, 1, 2, 3))   -- start coroutine
    630     local n,v = debug.getlocal(c, 0, 1)    -- check its local
    631     assert(n == "a" and v == 1 and debug.getlocal(c, 0, 2) ~= "b")
    632     assert(debug.setlocal(c, 0, 1, 10))     -- test 'setlocal'
    633     local t = debug.getinfo(c, 0)        -- test 'getinfo'
    634     assert(t.currentline == t.linedefined + 2)
    635     assert(not debug.getinfo(c, 1))      -- no other level
    636     assert(coroutine.resume(c))          -- run next line
    637     local n,v = debug.getlocal(c, 0, 2)    -- check next local
    638     assert(n == "b" and v == 10)
    639     v = {coroutine.resume(c)}         -- finish coroutine
    640     assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef)
    641     assert(not coroutine.resume(c))
    642   end
    643 
    644   do
    645     -- testing debug library on last function in a suspended coroutine
    646     -- (bug in 5.2/5.3)
    647     local c = coroutine.create(function () T.testC("yield 1", 10, 20) end)
    648     local a, b = coroutine.resume(c)
    649     assert(a and b == 20)
    650     assert(debug.getinfo(c, 0).linedefined == -1)
    651     a, b = debug.getlocal(c, 0, 2)
    652     assert(b == 10)
    653   end
    654 
    655 
    656   print "testing coroutine API"
    657 
    658   -- reusing a thread
    659   assert(T.testC([[
    660     newthread      # create thread
    661     pushvalue 2    # push body
    662     pushstring 'a a a'  # push argument
    663     xmove 0 3 2   # move values to new thread
    664     resume -1, 1    # call it first time
    665     pushstatus
    666     xmove 3 0 0   # move results back to stack
    667     setglobal X    # result
    668     setglobal Y    # status
    669     pushvalue 2     # push body (to call it again)
    670     pushstring 'b b b'
    671     xmove 0 3 2
    672     resume -1, 1    # call it again
    673     pushstatus
    674     xmove 3 0 0
    675     return 1        # return result
    676   ]], function (...) return ... end) == 'b b b')
    677 
    678   assert(X == 'a a a' and Y == 'OK')
    679 
    680   X, Y = nil
    681 
    682 
    683   -- resuming running coroutine
    684   C = coroutine.create(function ()
    685         return T.testC([[
    686                  pushnum 10;
    687                  pushnum 20;
    688                  resume -3 2;
    689                  pushstatus
    690                  gettop;
    691                  return 3]], C)
    692       end)
    693   local a, b, c, d = coroutine.resume(C)
    694   assert(a == true and string.find(b, "non%-suspended") and
    695          c == "ERRRUN" and d == 4)
    696 
    697   a, b, c, d = T.testC([[
    698     rawgeti R !M    # get main thread
    699     pushnum 10;
    700     pushnum 20;
    701     resume -3 2;
    702     pushstatus
    703     gettop;
    704     return 4]])
    705   assert(a == coroutine.running() and string.find(b, "non%-suspended") and
    706          c == "ERRRUN" and d == 4)
    707 
    708 
    709   -- using a main thread as a coroutine  (dubious use!)
    710   local state = T.newstate()
    711 
    712   -- check that yielddable is working correctly
    713   assert(T.testC(state, "newthread; isyieldable -1; remove 1; return 1"))
    714 
    715   -- main thread is not yieldable
    716   assert(not T.testC(state, "rawgeti R !M; isyieldable -1; remove 1; return 1"))
    717 
    718   T.testC(state, "settop 0")
    719 
    720   T.loadlib(state, 1 | 2, 4)   -- load _G and 'package', preload 'coroutine'
    721 
    722   assert(T.doremote(state, [[
    723     coroutine = require'coroutine';
    724     X = function (x) coroutine.yield(x, 'BB'); return 'CC' end;
    725     return 'ok']]))
    726 
    727   local t = table.pack(T.testC(state, [[
    728     rawgeti R !M     # get main thread
    729     pushstring 'XX'
    730     getglobal X    # get function for body
    731     pushstring AA      # arg
    732     resume 1 1      # 'resume' shadows previous stack!
    733     gettop
    734     setglobal T    # top
    735     setglobal B    # second yielded value
    736     setglobal A    # fist yielded value
    737     rawgeti R !M     # get main thread
    738     pushnum 5       # arg (noise)
    739     resume 1 1      # after coroutine ends, previous stack is back
    740     pushstatus
    741     return *
    742   ]]))
    743   assert(t.n == 4 and t[2] == 'XX' and t[3] == 'CC' and t[4] == 'OK')
    744   assert(T.doremote(state, "return T") == '2')
    745   assert(T.doremote(state, "return A") == 'AA')
    746   assert(T.doremote(state, "return B") == 'BB')
    747 
    748   T.closestate(state)
    749 
    750   print'+'
    751 
    752 end
    753 
    754 
    755 -- leaving a pending coroutine open
    756 _G.TO_SURVIVE = coroutine.wrap(function ()
    757       local a = 10
    758       local x = function () a = a+1 end
    759       coroutine.yield()
    760     end)
    761 
    762 _G.TO_SURVIVE()
    763 
    764 
    765 if not _soft then
    766   -- bug (stack overflow)
    767   local lim = 1000000    -- stack limit; assume 32-bit machine
    768   local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1, lim + 5}
    769   for i = 1, #t do
    770     local j = t[i]
    771     local co = coroutine.create(function()
    772            return table.unpack({}, 1, j)
    773          end)
    774     local r, msg = coroutine.resume(co)
    775     -- must fail for unpacking larger than stack limit
    776     assert(j < lim or not r)
    777   end
    778 end
    779 
    780 
    781 assert(coroutine.running() == main)
    782 
    783 print"+"
    784 
    785 
    786 print"testing yields inside metamethods"
    787 
    788 local function val(x)
    789   if type(x) == "table" then return x.x else return x end
    790 end
    791 
    792 local mt = {
    793   __eq = function(a,b) coroutine.yield(nil, "eq"); return val(a) == val(b) end,
    794   __lt = function(a,b) coroutine.yield(nil, "lt"); return val(a) < val(b) end,
    795   __le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
    796   __add = function(a,b) coroutine.yield(nil, "add");
    797                         return val(a) + val(b) end,
    798   __sub = function(a,b) coroutine.yield(nil, "sub"); return val(a) - val(b) end,
    799   __mul = function(a,b) coroutine.yield(nil, "mul"); return val(a) * val(b) end,
    800   __div = function(a,b) coroutine.yield(nil, "div"); return val(a) / val(b) end,
    801   __idiv = function(a,b) coroutine.yield(nil, "idiv");
    802                          return val(a) // val(b) end,
    803   __pow = function(a,b) coroutine.yield(nil, "pow"); return val(a) ^ val(b) end,
    804   __mod = function(a,b) coroutine.yield(nil, "mod"); return val(a) % val(b) end,
    805   __unm = function(a,b) coroutine.yield(nil, "unm"); return -val(a) end,
    806   __bnot = function(a,b) coroutine.yield(nil, "bnot"); return ~val(a) end,
    807   __shl = function(a,b) coroutine.yield(nil, "shl");
    808                         return val(a) << val(b) end,
    809   __shr = function(a,b) coroutine.yield(nil, "shr");
    810                         return val(a) >> val(b) end,
    811   __band = function(a,b)
    812              coroutine.yield(nil, "band")
    813              return val(a) & val(b)
    814            end,
    815   __bor = function(a,b) coroutine.yield(nil, "bor");
    816                         return val(a) | val(b) end,
    817   __bxor = function(a,b) coroutine.yield(nil, "bxor");
    818                          return val(a) ~ val(b) end,
    819 
    820   __concat = function(a,b)
    821                coroutine.yield(nil, "concat");
    822                return val(a) .. val(b)
    823              end,
    824   __index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
    825   __newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
    826 }
    827 
    828 
    829 local function new (x)
    830   return setmetatable({x = x, k = {}}, mt)
    831 end
    832 
    833 
    834 local a = new(10)
    835 local b = new(12)
    836 local c = new"hello"
    837 
    838 local function run (f, t)
    839   local i = 1
    840   local c = coroutine.wrap(f)
    841   while true do
    842     local res, stat = c()
    843     if res then assert(t[i] == undef); return res, t end
    844     assert(stat == t[i])
    845     i = i + 1
    846   end
    847 end
    848 
    849 
    850 assert(run(function () if (a>=b) then return '>=' else return '<' end end,
    851        {"le", "sub"}) == "<")
    852 assert(run(function () if (a<=b) then return '<=' else return '>' end end,
    853        {"le", "sub"}) == "<=")
    854 assert(run(function () if (a==b) then return '==' else return '~=' end end,
    855        {"eq"}) == "~=")
    856 
    857 assert(run(function () return a & b + a end, {"add", "band"}) == 2)
    858 
    859 assert(run(function () return 1 + a end, {"add"}) == 11)
    860 assert(run(function () return a - 25 end, {"sub"}) == -15)
    861 assert(run(function () return 2 * a end, {"mul"}) == 20)
    862 assert(run(function () return a ^ 2 end, {"pow"}) == 100)
    863 assert(run(function () return a / 2 end, {"div"}) == 5)
    864 assert(run(function () return a % 6 end, {"mod"}) == 4)
    865 assert(run(function () return a // 3 end, {"idiv"}) == 3)
    866 
    867 assert(run(function () return a + b end, {"add"}) == 22)
    868 assert(run(function () return a - b end, {"sub"}) == -2)
    869 assert(run(function () return a * b end, {"mul"}) == 120)
    870 assert(run(function () return a ^ b end, {"pow"}) == 10^12)
    871 assert(run(function () return a / b end, {"div"}) == 10/12)
    872 assert(run(function () return a % b end, {"mod"}) == 10)
    873 assert(run(function () return a // b end, {"idiv"}) == 0)
    874 
    875 -- repeat tests with larger constants (to use 'K' opcodes)
    876 local a1000 = new(1000)
    877 
    878 assert(run(function () return a1000 + 1000 end, {"add"}) == 2000)
    879 assert(run(function () return a1000 - 25000 end, {"sub"}) == -24000)
    880 assert(run(function () return 2000 * a end, {"mul"}) == 20000)
    881 assert(run(function () return a1000 / 1000 end, {"div"}) == 1)
    882 assert(run(function () return a1000 % 600 end, {"mod"}) == 400)
    883 assert(run(function () return a1000 // 500 end, {"idiv"}) == 2)
    884 
    885 
    886 
    887 assert(run(function () return a % b end, {"mod"}) == 10)
    888 
    889 assert(run(function () return ~a & b end, {"bnot", "band"}) == ~10 & 12)
    890 assert(run(function () return a | b end, {"bor"}) == 10 | 12)
    891 assert(run(function () return a ~ b end, {"bxor"}) == 10 ~ 12)
    892 assert(run(function () return a << b end, {"shl"}) == 10 << 12)
    893 assert(run(function () return a >> b end, {"shr"}) == 10 >> 12)
    894 
    895 assert(run(function () return 10 & b end, {"band"}) == 10 & 12)
    896 assert(run(function () return a | 2 end, {"bor"}) == 10 | 2)
    897 assert(run(function () return a ~ 2 end, {"bxor"}) == 10 ~ 2)
    898 assert(run(function () return a >> 2 end, {"shr"}) == 10 >> 2)
    899 assert(run(function () return 1 >> a end, {"shr"}) == 1 >> 10)
    900 assert(run(function () return a << 2 end, {"shl"}) == 10 << 2)
    901 assert(run(function () return 1 << a end, {"shl"}) == 1 << 10)
    902 assert(run(function () return 2 ~ a end, {"bxor"}) == 2 ~ 10)
    903 
    904 
    905 assert(run(function () return a..b end, {"concat"}) == "1012")
    906 
    907 assert(run(function() return a .. b .. c .. a end,
    908        {"concat", "concat", "concat"}) == "1012hello10")
    909 
    910 assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
    911        {"concat", "concat", "concat"}) == "ab10chello12x")
    912 
    913 
    914 do   -- a few more tests for comparison operators
    915   local mt1 = {
    916     __le = function (a,b)
    917       coroutine.yield(10)
    918       return (val(a) <= val(b))
    919     end,
    920     __lt = function (a,b)
    921       coroutine.yield(10)
    922       return val(a) < val(b)
    923     end,
    924   }
    925   local mt2 = { __lt = mt1.__lt, __le = mt1.__le }
    926 
    927   local function run (f)
    928     local co = coroutine.wrap(f)
    929     local res
    930     repeat
    931       res = co()
    932     until res ~= 10
    933     return res
    934   end
    935 
    936   local function test ()
    937     local a1 = setmetatable({x=1}, mt1)
    938     local a2 = setmetatable({x=2}, mt2)
    939     assert(a1 < a2)
    940     assert(a1 <= a2)
    941     assert(1 < a2)
    942     assert(1 <= a2)
    943     assert(2 > a1)
    944     assert(2 >= a2)
    945     return true
    946   end
    947 
    948   run(test)
    949 
    950 end
    951 
    952 assert(run(function ()
    953              a.BB = print
    954              return a.BB
    955            end, {"nidx", "idx"}) == print)
    956 
    957 -- getuptable & setuptable
    958 do local _ENV = _ENV
    959   f = function () AAA = BBB + 1; return AAA end
    960 end
    961 local g = new(10); g.k.BBB = 10;
    962 debug.setupvalue(f, 1, g)
    963 assert(run(f, {"idx", "nidx", "idx"}) == 11)
    964 assert(g.k.AAA == 11)
    965 
    966 print"+"
    967 
    968 print"testing yields inside 'for' iterators"
    969 
    970 local f = function (s, i)
    971       if i%2 == 0 then coroutine.yield(nil, "for") end
    972       if i < s then return i + 1 end
    973     end
    974 
    975 assert(run(function ()
    976              local s = 0
    977              for i in f, 4, 0 do s = s + i end
    978              return s
    979            end, {"for", "for", "for"}) == 10)
    980 
    981 
    982 
    983 -- tests for coroutine API
    984 if T==nil then
    985   (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n')
    986   print "OK"; return
    987 end
    988 
    989 print('testing coroutine API')
    990 
    991 local function apico (...)
    992   local x = {...}
    993   return coroutine.wrap(function ()
    994     return T.testC(table.unpack(x))
    995   end)
    996 end
    997 
    998 local a = {apico(
    999 [[
   1000   pushstring errorcode
   1001   pcallk 1 0 2;
   1002   invalid command (should not arrive here)
   1003 ]],
   1004 [[return *]],
   1005 "stackmark",
   1006 error
   1007 )()}
   1008 assert(#a == 4 and
   1009        a[3] == "stackmark" and
   1010        a[4] == "errorcode" and
   1011        _G.status == "ERRRUN" and
   1012        _G.ctx == 2)       -- 'ctx' to pcallk
   1013 
   1014 local co = apico(
   1015   "pushvalue 2; pushnum 10; pcallk 1 2 3; invalid command;",
   1016   coroutine.yield,
   1017   "getglobal status; getglobal ctx; pushvalue 2; pushstring a; pcallk 1 0 4; invalid command",
   1018   "getglobal status; getglobal ctx; return *")
   1019 
   1020 assert(co() == 10)
   1021 assert(co(20, 30) == 'a')
   1022 a = {co()}
   1023 assert(#a == 10 and
   1024        a[2] == coroutine.yield and
   1025        a[5] == 20 and a[6] == 30 and
   1026        a[7] == "YIELD" and a[8] == 3 and
   1027        a[9] == "YIELD" and a[10] == 4)
   1028 assert(not pcall(co))   -- coroutine is dead now
   1029 
   1030 
   1031 f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;")
   1032 co = coroutine.wrap(function ()
   1033   assert(f() == 23); assert(f() == 23); return 10
   1034 end)
   1035 assert(co(23,16) == 5)
   1036 assert(co(23,16) == 5)
   1037 assert(co(23,16) == 10)
   1038 
   1039 
   1040 -- testing coroutines with C bodies
   1041 f = T.makeCfunc([[
   1042         pushnum 102
   1043 	yieldk	1 U2
   1044 	cannot be here!
   1045 ]],
   1046 [[      # continuation
   1047 	pushvalue U3   # accessing upvalues inside a continuation
   1048         pushvalue U4
   1049 	return *
   1050 ]], 23, "huu")
   1051 
   1052 
   1053 do  -- testing bug introduced in commit f407b3c4a
   1054   local X = false   -- flag "to be closed"
   1055   local coro = coroutine.wrap(T.testC)
   1056   -- runs it until 'pcallk' (that yields)
   1057   -- 4th argument (at index 4): object to be closed
   1058   local res1, res2 = coro(
   1059     [[
   1060       toclose 3   # this could break the next 'pcallk'
   1061       pushvalue 2   # push function 'yield' to call it
   1062       pushint 22; pushint 33    # arguments to yield
   1063       # calls 'yield' (2 args; 2 results; continuation function at index 4)
   1064       pcallk 2 2 4
   1065       invalid command (should not arrive here)
   1066     ]],   -- 1st argument (at index 1): code;
   1067     coroutine.yield,  -- (at index 2): function to be called
   1068     func2close(function () X = true end),   -- (index 3): TBC slot
   1069     "pushint 43; return 3"   -- (index 4): code for continuation function
   1070   )
   1071 
   1072   assert(res1 == 22 and res2 == 33 and not X)
   1073   local res1, res2, res3 = coro(34, "hi")  -- runs continuation function
   1074   assert(res1 == 34 and res2 == "hi" and res3 == 43 and X)
   1075 end
   1076 
   1077 x = coroutine.wrap(f)
   1078 assert(x() == 102)
   1079 eqtab({x()}, {23, "huu"})
   1080 
   1081 
   1082 f = T.makeCfunc[[pushstring 'a'; pushnum 102; yield 2; ]]
   1083 
   1084 a, b, c, d = T.testC([[newthread; pushvalue 2; xmove 0 3 1; resume 3 0;
   1085                        pushstatus; xmove 3 0 0;  resume 3 0; pushstatus;
   1086                        return 4; ]], f)
   1087 
   1088 assert(a == 'YIELD' and b == 'a' and c == 102 and d == 'OK')
   1089 
   1090 
   1091 -- testing chain of suspendable C calls
   1092 
   1093 local count = 3   -- number of levels
   1094 
   1095 f = T.makeCfunc([[
   1096   remove 1;             # remove argument
   1097   pushvalue U3;         # get selection function
   1098   call 0 1;             # call it  (result is 'f' or 'yield')
   1099   pushstring hello      # single argument for selected function
   1100   pushupvalueindex 2;   # index of continuation program
   1101   callk 1 -1 .;		# call selected function
   1102   errorerror		# should never arrive here
   1103 ]],
   1104 [[
   1105   # continuation program
   1106   pushnum 34	# return value
   1107   return *     # return all results
   1108 ]],
   1109 function ()     -- selection function
   1110   count = count - 1
   1111   if count == 0 then return coroutine.yield
   1112   else return f
   1113   end
   1114 end
   1115 )
   1116 
   1117 co = coroutine.wrap(function () return f(nil) end)
   1118 assert(co() == "hello")   -- argument to 'yield'
   1119 a = {co()}
   1120 -- three '34's (one from each pending C call)
   1121 assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
   1122 
   1123 
   1124 -- testing yields with continuations
   1125 
   1126 local y
   1127 
   1128 co = coroutine.wrap(function (...) return
   1129        T.testC([[ # initial function
   1130           yieldk 1 2
   1131           cannot be here!
   1132        ]],
   1133        [[  # 1st continuation
   1134          yieldk 0 3
   1135          cannot be here!
   1136        ]],
   1137        [[  # 2nd continuation
   1138          yieldk 0 4
   1139          cannot be here!
   1140        ]],
   1141        [[  # 3th continuation
   1142           pushvalue 6   # function which is last arg. to 'testC' here
   1143           pushnum 10; pushnum 20;
   1144           pcall 2 0 0   # call should throw an error and return to next line
   1145           pop 1		# remove error message
   1146           pushvalue 6
   1147           getglobal status; getglobal ctx
   1148           pcallk 2 2 5  # call should throw an error and jump to continuation
   1149           cannot be here!
   1150        ]],
   1151        [[  # 4th (and last) continuation
   1152          return *
   1153        ]],
   1154        -- function called by 3th continuation
   1155        function (a,b) x=a; y=b; error("errmsg") end,
   1156        ...
   1157 )
   1158 end)
   1159 
   1160 local a = {co(3,4,6)}
   1161 assert(a[1] == 6 and a[2] == undef)
   1162 a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 2)
   1163 a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 3)
   1164 a = {co(7,8)};
   1165 -- original arguments
   1166 assert(type(a[1]) == 'string' and type(a[2]) == 'string' and
   1167      type(a[3]) == 'string' and type(a[4]) == 'string' and
   1168      type(a[5]) == 'string' and type(a[6]) == 'function')
   1169 -- arguments left from fist resume
   1170 assert(a[7] == 3 and a[8] == 4)
   1171 -- arguments to last resume
   1172 assert(a[9] == 7 and a[10] == 8)
   1173 -- error message and nothing more
   1174 assert(a[11]:find("errmsg") and #a == 11)
   1175 -- check arguments to pcallk
   1176 assert(x == "YIELD" and y == 4)
   1177 
   1178 assert(not pcall(co))   -- coroutine should be dead
   1179 
   1180 _G.ctx = nil
   1181 _G.status = nil
   1182 
   1183 
   1184 -- bug in nCcalls
   1185 local co = coroutine.wrap(function ()
   1186   local a = {pcall(pcall,pcall,pcall,pcall,pcall,pcall,pcall,error,"hi")}
   1187   return pcall(assert, table.unpack(a))
   1188 end)
   1189 
   1190 local a = {co()}
   1191 assert(a[10] == "hi")
   1192 
   1193 print'OK'