db.lua 25 KB

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