coroutine.lua 31 KB

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