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