db.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. -- testing debug library
  2. debug = require "debug"
  3. local function dostring(s) return assert(load(s))() end
  4. print"testing debug library and debug information"
  5. do
  6. local a=1
  7. end
  8. function test (s, l, p)
  9. collectgarbage() -- avoid gc during trace
  10. local function f (event, line)
  11. assert(event == 'line')
  12. local l = table.remove(l, 1)
  13. if p then print(l, line) end
  14. assert(l == line, "wrong trace!!")
  15. end
  16. debug.sethook(f,"l"); load(s)(); debug.sethook()
  17. assert(#l == 0)
  18. end
  19. do
  20. assert(not pcall(debug.getinfo, print, "X")) -- invalid option
  21. assert(debug.getinfo(1000) == nil) -- out of range level
  22. assert(debug.getinfo(-1) == nil) -- out of range level
  23. local a = debug.getinfo(print)
  24. assert(a.what == "C#" and a.short_src == "[C#]") -- changed C to C#
  25. a = debug.getinfo(print, "L")
  26. assert(a.activelines == nil)
  27. local b = debug.getinfo(test, "SfL")
  28. assert(b.name == nil and b.what == "Lua" and b.linedefined == 13 and
  29. b.lastlinedefined == b.linedefined + 10 and
  30. b.func == test and not string.find(b.short_src, "%["))
  31. assert(b.activelines[b.linedefined + 1] and
  32. b.activelines[b.lastlinedefined])
  33. assert(not b.activelines[b.linedefined] and
  34. not b.activelines[b.lastlinedefined + 1])
  35. end
  36. -- test file and string names truncation
  37. a = "function f () end"
  38. local function dostring (s, x) return load(s, x)() end
  39. dostring(a)
  40. assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
  41. dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
  42. assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
  43. dostring(a..string.format("; %s=1", string.rep('p', 400)))
  44. assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
  45. dostring("\n"..a)
  46. assert(debug.getinfo(f).short_src == '[string "..."]')
  47. dostring(a, "")
  48. assert(debug.getinfo(f).short_src == '[string ""]')
  49. dostring(a, "@xuxu")
  50. assert(debug.getinfo(f).short_src == "xuxu")
  51. dostring(a, "@"..string.rep('p', 1000)..'t')
  52. assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
  53. dostring(a, "=xuxu")
  54. assert(debug.getinfo(f).short_src == "xuxu")
  55. dostring(a, string.format("=%s", string.rep('x', 500)))
  56. assert(string.find(debug.getinfo(f).short_src, "^x*$"))
  57. dostring(a, "=")
  58. assert(debug.getinfo(f).short_src == "")
  59. a = nil; f = nil;
  60. repeat
  61. local g = {x = function ()
  62. local a = debug.getinfo(2)
  63. assert(a.name == 'f' and a.namewhat == 'local')
  64. a = debug.getinfo(1)
  65. assert(a.name == 'x' and a.namewhat == 'field')
  66. return 'xixi'
  67. end}
  68. local f = function () return 1+1 and (not 1 or g.x()) end
  69. assert(f() == 'xixi')
  70. g = debug.getinfo(f)
  71. assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
  72. function f (x, name) -- local!
  73. if not name then -- todo fix compiler bug Lua-CSharp
  74. name = 'f'
  75. end
  76. local a = debug.getinfo(1)
  77. assert(a.name == name and a.namewhat == 'local')
  78. return x
  79. end
  80. -- breaks in different conditions
  81. if 3>4 then break end; f()
  82. if 3<4 then a=1 else break end; f()
  83. while 1 do local x=10; break end; f()
  84. local b = 1
  85. if 3>4 then return math.sin(1) end; f()
  86. a = 3<4; f()
  87. a = 3<4 or 1; f()
  88. repeat local x=20; if 4>3 then f() else break end; f() until 1
  89. g = {}
  90. f(g).x = f(2) and f(10)+f(9)
  91. assert(g.x == f(19))
  92. function g(x) if not x then return 3 end return (x('a', 'x')) end
  93. assert(g(f) == 'a')
  94. until 1
  95. test([[if
  96. math.sin(1)
  97. then
  98. a=1
  99. else
  100. a=2
  101. end
  102. ]], {2,3,4,7})
  103. test([[--
  104. if nil then
  105. a=1
  106. else
  107. a=2
  108. end
  109. ]], {2,5,6})
  110. test([[a=1
  111. repeat
  112. a=a+1
  113. until a==3
  114. ]], {1,3,4,3,4})
  115. test([[ do
  116. return
  117. end
  118. ]], {2})
  119. test([[local a
  120. a=1
  121. while a<=3 do
  122. a=a+1
  123. end
  124. ]], {1,2,3,4,3,4,3,4,3,5})
  125. test([[while math.sin(1) do
  126. if math.sin(1)
  127. then break
  128. end
  129. end
  130. a=1]], {1,2,3,6})
  131. test([[for i=1,3 do
  132. a=i
  133. end
  134. ]], {1,2,1,2,1,2,1,3})
  135. test([[for i,v in pairs{'a','b'} do
  136. a=i..v
  137. end
  138. ]], {1,2,1,2,1,3})
  139. test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
  140. print'+'
  141. -- invalid levels in [gs]etlocal
  142. assert(not pcall(debug.getlocal, 20, 1))
  143. assert(not pcall(debug.setlocal, -1, 1, 10))
  144. -- parameter names
  145. local function foo (a,b,...) local d, e end
  146. local co = coroutine.create(foo)
  147. assert(debug.getlocal(foo, 1) == 'a')
  148. assert(debug.getlocal(foo, 2) == 'b')
  149. assert(debug.getlocal(foo, 3) == nil)
  150. assert(debug.getlocal(co, foo, 1) == 'a')
  151. assert(debug.getlocal(co, foo, 2) == 'b')
  152. assert(debug.getlocal(co, foo, 3) == nil)
  153. assert(debug.getlocal(print, 1) == nil)
  154. -- varargs
  155. local function foo (a, ...)
  156. local t = table.pack(...)
  157. for i = 1, t.n do
  158. local n, v = debug.getlocal(1, -i)
  159. assert(n == "(*vararg)" and v == t[i])
  160. end
  161. assert(not debug.getlocal(1, -(t.n + 1)))
  162. assert(not debug.setlocal(1, -(t.n + 1), 30))
  163. if t.n > 0 then
  164. (function (x)
  165. assert(debug.setlocal(2, -1, x) == "(*vararg)")
  166. assert(debug.setlocal(2, -t.n, x) == "(*vararg)")
  167. end)(430)
  168. assert(... == 430)
  169. end
  170. end
  171. foo()
  172. foo(print)
  173. foo(200, 3, 4)
  174. local a = {}
  175. for i = 1,1000 do a[i] = i end
  176. foo(table.unpack(a))
  177. a = nil
  178. -- access to vararg in non-vararg function
  179. local function foo () return debug.getlocal(1, -1) end
  180. assert(foo(10) == nil)
  181. a = {}; L = nil
  182. local glob = 1
  183. local oldglob = glob
  184. debug.sethook(function (e,l)
  185. collectgarbage() -- force GC during a hook
  186. local f, m, c = debug.gethook()
  187. assert(m == 'crl' and c == 0)
  188. if e == "line" then
  189. if glob ~= oldglob then
  190. L = l-1 -- get the first line where "glob" has changed
  191. oldglob = glob
  192. end
  193. elseif e == "call" then
  194. local f = debug.getinfo(2, "f").func
  195. a[f] = 1
  196. else assert(e == "return")
  197. end
  198. end, "crl")
  199. function f(a,b)
  200. collectgarbage()
  201. local _, x = debug.getlocal(1, 1)
  202. local _, y = debug.getlocal(1, 2)
  203. assert(x == a and y == b)
  204. assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
  205. assert(debug.setlocal(2, 4, "ma��") == "B")
  206. x = debug.getinfo(2)
  207. assert(x.func == g and x.what == "Lua" and x.name == 'g' and
  208. x.nups == 1 and string.find(x.source, "^@.*db%.lua$"))
  209. glob = glob+1
  210. assert(debug.getinfo(1, "l").currentline == L+1)
  211. assert(debug.getinfo(1, "l").currentline == L+2)
  212. end
  213. function foo()
  214. glob = glob+1
  215. assert(debug.getinfo(1, "l").currentline == L+1)
  216. end; foo() -- set L
  217. -- check line counting inside strings and empty lines
  218. --_ = 'alo\ -- todo fix compiler bug Lua-CSharp
  219. --alo' .. [[
  220. --
  221. --]]
  222. --[[
  223. ]]
  224. assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
  225. function g(...)
  226. local arg = {...}
  227. do local a,b,c; a=math.sin(40); end
  228. local feijao
  229. local AAAA,B = "xuxu", "mam�o"
  230. f(AAAA,B)
  231. assert(AAAA == "pera" and B == "ma��")
  232. do
  233. local B = 13
  234. local x,y = debug.getlocal(1,5)
  235. assert(x == 'B' and y == 13)
  236. end
  237. end
  238. g()
  239. assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
  240. -- tests for manipulating non-registered locals (C and Lua temporaries)
  241. local n, v = debug.getlocal(0, 1)
  242. assert(v == 0 and n == "(*temporary)")
  243. local n, v = debug.getlocal(0, 2)
  244. assert(v == 2 and n == "(*temporary)")
  245. assert(not debug.getlocal(0, 3))
  246. assert(not debug.getlocal(0, 0))
  247. function f()
  248. assert(select(2, debug.getlocal(2,3)) == 1)
  249. assert(not debug.getlocal(2,4))
  250. debug.setlocal(2, 3, 10)
  251. return 20
  252. end
  253. function g(a,b) return (a+1) + f() end
  254. assert(g(0,0) == 30)
  255. debug.sethook(nil);
  256. assert(debug.gethook() == nil)
  257. -- testing access to function arguments
  258. X = nil
  259. a = {}
  260. function a:f (a, b, ...) local arg = {...}; local c = 13 end
  261. debug.sethook(function (e)
  262. assert(e == "call")
  263. dostring("XX = 12") -- test dostring inside hooks
  264. -- testing errors inside hooks
  265. assert(not pcall(load("a='joao'+1")))
  266. debug.sethook(function (e, l)
  267. assert(debug.getinfo(2, "l").currentline == l)
  268. local f,m,c = debug.gethook()
  269. assert(e == "line")
  270. assert(m == 'l' and c == 0)
  271. debug.sethook(nil) -- hook is called only once
  272. assert(not X) -- check that
  273. X = {}; local i = 1
  274. local x,y
  275. while 1 do
  276. x,y = debug.getlocal(2, i)
  277. if x==nil then break end
  278. X[x] = y
  279. i = i+1
  280. end
  281. end, "l")
  282. end, "c")
  283. a:f(1,2,3,4,5)
  284. assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
  285. assert(XX == 12)
  286. assert(debug.gethook() == nil)
  287. -- testing upvalue access
  288. local function getupvalues (f)
  289. local t = {}
  290. local i = 1
  291. while true do
  292. local name, value = debug.getupvalue(f, i)
  293. if not name then break end
  294. assert(not t[name])
  295. t[name] = value
  296. i = i + 1
  297. end
  298. return t
  299. end
  300. local a,b,c = 1,2,3
  301. local function foo1 (a) b = a; return c end
  302. local function foo2 (x) a = x; return c+b end
  303. assert(debug.getupvalue(foo1, 3) == nil)
  304. assert(debug.getupvalue(foo1, 0) == nil)
  305. assert(debug.setupvalue(foo1, 3, "xuxu") == nil)
  306. local t = getupvalues(foo1)
  307. assert(t.a == nil and t.b == 2 and t.c == 3)
  308. t = getupvalues(foo2)
  309. assert(t.a == 1 and t.b == 2 and t.c == 3)
  310. assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
  311. assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
  312. -- upvalues of C functions are allways "called" "" (the empty string)
  313. assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")
  314. -- testing count hooks
  315. local a=0
  316. debug.sethook(function (e) a=a+1 end, "", 1)
  317. a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
  318. debug.sethook(function (e) a=a+1 end, "", 4)
  319. a=0; for i=1,1000 do end; assert(250 < a and a < 255)
  320. local f,m,c = debug.gethook()
  321. assert(m == "" and c == 4)
  322. debug.sethook(function (e) a=a+1 end, "", 4000)
  323. a=0; for i=1,1000 do end; assert(a == 0)
  324. if not _no32 then
  325. debug.sethook(print, "", 2^24 - 1) -- count upperbound
  326. local f,m,c = debug.gethook()
  327. assert(({debug.gethook()})[3] == 2^24 - 1)
  328. end
  329. debug.sethook()
  330. -- tests for tail calls
  331. local function f (x)
  332. if x then
  333. assert(debug.getinfo(1, "S").what == "Lua")
  334. assert(debug.getinfo(1, "t").istailcall == true)
  335. local tail = debug.getinfo(2)
  336. assert(tail.func == g1 and tail.istailcall == true)
  337. assert(debug.getinfo(3, "S").what == "main")
  338. print"+"
  339. end
  340. end
  341. function g(x) return f(x) end
  342. function g1(x) g(x) end
  343. local function h (x) local f=g1; return f(x) end
  344. h(true)
  345. local b = {}
  346. debug.sethook(function (e) table.insert(b, e) end, "cr")
  347. h(false)
  348. debug.sethook()
  349. local res = {"return", -- first return (from sethook)
  350. "call", "tail call", "call", "tail call",
  351. "return", "return",
  352. "call", -- last call (to sethook)
  353. }
  354. for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
  355. b = 0
  356. debug.sethook(function (e)
  357. if e == "tail call" then
  358. b = b + 1
  359. assert(debug.getinfo(2, "t").istailcall == true)
  360. else
  361. assert(debug.getinfo(2, "t").istailcall == false)
  362. end
  363. end, "c")
  364. h(false)
  365. debug.sethook()
  366. assert(b == 2) -- two tail calls
  367. lim = 30000
  368. if _soft then limit = 3000 end
  369. local function foo (x)
  370. if x==0 then
  371. assert(debug.getinfo(2).what == "main")
  372. local info = debug.getinfo(1)
  373. assert(info.istailcall == true and info.func == foo)
  374. else return foo(x-1)
  375. end
  376. end
  377. foo(lim)
  378. print"+"
  379. -- testing local function information
  380. co = load[[
  381. local A = function ()
  382. return x
  383. end
  384. return
  385. ]]
  386. local a = 0
  387. -- 'A' should be visible to debugger only after its complete definition
  388. debug.sethook(function (e, l)
  389. if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == nil)-- assert(debug.getlocal(2, 1) == "(*temporary)") --changed behavior Lua-CSharp
  390. elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
  391. end
  392. end, "l")
  393. co() -- run local function definition
  394. debug.sethook() -- turn off hook
  395. assert(a == 2) -- ensure all two lines where hooked
  396. -- testing traceback
  397. assert(debug.traceback(print) == print)
  398. assert(debug.traceback(print, 4) == print)
  399. assert(string.find(debug.traceback("hi", 4), "^hi\n"))
  400. assert(string.find(debug.traceback("hi"), "^hi\n"))
  401. assert(not string.find(debug.traceback("hi"), "'traceback'"))
  402. assert(string.find(debug.traceback("hi", 0), "'traceback'"))
  403. assert(string.find(debug.traceback(), "^stack traceback:\n"))
  404. -- testing nparams, nups e isvararg
  405. local t = debug.getinfo(print, "u")
  406. assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
  407. t = debug.getinfo(function (a,b,c) end, "u")
  408. assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
  409. t = debug.getinfo(function (a,b,...) return t[a] end, "u")
  410. assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
  411. t = debug.getinfo(1) -- main
  412. assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
  413. debug.getupvalue(t.func, 1) == "_ENV")
  414. -- testing debugging of coroutines
  415. local function checktraceback (co, p, level)
  416. local tb = debug.traceback(co, nil, level)
  417. local i = 0
  418. for l in string.gmatch(tb, "[^\n]+\n?") do
  419. assert(i == 0 or string.find(l, p[i]))
  420. i = i+1
  421. end
  422. assert(p[i] == nil)
  423. end
  424. local function f (n)
  425. if n > 0 then f(n-1)
  426. else coroutine.yield() end
  427. end
  428. local co = coroutine.create(f)
  429. coroutine.resume(co, 3)
  430. checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
  431. checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
  432. checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
  433. checktraceback(co, {"db.lua"}, 4)
  434. checktraceback(co, {}, 40)
  435. co = coroutine.create(function (x)
  436. local a = 1
  437. coroutine.yield(debug.getinfo(1, "l"))
  438. coroutine.yield(debug.getinfo(1, "l").currentline)
  439. return a
  440. end)
  441. local tr = {}
  442. local foo = function (e, l) if l then table.insert(tr, l) end end
  443. debug.sethook(co, foo, "lcr")
  444. local _, l = coroutine.resume(co, 10)
  445. local x = debug.getinfo(co, 1, "lfLS")
  446. assert(x.currentline == l.currentline and x.activelines[x.currentline])
  447. assert(type(x.func) == "function")
  448. for i=x.linedefined + 1, x.lastlinedefined do
  449. assert(x.activelines[i])
  450. x.activelines[i] = nil
  451. end
  452. assert(next(x.activelines) == nil) -- no 'extra' elements
  453. assert(debug.getinfo(co, 2) == nil)
  454. local a,b = debug.getlocal(co, 1, 1)
  455. assert(a == "x" and b == 10)
  456. a,b = debug.getlocal(co, 1, 2)
  457. assert(a == "a" and b == 1)
  458. debug.setlocal(co, 1, 2, "hi")
  459. assert(debug.gethook(co) == foo)
  460. assert(#tr == 2 and
  461. tr[1] == l.currentline-1 and tr[2] == l.currentline)
  462. a,b,c = pcall(coroutine.resume, co)
  463. assert(a and b and c == l.currentline+1)
  464. checktraceback(co, {"yield", "in function <"})
  465. a,b = coroutine.resume(co)
  466. assert(a and b == "hi")
  467. assert(#tr == 4 and tr[4] == l.currentline+2)
  468. assert(debug.gethook(co) == foo)
  469. assert(debug.gethook() == nil)
  470. checktraceback(co, {})
  471. -- check traceback of suspended (or dead with error) coroutines
  472. function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
  473. co = coroutine.create(function (x) f(x) end)
  474. a, b = coroutine.resume(co, 3)
  475. t = {"'yield'", "'f'", "in function <"}
  476. while coroutine.status(co) == "suspended" do
  477. checktraceback(co, t)
  478. a, b = coroutine.resume(co)
  479. table.insert(t, 2, "'f'") -- one more recursive call to 'f'
  480. end
  481. t[1] = "'error'"
  482. checktraceback(co, t)
  483. -- test acessing line numbers of a coroutine from a resume inside
  484. -- a C function (this is a known bug in Lua 5.0)
  485. local function g(x)
  486. coroutine.yield(x)
  487. end
  488. local function f (i)
  489. debug.sethook(function () end, "l")
  490. for j=1,1000 do
  491. g(i+j)
  492. end
  493. end
  494. local co = coroutine.wrap(f)
  495. co(10)
  496. pcall(co)
  497. pcall(co)
  498. assert(type(debug.getregistry()) == "table")
  499. -- test tagmethod information
  500. local a = {}
  501. local function f (t)
  502. local info = debug.getinfo(1);
  503. assert(info.namewhat == "metamethod")
  504. a.op = info.name
  505. return info.name
  506. end
  507. setmetatable(a, {
  508. __index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
  509. __eq = f; __le = f; __lt = f;
  510. })
  511. local b = setmetatable({}, getmetatable(a))
  512. assert(a[3] == "index" and a^3 == "pow" and a..a == "concat")
  513. assert(a/3 == "div" and 3%a == "mod")
  514. assert (a==b and a.op == "eq")
  515. assert (a>=b and a.op == "le")
  516. assert (a>b and a.op == "lt")
  517. print"OK"