github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/db.lua (about)

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