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