coroutine.lua 29 KB

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