github.com/xyproto/gopher-lua@v1.0.2/_lua5.1-tests/errors.lua (about)

     1  print("testing errors")
     2  
     3  function doit (s)
     4    local f, msg = loadstring(s)
     5    if f == nil then return msg end
     6    local cond, msg = pcall(f)
     7    return (not cond) and msg
     8  end
     9  
    10  
    11  function checkmessage (prog, msg)
    12    assert(string.find(doit(prog), msg, 1, true))
    13  end
    14  
    15  function checksyntax (prog, extra, token, line)
    16    local msg = doit(prog)
    17    token = string.gsub(token, "(%p)", "%%%1")
    18    local pt = string.format([[^%%[string ".*"%%]:%d: .- near '%s'$]],
    19                             line, token)
    20    assert(string.find(msg, pt))
    21    assert(string.find(msg, msg, 1, true))
    22  end
    23  
    24  
    25  -- test error message with no extra info
    26  assert(doit("error('hi', 0)") == 'hi')
    27  
    28  -- test error message with no info
    29  assert(doit("error()") == nil)
    30  
    31  
    32  -- test common errors/errors that crashed in the past
    33  assert(doit("unpack({}, 1, n=2^30)"))
    34  assert(doit("a=math.sin()"))
    35  assert(not doit("tostring(1)") and doit("tostring()"))
    36  assert(doit"tonumber()")
    37  assert(doit"repeat until 1; a")
    38  checksyntax("break label", "", "label", 1)
    39  assert(doit";")
    40  assert(doit"a=1;;")
    41  assert(doit"return;;")
    42  assert(doit"assert(false)")
    43  assert(doit"assert(nil)")
    44  assert(doit"a=math.sin\n(3)")
    45  assert(doit("function a (... , ...) end"))
    46  assert(doit("function a (, ...) end"))
    47  
    48  checksyntax([[
    49    local a = {4
    50  
    51  ]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
    52  
    53  
    54  -- tests for better error messages
    55  
    56  checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
    57  checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
    58         "local 'bbbb'")
    59  checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
    60  checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
    61  assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
    62  checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
    63  
    64  aaa = nil
    65  checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
    66  checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
    67  checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
    68  checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'")
    69  assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
    70  
    71  checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
    72  checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
    73  checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
    74  checkmessage("aaa={}; x=-aaa", "global 'aaa'")
    75  assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
    76  assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
    77  
    78  checkmessage([[aaa=9
    79  repeat until 3==3
    80  local x=math.sin(math.cos(3))
    81  if math.sin(1) == x then return math.sin(1) end   -- tail call
    82  local a,b = 1, {
    83    {x='a'..'b'..'c', y='b', z=x},
    84    {1,2,3,4,5} or 3+3<=3+3,
    85    3+1>3+1,
    86    {d = x and aaa[x or y]}}
    87  ]], "global 'aaa'")
    88  
    89  checkmessage([[
    90  local x,y = {},1
    91  if math.sin(1) == 0 then return 3 end    -- return
    92  x.a()]], "field 'a'")
    93  
    94  checkmessage([[
    95  prefix = nil
    96  insert = nil
    97  while 1 do  
    98    local a
    99    if nil then break end
   100    insert(prefix, a)
   101  end]], "global 'insert'")
   102  
   103  checkmessage([[  -- tail call
   104    return math.sin("a")
   105  ]], "'sin'")
   106  
   107  checkmessage([[collectgarbage("nooption")]], "invalid option")
   108  
   109  checkmessage([[x = print .. "a"]], "concatenate")
   110  
   111  checkmessage("getmetatable(io.stdin).__gc()", "no value")
   112  
   113  print'+'
   114  
   115  
   116  -- testing line error
   117  
   118  function lineerror (s)
   119    local err,msg = pcall(loadstring(s))
   120    local line = string.match(msg, ":(%d+):")
   121    return line and line+0
   122  end
   123  
   124  assert(lineerror"local a\n for i=1,'a' do \n print(i) \n end" == 2)
   125  assert(lineerror"\n local a \n for k,v in 3 \n do \n print(k) \n end" == 3)
   126  assert(lineerror"\n\n for k,v in \n 3 \n do \n print(k) \n end" == 4)
   127  assert(lineerror"function a.x.y ()\na=a+1\nend" == 1)
   128  
   129  local p = [[
   130  function g() f() end
   131  function f(x) error('a', X) end
   132  g()
   133  ]]
   134  X=3;assert(lineerror(p) == 3)
   135  X=0;assert(lineerror(p) == nil)
   136  X=1;assert(lineerror(p) == 2)
   137  X=2;assert(lineerror(p) == 1)
   138  
   139  lineerror = nil
   140  
   141  C = 0
   142  local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
   143  
   144  local function checkstackmessage (m)
   145    return (string.find(m, "^.-:%d+: stack overflow"))
   146  end
   147  assert(checkstackmessage(doit('y()')))
   148  assert(checkstackmessage(doit('y()')))
   149  assert(checkstackmessage(doit('y()')))
   150  -- teste de linhas em erro
   151  C = 0
   152  local l1
   153  local function g()
   154    l1 = debug.getinfo(1, "l").currentline; y()
   155  end
   156  local _, stackmsg = xpcall(g, debug.traceback)
   157  local stack = {}
   158  for line in string.gmatch(stackmsg, "[^\n]*") do
   159    local curr = string.match(line, ":(%d+):")
   160    if curr then table.insert(stack, tonumber(curr)) end
   161  end
   162  local i=1
   163  while stack[i] ~= l1 do
   164    assert(stack[i] == l)
   165    i = i+1
   166  end
   167  assert(i > 15)
   168  
   169  
   170  -- error in error handling
   171  local res, msg = xpcall(error, error)
   172  assert(not res and type(msg) == 'string')
   173  
   174  local function f (x)
   175    if x==0 then error('a\n')
   176    else
   177      local aux = function () return f(x-1) end
   178      local a,b = xpcall(aux, aux)
   179      return a,b
   180    end
   181  end
   182  f(3)
   183  
   184  -- non string messages
   185  function f() error{msg='x'} end
   186  res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
   187  assert(msg.msg == 'xy')
   188  
   189  print('+')
   190  checksyntax("syntax error", "", "error", 1)
   191  checksyntax("1.000", "", "1.000", 1)
   192  checksyntax("[[a]]", "", "[[a]]", 1)
   193  checksyntax("'aa'", "", "'aa'", 1)
   194  
   195  -- test 255 as first char in a chunk
   196  checksyntax("\255a = 1", "", "\255", 1)
   197  
   198  doit('I = loadstring("a=9+"); a=3')
   199  assert(a==3 and I == nil)
   200  print('+')
   201  
   202  lim = 1000
   203  if rawget(_G, "_soft") then lim = 100 end
   204  for i=1,lim do
   205    doit('a = ')
   206    doit('a = 4+nil')
   207  end
   208  
   209  
   210  -- testing syntax limits
   211  local function testrep (init, rep)
   212    local s = "local a; "..init .. string.rep(rep, 400)
   213    local a,b = loadstring(s)
   214    assert(not a and string.find(b, "syntax levels"))
   215  end
   216  testrep("a=", "{")
   217  testrep("a=", "(")
   218  testrep("", "a(")
   219  testrep("", "do ")
   220  testrep("", "while a do ")
   221  testrep("", "if a then else ")
   222  testrep("", "function foo () ")
   223  testrep("a=", "a..")
   224  testrep("a=", "a^")
   225  
   226  
   227  -- testing other limits
   228  -- upvalues
   229  local  s = "function foo ()\n  local "
   230  for j = 1,70 do
   231    s = s.."a"..j..", "
   232  end
   233  s = s.."b\n"
   234  for j = 1,70 do
   235    s = s.."function foo"..j.." ()\n a"..j.."=3\n"
   236  end
   237  local a,b = loadstring(s)
   238  assert(string.find(b, "line 3"))
   239  
   240  -- local variables
   241  s = "\nfunction foo ()\n  local "
   242  for j = 1,300 do
   243    s = s.."a"..j..", " 
   244  end
   245  s = s.."b\n"
   246  local a,b = loadstring(s)
   247  assert(string.find(b, "line 2"))
   248  
   249  
   250  print('OK')