db.lua 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. -- testing debug library
  2. local function dostring(s) return assert(loadstring(s))() end
  3. print"testing debug library and debug information"
  4. do
  5. local a=1
  6. end
  7. function test (s, l, p)
  8. collectgarbage() -- avoid gc during trace
  9. local function f (event, line)
  10. assert(event == 'line')
  11. local l = table.remove(l, 1)
  12. if p then print(l, line) end
  13. assert(l == line, "wrong trace!!")
  14. end
  15. debug.sethook(f,"l"); loadstring(s)(); debug.sethook()
  16. assert(table.getn(l) == 0)
  17. end
  18. do
  19. local a = debug.getinfo(print)
  20. assert(a.what == "C" and a.short_src == "[C]")
  21. local b = debug.getinfo(test, "SfL")
  22. assert(b.name == nil and b.what == "Lua" and b.linedefined == 11 and
  23. b.lastlinedefined == b.linedefined + 10 and
  24. b.func == test and not string.find(b.short_src, "%["))
  25. assert(b.activelines[b.linedefined + 1] and
  26. b.activelines[b.lastlinedefined])
  27. assert(not b.activelines[b.linedefined] and
  28. not b.activelines[b.lastlinedefined + 1])
  29. end
  30. -- test file and string names truncation
  31. a = "function f () end"
  32. local function dostring (s, x) return loadstring(s, x)() end
  33. dostring(a)
  34. assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
  35. dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
  36. assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
  37. dostring("\n"..a)
  38. assert(debug.getinfo(f).short_src == '[string "..."]')
  39. dostring(a, "")
  40. assert(debug.getinfo(f).short_src == '[string ""]')
  41. dostring(a, "@xuxu")
  42. assert(debug.getinfo(f).short_src == "xuxu")
  43. dostring(a, "@"..string.rep('p', 1000)..'t')
  44. assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
  45. dostring(a, "=xuxu")
  46. assert(debug.getinfo(f).short_src == "xuxu")
  47. dostring(a, string.format("=%s", string.rep('x', 500)))
  48. assert(string.find(debug.getinfo(f).short_src, "^x*"))
  49. dostring(a, "=")
  50. assert(debug.getinfo(f).short_src == "")
  51. a = nil; f = nil;
  52. repeat
  53. local g = {x = function ()
  54. local a = debug.getinfo(2)
  55. assert(a.name == 'f' and a.namewhat == 'local')
  56. a = debug.getinfo(1)
  57. assert(a.name == 'x' and a.namewhat == 'field')
  58. return 'xixi'
  59. end}
  60. local f = function () return 1+1 and (not 1 or g.x()) end
  61. assert(f() == 'xixi')
  62. g = debug.getinfo(f)
  63. assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
  64. function f (x, name) -- local!
  65. name = name or 'f'
  66. local a = debug.getinfo(1)
  67. assert(a.name == name and a.namewhat == 'local')
  68. return x
  69. end
  70. -- breaks in different conditions
  71. if 3>4 then break end; f()
  72. if 3<4 then a=1 else break end; f()
  73. while 1 do local x=10; break end; f()
  74. local b = 1
  75. if 3>4 then return math.sin(1) end; f()
  76. a = 3<4; f()
  77. a = 3<4 or 1; f()
  78. repeat local x=20; if 4>3 then f() else break end; f() until 1
  79. g = {}
  80. f(g).x = f(2) and f(10)+f(9)
  81. assert(g.x == f(19))
  82. function g(x) if not x then return 3 end return (x('a', 'x')) end
  83. assert(g(f) == 'a')
  84. until 1
  85. test([[if
  86. math.sin(1)
  87. then
  88. a=1
  89. else
  90. a=2
  91. end
  92. ]], {2,4,7})
  93. test([[--
  94. if nil then
  95. a=1
  96. else
  97. a=2
  98. end
  99. ]], {2,5,6})
  100. test([[a=1
  101. repeat
  102. a=a+1
  103. until a==3
  104. ]], {1,3,4,3,4})
  105. test([[ do
  106. return
  107. end
  108. ]], {2})
  109. test([[local a
  110. a=1
  111. while a<=3 do
  112. a=a+1
  113. end
  114. ]], {2,3,4,3,4,3,4,3,5})
  115. test([[while math.sin(1) do
  116. if math.sin(1)
  117. then
  118. break
  119. end
  120. end
  121. a=1]], {1,2,4,7})
  122. test([[for i=1,3 do
  123. a=i
  124. end
  125. ]], {1,2,1,2,1,2,1,3})
  126. test([[for i,v in pairs{'a','b'} do
  127. a=i..v
  128. end
  129. ]], {1,2,1,2,1,3})
  130. test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
  131. print'+'
  132. a = {}; L = nil
  133. local glob = 1
  134. local oldglob = glob
  135. debug.sethook(function (e,l)
  136. collectgarbage() -- force GC during a hook
  137. local f, m, c = debug.gethook()
  138. assert(m == 'crl' and c == 0)
  139. if e == "line" then
  140. if glob ~= oldglob then
  141. L = l-1 -- get the first line where "glob" has changed
  142. oldglob = glob
  143. end
  144. elseif e == "call" then
  145. local f = debug.getinfo(2, "f").func
  146. a[f] = 1
  147. else assert(e == "return")
  148. end
  149. end, "crl")
  150. function f(a,b)
  151. collectgarbage()
  152. local _, x = debug.getlocal(1, 1)
  153. local _, y = debug.getlocal(1, 2)
  154. assert(x == a and y == b)
  155. assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
  156. assert(debug.setlocal(2, 4, "maçã") == "B")
  157. x = debug.getinfo(2)
  158. assert(x.func == g and x.what == "Lua" and x.name == 'g' and
  159. x.nups == 0 and string.find(x.source, "^@.*db%.lua"))
  160. glob = glob+1
  161. assert(debug.getinfo(1, "l").currentline == L+1)
  162. assert(debug.getinfo(1, "l").currentline == L+2)
  163. end
  164. function foo()
  165. glob = glob+1
  166. assert(debug.getinfo(1, "l").currentline == L+1)
  167. end; foo() -- set L
  168. -- check line counting inside strings and empty lines
  169. _ = 'alo\
  170. alo' .. [[
  171. ]]
  172. --[[
  173. ]]
  174. assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
  175. function g(...)
  176. do local a,b,c; a=math.sin(40); end
  177. local feijao
  178. local AAAA,B = "xuxu", "mamão"
  179. f(AAAA,B)
  180. assert(AAAA == "pera" and B == "maçã")
  181. do
  182. local B = 13
  183. local x,y = debug.getlocal(1,5)
  184. assert(x == 'B' and y == 13)
  185. end
  186. end
  187. g()
  188. assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
  189. -- tests for manipulating non-registered locals (C and Lua temporaries)
  190. local n, v = debug.getlocal(0, 1)
  191. assert(v == 0 and n == "(*temporary)")
  192. local n, v = debug.getlocal(0, 2)
  193. assert(v == 2 and n == "(*temporary)")
  194. assert(not debug.getlocal(0, 3))
  195. assert(not debug.getlocal(0, 0))
  196. function f()
  197. assert(select(2, debug.getlocal(2,3)) == 1)
  198. assert(not debug.getlocal(2,4))
  199. debug.setlocal(2, 3, 10)
  200. return 20
  201. end
  202. function g(a,b) return (a+1) + f() end
  203. assert(g(0,0) == 30)
  204. debug.sethook(nil);
  205. assert(debug.gethook() == nil)
  206. -- testing access to function arguments
  207. X = nil
  208. a = {}
  209. function a:f (a, b, ...) local c = 13 end
  210. debug.sethook(function (e)
  211. assert(e == "call")
  212. dostring("XX = 12") -- test dostring inside hooks
  213. -- testing errors inside hooks
  214. assert(not pcall(loadstring("a='joao'+1")))
  215. debug.sethook(function (e, l)
  216. assert(debug.getinfo(2, "l").currentline == l)
  217. local f,m,c = debug.gethook()
  218. assert(e == "line")
  219. assert(m == 'l' and c == 0)
  220. debug.sethook(nil) -- hook is called only once
  221. assert(not X) -- check that
  222. X = {}; local i = 1
  223. local x,y
  224. while 1 do
  225. x,y = debug.getlocal(2, i)
  226. if x==nil then break end
  227. X[x] = y
  228. i = i+1
  229. end
  230. end, "l")
  231. end, "c")
  232. a:f(1,2,3,4,5)
  233. assert(X.self == a and X.a == 1 and X.b == 2 and X.arg.n == 3 and X.c == nil)
  234. assert(XX == 12)
  235. assert(debug.gethook() == nil)
  236. -- testing upvalue access
  237. local function getupvalues (f)
  238. local t = {}
  239. local i = 1
  240. while true do
  241. local name, value = debug.getupvalue(f, i)
  242. if not name then break end
  243. assert(not t[name])
  244. t[name] = value
  245. i = i + 1
  246. end
  247. return t
  248. end
  249. local a,b,c = 1,2,3
  250. local function foo1 (a) b = a; return c end
  251. local function foo2 (x) a = x; return c+b end
  252. assert(debug.getupvalue(foo1, 3) == nil)
  253. assert(debug.getupvalue(foo1, 0) == nil)
  254. assert(debug.setupvalue(foo1, 3, "xuxu") == nil)
  255. local t = getupvalues(foo1)
  256. assert(t.a == nil and t.b == 2 and t.c == 3)
  257. t = getupvalues(foo2)
  258. assert(t.a == 1 and t.b == 2 and t.c == 3)
  259. assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
  260. assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
  261. -- cannot manipulate C upvalues from Lua
  262. assert(debug.getupvalue(io.read, 1) == nil)
  263. assert(debug.setupvalue(io.read, 1, 10) == nil)
  264. -- testing count hooks
  265. local a=0
  266. debug.sethook(function (e) a=a+1 end, "", 1)
  267. a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
  268. debug.sethook(function (e) a=a+1 end, "", 4)
  269. a=0; for i=1,1000 do end; assert(250 < a and a < 255)
  270. local f,m,c = debug.gethook()
  271. assert(m == "" and c == 4)
  272. debug.sethook(function (e) a=a+1 end, "", 4000)
  273. a=0; for i=1,1000 do end; assert(a == 0)
  274. debug.sethook(print, "", 2^24 - 1) -- count upperbound
  275. local f,m,c = debug.gethook()
  276. assert(({debug.gethook()})[3] == 2^24 - 1)
  277. debug.sethook()
  278. -- tests for tail calls
  279. local function f (x)
  280. if x then
  281. assert(debug.getinfo(1, "S").what == "Lua")
  282. local tail = debug.getinfo(2)
  283. assert(not pcall(getfenv, 3))
  284. assert(tail.what == "tail" and tail.short_src == "(tail call)" and
  285. tail.linedefined == -1 and tail.func == nil)
  286. assert(debug.getinfo(3, "f").func == g1)
  287. assert(getfenv(3))
  288. assert(debug.getinfo(4, "S").what == "tail")
  289. assert(not pcall(getfenv, 5))
  290. assert(debug.getinfo(5, "S").what == "main")
  291. assert(getfenv(5))
  292. print"+"
  293. end
  294. end
  295. function g(x) return f(x) end
  296. function g1(x) g(x) end
  297. local function h (x) local f=g1; return f(x) end
  298. h(true)
  299. local b = {}
  300. debug.sethook(function (e) table.insert(b, e) end, "cr")
  301. h(false)
  302. debug.sethook()
  303. local res = {"return", -- first return (from sethook)
  304. "call", "call", "call", "call",
  305. "return", "tail return", "return", "tail return",
  306. "call", -- last call (to sethook)
  307. }
  308. for _, k in ipairs(res) do assert(k == table.remove(b, 1)) end
  309. lim = 30000
  310. local function foo (x)
  311. if x==0 then
  312. assert(debug.getinfo(lim+2).what == "main")
  313. for i=2,lim do assert(debug.getinfo(i, "S").what == "tail") end
  314. else return foo(x-1)
  315. end
  316. end
  317. foo(lim)
  318. print"+"
  319. -- testing traceback
  320. assert(debug.traceback(print) == print)
  321. assert(debug.traceback(print, 4) == print)
  322. assert(string.find(debug.traceback("hi", 4), "^hi\n"))
  323. assert(string.find(debug.traceback("hi"), "^hi\n"))
  324. assert(not string.find(debug.traceback("hi"), "'traceback'"))
  325. assert(string.find(debug.traceback("hi", 0), "'traceback'"))
  326. assert(string.find(debug.traceback(), "^stack traceback:\n"))
  327. -- testing debugging of coroutines
  328. local function checktraceback (co, p)
  329. local tb = debug.traceback(co)
  330. local i = 0
  331. for l in string.gmatch(tb, "[^\n]+\n?") do
  332. assert(i == 0 or string.find(l, p[i]))
  333. i = i+1
  334. end
  335. assert(p[i] == nil)
  336. end
  337. local function f (n)
  338. if n > 0 then return f(n-1)
  339. else coroutine.yield() end
  340. end
  341. local co = coroutine.create(f)
  342. coroutine.resume(co, 3)
  343. checktraceback(co, {"yield", "db.lua", "tail", "tail", "tail"})
  344. co = coroutine.create(function (x)
  345. local a = 1
  346. coroutine.yield(debug.getinfo(1, "l"))
  347. coroutine.yield(debug.getinfo(1, "l").currentline)
  348. return a
  349. end)
  350. local tr = {}
  351. local foo = function (e, l) table.insert(tr, l) end
  352. debug.sethook(co, foo, "l")
  353. local _, l = coroutine.resume(co, 10)
  354. local x = debug.getinfo(co, 1, "lfLS")
  355. assert(x.currentline == l.currentline and x.activelines[x.currentline])
  356. assert(type(x.func) == "function")
  357. for i=x.linedefined + 1, x.lastlinedefined do
  358. assert(x.activelines[i])
  359. x.activelines[i] = nil
  360. end
  361. assert(next(x.activelines) == nil) -- no 'extra' elements
  362. assert(debug.getinfo(co, 2) == nil)
  363. local a,b = debug.getlocal(co, 1, 1)
  364. assert(a == "x" and b == 10)
  365. a,b = debug.getlocal(co, 1, 2)
  366. assert(a == "a" and b == 1)
  367. debug.setlocal(co, 1, 2, "hi")
  368. assert(debug.gethook(co) == foo)
  369. assert(table.getn(tr) == 2 and
  370. tr[1] == l.currentline-1 and tr[2] == l.currentline)
  371. a,b,c = pcall(coroutine.resume, co)
  372. assert(a and b and c == l.currentline+1)
  373. checktraceback(co, {"yield", "in function <"})
  374. a,b = coroutine.resume(co)
  375. assert(a and b == "hi")
  376. assert(table.getn(tr) == 4 and tr[4] == l.currentline+2)
  377. assert(debug.gethook(co) == foo)
  378. assert(debug.gethook() == nil)
  379. checktraceback(co, {})
  380. -- check traceback of suspended (or dead with error) coroutines
  381. function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
  382. co = coroutine.create(function (x) f(x) end)
  383. a, b = coroutine.resume(co, 3)
  384. t = {"'yield'", "'f'", "in function <"}
  385. while coroutine.status(co) == "suspended" do
  386. checktraceback(co, t)
  387. a, b = coroutine.resume(co)
  388. table.insert(t, 2, "'f'") -- one more recursive call to 'f'
  389. end
  390. t[1] = "'error'"
  391. checktraceback(co, t)
  392. -- test acessing line numbers of a coroutine from a resume inside
  393. -- a C function (this is a known bug in Lua 5.0)
  394. local function g(x)
  395. coroutine.yield(x)
  396. end
  397. local function f (i)
  398. debug.sethook(function () end, "l")
  399. for j=1,1000 do
  400. g(i+j)
  401. end
  402. end
  403. local co = coroutine.wrap(f)
  404. co(10)
  405. pcall(co)
  406. pcall(co)
  407. assert(type(debug.getregistry()) == "table")
  408. print"OK"