db.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. -- $Id: db.lua,v 1.79 2016/11/07 13:02:34 roberto Exp $
  2. -- See Copyright Notice in file all.lua
  3. -- testing debug library
  4. local debug = require "debug"
  5. local function dostring(s) return assert(load(s))() end
  6. print"testing debug library and debug information"
  7. do
  8. local a=1
  9. end
  10. assert(not debug.gethook())
  11. local testline = 19 -- line where 'test' is defined
  12. function test (s, l, p) -- this must be line 19
  13. collectgarbage() -- avoid gc during trace
  14. local function f (event, line)
  15. assert(event == 'line')
  16. local l = table.remove(l, 1)
  17. if p then print(l, line) end
  18. assert(l == line, "wrong trace!!")
  19. end
  20. debug.sethook(f,"l"); load(s)(); debug.sethook()
  21. assert(#l == 0)
  22. end
  23. do
  24. assert(not pcall(debug.getinfo, print, "X")) -- invalid option
  25. assert(not debug.getinfo(1000)) -- out of range level
  26. assert(not debug.getinfo(-1)) -- out of range level
  27. local a = debug.getinfo(print)
  28. assert(a.what == "C" and a.short_src == "[C]")
  29. a = debug.getinfo(print, "L")
  30. assert(a.activelines == nil)
  31. local b = debug.getinfo(test, "SfL")
  32. assert(b.name == nil and b.what == "Lua" and b.linedefined == testline and
  33. b.lastlinedefined == b.linedefined + 10 and
  34. b.func == test and not string.find(b.short_src, "%["))
  35. assert(b.activelines[b.linedefined + 1] and
  36. b.activelines[b.lastlinedefined])
  37. assert(not b.activelines[b.linedefined] and
  38. not b.activelines[b.lastlinedefined + 1])
  39. end
  40. -- test file and string names truncation
  41. a = "function f () end"
  42. local function dostring (s, x) return load(s, x)() end
  43. dostring(a)
  44. assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
  45. dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
  46. assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
  47. dostring(a..string.format("; %s=1", string.rep('p', 400)))
  48. assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
  49. dostring("\n"..a)
  50. assert(debug.getinfo(f).short_src == '[string "..."]')
  51. dostring(a, "")
  52. assert(debug.getinfo(f).short_src == '[string ""]')
  53. dostring(a, "@xuxu")
  54. assert(debug.getinfo(f).short_src == "xuxu")
  55. dostring(a, "@"..string.rep('p', 1000)..'t')
  56. assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
  57. dostring(a, "=xuxu")
  58. assert(debug.getinfo(f).short_src == "xuxu")
  59. dostring(a, string.format("=%s", string.rep('x', 500)))
  60. assert(string.find(debug.getinfo(f).short_src, "^x*$"))
  61. dostring(a, "=")
  62. assert(debug.getinfo(f).short_src == "")
  63. a = nil; f = nil;
  64. repeat
  65. local g = {x = function ()
  66. local a = debug.getinfo(2)
  67. assert(a.name == 'f' and a.namewhat == 'local')
  68. a = debug.getinfo(1)
  69. assert(a.name == 'x' and a.namewhat == 'field')
  70. return 'xixi'
  71. end}
  72. local f = function () return 1+1 and (not 1 or g.x()) end
  73. assert(f() == 'xixi')
  74. g = debug.getinfo(f)
  75. assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
  76. function f (x, name) -- local!
  77. name = name or 'f'
  78. local a = debug.getinfo(1)
  79. assert(a.name == name and a.namewhat == 'local')
  80. return x
  81. end
  82. -- breaks in different conditions
  83. if 3>4 then break end; f()
  84. if 3<4 then a=1 else break end; f()
  85. while 1 do local x=10; break end; f()
  86. local b = 1
  87. if 3>4 then return math.sin(1) end; f()
  88. a = 3<4; f()
  89. a = 3<4 or 1; f()
  90. repeat local x=20; if 4>3 then f() else break end; f() until 1
  91. g = {}
  92. f(g).x = f(2) and f(10)+f(9)
  93. assert(g.x == f(19))
  94. function g(x) if not x then return 3 end return (x('a', 'x')) end
  95. assert(g(f) == 'a')
  96. until 1
  97. test([[if
  98. math.sin(1)
  99. then
  100. a=1
  101. else
  102. a=2
  103. end
  104. ]], {2,3,4,7})
  105. test([[--
  106. if nil then
  107. a=1
  108. else
  109. a=2
  110. end
  111. ]], {2,5,6})
  112. test([[a=1
  113. repeat
  114. a=a+1
  115. until a==3
  116. ]], {1,3,4,3,4})
  117. test([[ do
  118. return
  119. end
  120. ]], {2})
  121. test([[local a
  122. a=1
  123. while a<=3 do
  124. a=a+1
  125. end
  126. ]], {1,2,3,4,3,4,3,4,3,5})
  127. test([[while math.sin(1) do
  128. if math.sin(1)
  129. then break
  130. end
  131. end
  132. a=1]], {1,2,3,6})
  133. test([[for i=1,3 do
  134. a=i
  135. end
  136. ]], {1,2,1,2,1,2,1,3})
  137. test([[for i,v in pairs{'a','b'} do
  138. a=tostring(i) .. v
  139. end
  140. ]], {1,2,1,2,1,3})
  141. test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
  142. print'+'
  143. -- invalid levels in [gs]etlocal
  144. assert(not pcall(debug.getlocal, 20, 1))
  145. assert(not pcall(debug.setlocal, -1, 1, 10))
  146. -- parameter names
  147. local function foo (a,b,...) local d, e end
  148. local co = coroutine.create(foo)
  149. assert(debug.getlocal(foo, 1) == 'a')
  150. assert(debug.getlocal(foo, 2) == 'b')
  151. assert(not debug.getlocal(foo, 3))
  152. assert(debug.getlocal(co, foo, 1) == 'a')
  153. assert(debug.getlocal(co, foo, 2) == 'b')
  154. assert(not debug.getlocal(co, foo, 3))
  155. assert(not debug.getlocal(print, 1))
  156. -- varargs
  157. local function foo (a, ...)
  158. local t = table.pack(...)
  159. for i = 1, t.n do
  160. local n, v = debug.getlocal(1, -i)
  161. assert(n == "(*vararg)" and v == t[i])
  162. end
  163. assert(not debug.getlocal(1, -(t.n + 1)))
  164. assert(not debug.setlocal(1, -(t.n + 1), 30))
  165. if t.n > 0 then
  166. (function (x)
  167. assert(debug.setlocal(2, -1, x) == "(*vararg)")
  168. assert(debug.setlocal(2, -t.n, x) == "(*vararg)")
  169. end)(430)
  170. assert(... == 430)
  171. end
  172. end
  173. foo()
  174. foo(print)
  175. foo(200, 3, 4)
  176. local a = {}
  177. for i = 1, (_soft and 100 or 1000) do a[i] = i end
  178. foo(table.unpack(a))
  179. a = nil
  180. -- access to vararg in non-vararg function
  181. local function foo () return debug.getlocal(1, -1) end
  182. assert(not foo(10))
  183. do -- test hook presence in debug info
  184. assert(not debug.gethook())
  185. local count = 0
  186. local function f ()
  187. assert(debug.getinfo(1).namewhat == "hook")
  188. local sndline = string.match(debug.traceback(), "\n(.-)\n")
  189. assert(string.find(sndline, "hook"))
  190. count = count + 1
  191. end
  192. debug.sethook(f, "l")
  193. local a = 0
  194. _ENV.a = a
  195. a = 1
  196. debug.sethook()
  197. assert(count == 4)
  198. end
  199. a = {}; L = nil
  200. local glob = 1
  201. local oldglob = glob
  202. debug.sethook(function (e,l)
  203. collectgarbage() -- force GC during a hook
  204. local f, m, c = debug.gethook()
  205. assert(m == 'crl' and c == 0)
  206. if e == "line" then
  207. if glob ~= oldglob then
  208. L = l-1 -- get the first line where "glob" has changed
  209. oldglob = glob
  210. end
  211. elseif e == "call" then
  212. local f = debug.getinfo(2, "f").func
  213. a[f] = 1
  214. else assert(e == "return")
  215. end
  216. end, "crl")
  217. function f(a,b)
  218. collectgarbage()
  219. local _, x = debug.getlocal(1, 1)
  220. local _, y = debug.getlocal(1, 2)
  221. assert(x == a and y == b)
  222. assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
  223. assert(debug.setlocal(2, 4, "maçã") == "B")
  224. x = debug.getinfo(2)
  225. assert(x.func == g and x.what == "Lua" and x.name == 'g' and
  226. x.nups == 2 and string.find(x.source, "^@.*db%.lua$"))
  227. glob = glob+1
  228. assert(debug.getinfo(1, "l").currentline == L+1)
  229. assert(debug.getinfo(1, "l").currentline == L+2)
  230. end
  231. function foo()
  232. glob = glob+1
  233. assert(debug.getinfo(1, "l").currentline == L+1)
  234. end; foo() -- set L
  235. -- check line counting inside strings and empty lines
  236. _ = 'alo\
  237. alo' .. [[
  238. ]]
  239. --[[
  240. ]]
  241. assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
  242. function g(...)
  243. local arg = {...}
  244. do local a,b,c; a=math.sin(40); end
  245. local feijao
  246. local AAAA,B = "xuxu", "mamão"
  247. f(AAAA,B)
  248. assert(AAAA == "pera" and B == "maçã")
  249. do
  250. local B = 13
  251. local x,y = debug.getlocal(1,5)
  252. assert(x == 'B' and y == 13)
  253. end
  254. end
  255. g()
  256. assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
  257. -- tests for manipulating non-registered locals (C and Lua temporaries)
  258. local n, v = debug.getlocal(0, 1)
  259. assert(v == 0 and n == "(*temporary)")
  260. local n, v = debug.getlocal(0, 2)
  261. assert(v == 2 and n == "(*temporary)")
  262. assert(not debug.getlocal(0, 3))
  263. assert(not debug.getlocal(0, 0))
  264. function f()
  265. assert(select(2, debug.getlocal(2,3)) == 1)
  266. assert(not debug.getlocal(2,4))
  267. debug.setlocal(2, 3, 10)
  268. return 20
  269. end
  270. function g(a,b) return (a+1) + f() end
  271. assert(g(0,0) == 30)
  272. debug.sethook(nil);
  273. assert(debug.gethook() == nil)
  274. -- testing access to function arguments
  275. local function collectlocals (level)
  276. local tab = {}
  277. for i = 1, math.huge do
  278. local n, v = debug.getlocal(level + 1, i)
  279. if not (n and string.find(n, "^[a-zA-Z0-9_]+$")) then
  280. break -- consider only real variables
  281. end
  282. tab[n] = v
  283. end
  284. return tab
  285. end
  286. X = nil
  287. a = {}
  288. function a:f (a, b, ...) local arg = {...}; local c = 13 end
  289. debug.sethook(function (e)
  290. assert(e == "call")
  291. dostring("XX = 12") -- test dostring inside hooks
  292. -- testing errors inside hooks
  293. assert(not pcall(load("a='joao'+1")))
  294. debug.sethook(function (e, l)
  295. assert(debug.getinfo(2, "l").currentline == l)
  296. local f,m,c = debug.gethook()
  297. assert(e == "line")
  298. assert(m == 'l' and c == 0)
  299. debug.sethook(nil) -- hook is called only once
  300. assert(not X) -- check that
  301. X = collectlocals(2)
  302. end, "l")
  303. end, "c")
  304. a:f(1,2,3,4,5)
  305. assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
  306. assert(XX == 12)
  307. assert(debug.gethook() == nil)
  308. -- testing access to local variables in return hook (bug in 5.2)
  309. do
  310. local function foo (a, b)
  311. do local x,y,z end
  312. local c, d = 10, 20
  313. return
  314. end
  315. local function aux ()
  316. if debug.getinfo(2).name == "foo" then
  317. foo = nil -- to signal that it found 'foo'
  318. local tab = {a = 100, b = 200, c = 10, d = 20}
  319. for n, v in pairs(collectlocals(2)) do
  320. assert(tab[n] == v)
  321. tab[n] = nil
  322. end
  323. assert(next(tab) == nil) -- 'tab' must be empty
  324. end
  325. end
  326. debug.sethook(aux, "r"); foo(100, 200); debug.sethook()
  327. assert(foo == nil)
  328. end
  329. -- testing upvalue access
  330. local function getupvalues (f)
  331. local t = {}
  332. local i = 1
  333. while true do
  334. local name, value = debug.getupvalue(f, i)
  335. if not name then break end
  336. assert(not t[name])
  337. t[name] = value
  338. i = i + 1
  339. end
  340. return t
  341. end
  342. local a,b,c = 1,2,3
  343. local function foo1 (a) b = a; return c end
  344. local function foo2 (x) a = x; return c+b end
  345. assert(not debug.getupvalue(foo1, 3))
  346. assert(not debug.getupvalue(foo1, 0))
  347. assert(not debug.setupvalue(foo1, 3, "xuxu"))
  348. local t = getupvalues(foo1)
  349. assert(t.a == nil and t.b == 2 and t.c == 3)
  350. t = getupvalues(foo2)
  351. assert(t.a == 1 and t.b == 2 and t.c == 3)
  352. assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
  353. assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
  354. -- upvalues of C functions are allways "called" "" (the empty string)
  355. assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")
  356. -- testing count hooks
  357. local a=0
  358. debug.sethook(function (e) a=a+1 end, "", 1)
  359. a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
  360. debug.sethook(function (e) a=a+1 end, "", 4)
  361. a=0; for i=1,1000 do end; assert(250 < a and a < 255)
  362. local f,m,c = debug.gethook()
  363. assert(m == "" and c == 4)
  364. debug.sethook(function (e) a=a+1 end, "", 4000)
  365. a=0; for i=1,1000 do end; assert(a == 0)
  366. do
  367. debug.sethook(print, "", 2^24 - 1) -- count upperbound
  368. local f,m,c = debug.gethook()
  369. assert(({debug.gethook()})[3] == 2^24 - 1)
  370. end
  371. debug.sethook()
  372. -- tests for tail calls
  373. local function f (x)
  374. if x then
  375. assert(debug.getinfo(1, "S").what == "Lua")
  376. assert(debug.getinfo(1, "t").istailcall == true)
  377. local tail = debug.getinfo(2)
  378. assert(tail.func == g1 and tail.istailcall == true)
  379. assert(debug.getinfo(3, "S").what == "main")
  380. print"+"
  381. end
  382. end
  383. function g(x) return f(x) end
  384. function g1(x) g(x) end
  385. local function h (x) local f=g1; return f(x) end
  386. h(true)
  387. local b = {}
  388. debug.sethook(function (e) table.insert(b, e) end, "cr")
  389. h(false)
  390. debug.sethook()
  391. local res = {"return", -- first return (from sethook)
  392. "call", "tail call", "call", "tail call",
  393. "return", "return",
  394. "call", -- last call (to sethook)
  395. }
  396. for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
  397. b = 0
  398. debug.sethook(function (e)
  399. if e == "tail call" then
  400. b = b + 1
  401. assert(debug.getinfo(2, "t").istailcall == true)
  402. else
  403. assert(debug.getinfo(2, "t").istailcall == false)
  404. end
  405. end, "c")
  406. h(false)
  407. debug.sethook()
  408. assert(b == 2) -- two tail calls
  409. lim = _soft and 3000 or 30000
  410. local function foo (x)
  411. if x==0 then
  412. assert(debug.getinfo(2).what == "main")
  413. local info = debug.getinfo(1)
  414. assert(info.istailcall == true and info.func == foo)
  415. else return foo(x-1)
  416. end
  417. end
  418. foo(lim)
  419. print"+"
  420. -- testing local function information
  421. co = load[[
  422. local A = function ()
  423. return x
  424. end
  425. return
  426. ]]
  427. local a = 0
  428. -- 'A' should be visible to debugger only after its complete definition
  429. debug.sethook(function (e, l)
  430. if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(*temporary)")
  431. elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
  432. end
  433. end, "l")
  434. co() -- run local function definition
  435. debug.sethook() -- turn off hook
  436. assert(a == 2) -- ensure all two lines where hooked
  437. -- testing traceback
  438. assert(debug.traceback(print) == print)
  439. assert(debug.traceback(print, 4) == print)
  440. assert(string.find(debug.traceback("hi", 4), "^hi\n"))
  441. assert(string.find(debug.traceback("hi"), "^hi\n"))
  442. assert(not string.find(debug.traceback("hi"), "'debug.traceback'"))
  443. assert(string.find(debug.traceback("hi", 0), "'debug.traceback'"))
  444. assert(string.find(debug.traceback(), "^stack traceback:\n"))
  445. do -- C-function names in traceback
  446. local st, msg = (function () return pcall end)()(debug.traceback)
  447. assert(st == true and string.find(msg, "pcall"))
  448. end
  449. -- testing nparams, nups e isvararg
  450. local t = debug.getinfo(print, "u")
  451. assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
  452. t = debug.getinfo(function (a,b,c) end, "u")
  453. assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
  454. t = debug.getinfo(function (a,b,...) return t[a] end, "u")
  455. assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
  456. t = debug.getinfo(1) -- main
  457. assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
  458. debug.getupvalue(t.func, 1) == "_ENV")
  459. -- testing debugging of coroutines
  460. local function checktraceback (co, p, level)
  461. local tb = debug.traceback(co, nil, level)
  462. local i = 0
  463. for l in string.gmatch(tb, "[^\n]+\n?") do
  464. assert(i == 0 or string.find(l, p[i]))
  465. i = i+1
  466. end
  467. assert(p[i] == nil)
  468. end
  469. local function f (n)
  470. if n > 0 then f(n-1)
  471. else coroutine.yield() end
  472. end
  473. local co = coroutine.create(f)
  474. coroutine.resume(co, 3)
  475. checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
  476. checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
  477. checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
  478. checktraceback(co, {"db.lua"}, 4)
  479. checktraceback(co, {}, 40)
  480. co = coroutine.create(function (x)
  481. local a = 1
  482. coroutine.yield(debug.getinfo(1, "l"))
  483. coroutine.yield(debug.getinfo(1, "l").currentline)
  484. return a
  485. end)
  486. local tr = {}
  487. local foo = function (e, l) if l then table.insert(tr, l) end end
  488. debug.sethook(co, foo, "lcr")
  489. local _, l = coroutine.resume(co, 10)
  490. local x = debug.getinfo(co, 1, "lfLS")
  491. assert(x.currentline == l.currentline and x.activelines[x.currentline])
  492. assert(type(x.func) == "function")
  493. for i=x.linedefined + 1, x.lastlinedefined do
  494. assert(x.activelines[i])
  495. x.activelines[i] = nil
  496. end
  497. assert(next(x.activelines) == nil) -- no 'extra' elements
  498. assert(not debug.getinfo(co, 2))
  499. local a,b = debug.getlocal(co, 1, 1)
  500. assert(a == "x" and b == 10)
  501. a,b = debug.getlocal(co, 1, 2)
  502. assert(a == "a" and b == 1)
  503. debug.setlocal(co, 1, 2, "hi")
  504. assert(debug.gethook(co) == foo)
  505. assert(#tr == 2 and
  506. tr[1] == l.currentline-1 and tr[2] == l.currentline)
  507. a,b,c = pcall(coroutine.resume, co)
  508. assert(a and b and c == l.currentline+1)
  509. checktraceback(co, {"yield", "in function <"})
  510. a,b = coroutine.resume(co)
  511. assert(a and b == "hi")
  512. assert(#tr == 4 and tr[4] == l.currentline+2)
  513. assert(debug.gethook(co) == foo)
  514. assert(not debug.gethook())
  515. checktraceback(co, {})
  516. -- check get/setlocal in coroutines
  517. co = coroutine.create(function (x)
  518. local a, b = coroutine.yield(x)
  519. assert(a == 100 and b == nil)
  520. return x
  521. end)
  522. a, b = coroutine.resume(co, 10)
  523. assert(a and b == 10)
  524. a, b = debug.getlocal(co, 1, 1)
  525. assert(a == "x" and b == 10)
  526. assert(not debug.getlocal(co, 1, 5))
  527. assert(debug.setlocal(co, 1, 1, 30) == "x")
  528. assert(not debug.setlocal(co, 1, 5, 40))
  529. a, b = coroutine.resume(co, 100)
  530. assert(a and b == 30)
  531. -- check traceback of suspended (or dead with error) coroutines
  532. function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
  533. co = coroutine.create(function (x) f(x) end)
  534. a, b = coroutine.resume(co, 3)
  535. t = {"'coroutine.yield'", "'f'", "in function <"}
  536. while coroutine.status(co) == "suspended" do
  537. checktraceback(co, t)
  538. a, b = coroutine.resume(co)
  539. table.insert(t, 2, "'f'") -- one more recursive call to 'f'
  540. end
  541. t[1] = "'error'"
  542. checktraceback(co, t)
  543. -- test acessing line numbers of a coroutine from a resume inside
  544. -- a C function (this is a known bug in Lua 5.0)
  545. local function g(x)
  546. coroutine.yield(x)
  547. end
  548. local function f (i)
  549. debug.sethook(function () end, "l")
  550. for j=1,1000 do
  551. g(i+j)
  552. end
  553. end
  554. local co = coroutine.wrap(f)
  555. co(10)
  556. pcall(co)
  557. pcall(co)
  558. assert(type(debug.getregistry()) == "table")
  559. -- test tagmethod information
  560. local a = {}
  561. local function f (t)
  562. local info = debug.getinfo(1);
  563. assert(info.namewhat == "metamethod")
  564. a.op = info.name
  565. return info.name
  566. end
  567. setmetatable(a, {
  568. __index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
  569. __mul = f; __idiv = f; __unm = f; __len = f; __sub = f;
  570. __shl = f; __shr = f; __bor = f; __bxor = f;
  571. __eq = f; __le = f; __lt = f; __unm = f; __len = f; __band = f;
  572. __bnot = f;
  573. })
  574. local b = setmetatable({}, getmetatable(a))
  575. assert(a[3] == "__index" and a^3 == "__pow" and a..a == "__concat")
  576. assert(a/3 == "__div" and 3%a == "__mod")
  577. assert(a+3 == "__add" and 3-a == "__sub" and a*3 == "__mul" and
  578. -a == "__unm" and #a == "__len" and a&3 == "__band")
  579. assert(a|3 == "__bor" and 3~a == "__bxor" and a<<3 == "__shl" and
  580. a>>1 == "__shr")
  581. assert (a==b and a.op == "__eq")
  582. assert (a>=b and a.op == "__le")
  583. assert (a>b and a.op == "__lt")
  584. assert(~a == "__bnot")
  585. do -- testing for-iterator name
  586. local function f()
  587. assert(debug.getinfo(1).name == "for iterator")
  588. end
  589. for i in f do end
  590. end
  591. do -- testing debug info for finalizers
  592. local name = nil
  593. -- create a piece of garbage with a finalizer
  594. setmetatable({}, {__gc = function ()
  595. local t = debug.getinfo(2) -- get callee information
  596. assert(t.namewhat == "metamethod")
  597. name = t.name
  598. end})
  599. -- repeat until previous finalizer runs (setting 'name')
  600. repeat local a = {} until name
  601. assert(name == "__gc")
  602. end
  603. do
  604. print("testing traceback sizes")
  605. local function countlines (s)
  606. return select(2, string.gsub(s, "\n", ""))
  607. end
  608. local function deep (lvl, n)
  609. if lvl == 0 then
  610. return (debug.traceback("message", n))
  611. else
  612. return (deep(lvl-1, n))
  613. end
  614. end
  615. local function checkdeep (total, start)
  616. local s = deep(total, start)
  617. local rest = string.match(s, "^message\nstack traceback:\n(.*)$")
  618. local cl = countlines(rest)
  619. -- at most 10 lines in first part, 11 in second, plus '...'
  620. assert(cl <= 10 + 11 + 1)
  621. local brk = string.find(rest, "%.%.%.")
  622. if brk then -- does message have '...'?
  623. local rest1 = string.sub(rest, 1, brk)
  624. local rest2 = string.sub(rest, brk, #rest)
  625. assert(countlines(rest1) == 10 and countlines(rest2) == 11)
  626. else
  627. assert(cl == total - start + 2)
  628. end
  629. end
  630. for d = 1, 51, 10 do
  631. for l = 1, d do
  632. -- use coroutines to ensure complete control of the stack
  633. coroutine.wrap(checkdeep)(d, l)
  634. end
  635. end
  636. end
  637. print("testing debug functions on chunk without debug info")
  638. prog = [[-- program to be loaded without debug information
  639. local debug = require'debug'
  640. local a = 12 -- a local variable
  641. local n, v = debug.getlocal(1, 1)
  642. assert(n == "(*temporary)" and v == debug) -- unkown name but known value
  643. n, v = debug.getlocal(1, 2)
  644. assert(n == "(*temporary)" and v == 12) -- unkown name but known value
  645. -- a function with an upvalue
  646. local f = function () local x; return a end
  647. n, v = debug.getupvalue(f, 1)
  648. assert(n == "(*no name)" and v == 12)
  649. assert(debug.setupvalue(f, 1, 13) == "(*no name)")
  650. assert(a == 13)
  651. local t = debug.getinfo(f)
  652. assert(t.name == nil and t.linedefined > 0 and
  653. t.lastlinedefined == t.linedefined and
  654. t.short_src == "?")
  655. assert(debug.getinfo(1).currentline == -1)
  656. t = debug.getinfo(f, "L").activelines
  657. assert(next(t) == nil) -- active lines are empty
  658. -- dump/load a function without debug info
  659. f = load(string.dump(f))
  660. t = debug.getinfo(f)
  661. assert(t.name == nil and t.linedefined > 0 and
  662. t.lastlinedefined == t.linedefined and
  663. t.short_src == "?")
  664. assert(debug.getinfo(1).currentline == -1)
  665. return a
  666. ]]
  667. -- load 'prog' without debug info
  668. local f = assert(load(string.dump(load(prog), true)))
  669. assert(f() == 13)
  670. do -- tests for 'source' in binary dumps
  671. local prog = [[
  672. return function (x)
  673. return function (y)
  674. return x + y
  675. end
  676. end
  677. ]]
  678. local name = string.rep("x", 1000)
  679. local p = assert(load(prog, name))
  680. -- load 'p' as a binary chunk with debug information
  681. local c = string.dump(p)
  682. assert(#c > 1000 and #c < 2000) -- no repetition of 'source' in dump
  683. local f = assert(load(c))
  684. local g = f()
  685. local h = g(3)
  686. assert(h(5) == 8)
  687. assert(debug.getinfo(f).source == name and -- all functions have 'source'
  688. debug.getinfo(g).source == name and
  689. debug.getinfo(h).source == name)
  690. -- again, without debug info
  691. local c = string.dump(p, true)
  692. assert(#c < 500) -- no 'source' in dump
  693. local f = assert(load(c))
  694. local g = f()
  695. local h = g(30)
  696. assert(h(50) == 80)
  697. assert(debug.getinfo(f).source == '=?' and -- no function has 'source'
  698. debug.getinfo(g).source == '=?' and
  699. debug.getinfo(h).source == '=?')
  700. end
  701. print"OK"