summaryrefslogtreecommitdiff
path: root/testes/errors.lua
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 14:46:37 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 14:46:37 -0200
commit063d4e4543088e7a21965bda8ee5a0f952a9029e (patch)
tree6c3f2f8e98c26f071a94a32f9f2754396a66a9de /testes/errors.lua
parente354c6355e7f48e087678ec49e340ca0696725b1 (diff)
downloadlua-5.3.5.tar.gz
lua-5.3.5.tar.bz2
lua-5.3.5.zip
Lua 5.3.5 ported to gitv5.3.5
This is the first commit for the branch Lua 5.3. All source files were copied from the official distribution of 5.3.5 in the Lua site. The test files are the same of 5.3.4. The manual came from the previous RCS repository, revision 1.167.1.2.
Diffstat (limited to 'testes/errors.lua')
-rw-r--r--testes/errors.lua537
1 files changed, 537 insertions, 0 deletions
diff --git a/testes/errors.lua b/testes/errors.lua
new file mode 100644
index 00000000..79d746c7
--- /dev/null
+++ b/testes/errors.lua
@@ -0,0 +1,537 @@
1-- $Id: errors.lua,v 1.94 2016/12/21 19:23:02 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing errors")
5
6local debug = require"debug"
7
8-- avoid problems with 'strict' module (which may generate other error messages)
9local mt = getmetatable(_G) or {}
10local oldmm = mt.__index
11mt.__index = nil
12
13local function checkerr (msg, f, ...)
14 local st, err = pcall(f, ...)
15 assert(not st and string.find(err, msg))
16end
17
18
19local function doit (s)
20 local f, msg = load(s)
21 if f == nil then return msg end
22 local cond, msg = pcall(f)
23 return (not cond) and msg
24end
25
26
27local function checkmessage (prog, msg)
28 local m = doit(prog)
29 assert(string.find(m, msg, 1, true))
30end
31
32local function checksyntax (prog, extra, token, line)
33 local msg = doit(prog)
34 if not string.find(token, "^<%a") and not string.find(token, "^char%(")
35 then token = "'"..token.."'" end
36 token = string.gsub(token, "(%p)", "%%%1")
37 local pt = string.format([[^%%[string ".*"%%]:%d: .- near %s$]],
38 line, token)
39 assert(string.find(msg, pt))
40 assert(string.find(msg, msg, 1, true))
41end
42
43
44-- test error message with no extra info
45assert(doit("error('hi', 0)") == 'hi')
46
47-- test error message with no info
48assert(doit("error()") == nil)
49
50
51-- test common errors/errors that crashed in the past
52assert(doit("table.unpack({}, 1, n=2^30)"))
53assert(doit("a=math.sin()"))
54assert(not doit("tostring(1)") and doit("tostring()"))
55assert(doit"tonumber()")
56assert(doit"repeat until 1; a")
57assert(doit"return;;")
58assert(doit"assert(false)")
59assert(doit"assert(nil)")
60assert(doit("function a (... , ...) end"))
61assert(doit("function a (, ...) end"))
62assert(doit("local t={}; t = t[#t] + 1"))
63
64checksyntax([[
65 local a = {4
66
67]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
68
69
70-- tests for better error messages
71
72checkmessage("a = {} + 1", "arithmetic")
73checkmessage("a = {} | 1", "bitwise operation")
74checkmessage("a = {} < 1", "attempt to compare")
75checkmessage("a = {} <= 1", "attempt to compare")
76
77checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
78checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
79checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
80assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
81checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
82checkmessage("a=(1)..{}", "a table value")
83
84checkmessage("a = #print", "length of a function value")
85checkmessage("a = #3", "length of a number value")
86
87aaa = nil
88checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
89checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
90checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
91checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'")
92assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
93
94-- upvalues being indexed do not go to the stack
95checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
96checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
97
98checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
99
100checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
101checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
102checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
103checkmessage("aaa={}; x=-aaa", "global 'aaa'")
104
105-- short circuit
106checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
107 "local 'bbbb'")
108checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'")
109checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
110checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
111assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
112assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
113
114checkmessage("print(print < 10)", "function with number")
115checkmessage("print(print < print)", "two function values")
116checkmessage("print('10' < 10)", "string with number")
117checkmessage("print(10 < '23')", "number with string")
118
119-- float->integer conversions
120checkmessage("local a = 2.0^100; x = a << 2", "local a")
121checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
122checkmessage("local a = '10' << 2.0^100", "has no integer representation")
123checkmessage("local a = 2.0^100 & 1", "has no integer representation")
124checkmessage("local a = 2.0^100 & '1'", "has no integer representation")
125checkmessage("local a = 2.0 | 1e40", "has no integer representation")
126checkmessage("local a = 2e100 ~ 1", "has no integer representation")
127checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
128checkmessage("string.rep('a', 3.3)", "has no integer representation")
129checkmessage("return 6e40 & 7", "has no integer representation")
130checkmessage("return 34 << 7e30", "has no integer representation")
131checkmessage("return ~-3e40", "has no integer representation")
132checkmessage("return ~-3.009", "has no integer representation")
133checkmessage("return 3.009 & 1", "has no integer representation")
134checkmessage("return 34 >> {}", "table value")
135checkmessage("a = 24 // 0", "divide by zero")
136checkmessage("a = 1 % 0", "'n%0'")
137
138
139-- passing light userdata instead of full userdata
140_G.D = debug
141checkmessage([[
142 -- create light udata
143 local x = D.upvalueid(function () return debug end, 1)
144 D.setuservalue(x, {})
145]], "light userdata")
146_G.D = nil
147
148do -- named objects (field '__name')
149 checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
150 _G.XX = setmetatable({}, {__name = "My Type"})
151 assert(string.find(tostring(XX), "^My Type"))
152 checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
153 checkmessage("return XX + 1", "on a My Type value")
154 checkmessage("return ~io.stdin", "on a FILE* value")
155 checkmessage("return XX < XX", "two My Type values")
156 checkmessage("return {} < XX", "table with My Type")
157 checkmessage("return XX < io.stdin", "My Type with FILE*")
158 _G.XX = nil
159end
160
161-- global functions
162checkmessage("(io.write or print){}", "io.write")
163checkmessage("(collectgarbage or print){}", "collectgarbage")
164
165-- errors in functions without debug info
166do
167 local f = function (a) return a + 1 end
168 f = assert(load(string.dump(f, true)))
169 assert(f(3) == 4)
170 checkerr("^%?:%-1:", f, {})
171
172 -- code with a move to a local var ('OP_MOV A B' with A<B)
173 f = function () local a; a = {}; return a + 2 end
174 -- no debug info (so that 'a' is unknown)
175 f = assert(load(string.dump(f, true)))
176 -- symbolic execution should not get lost
177 checkerr("^%?:%-1:.*table value", f)
178end
179
180
181-- tests for field accesses after RK limit
182local t = {}
183for i = 1, 1000 do
184 t[i] = "a = x" .. i
185end
186local s = table.concat(t, "; ")
187t = nil
188checkmessage(s.."; a = bbb + 1", "global 'bbb'")
189checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'")
190checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'")
191checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
192
193checkmessage([[aaa=9
194repeat until 3==3
195local x=math.sin(math.cos(3))
196if math.sin(1) == x then return math.sin(1) end -- tail call
197local a,b = 1, {
198 {x='a'..'b'..'c', y='b', z=x},
199 {1,2,3,4,5} or 3+3<=3+3,
200 3+1>3+1,
201 {d = x and aaa[x or y]}}
202]], "global 'aaa'")
203
204checkmessage([[
205local x,y = {},1
206if math.sin(1) == 0 then return 3 end -- return
207x.a()]], "field 'a'")
208
209checkmessage([[
210prefix = nil
211insert = nil
212while 1 do
213 local a
214 if nil then break end
215 insert(prefix, a)
216end]], "global 'insert'")
217
218checkmessage([[ -- tail call
219 return math.sin("a")
220]], "'sin'")
221
222checkmessage([[collectgarbage("nooption")]], "invalid option")
223
224checkmessage([[x = print .. "a"]], "concatenate")
225checkmessage([[x = "a" .. false]], "concatenate")
226checkmessage([[x = {} .. 2]], "concatenate")
227
228checkmessage("getmetatable(io.stdin).__gc()", "no value")
229
230checkmessage([[
231local Var
232local function main()
233 NoSuchName (function() Var=0 end)
234end
235main()
236]], "global 'NoSuchName'")
237print'+'
238
239a = {}; setmetatable(a, {__index = string})
240checkmessage("a:sub()", "bad self")
241checkmessage("string.sub('a', {})", "#2")
242checkmessage("('a'):sub{}", "#1")
243
244checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
245checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
246
247-- tests for errors in coroutines
248
249local function f (n)
250 local c = coroutine.create(f)
251 local a,b = coroutine.resume(c)
252 return b
253end
254assert(string.find(f(), "C stack overflow"))
255
256checkmessage("coroutine.yield()", "outside a coroutine")
257
258f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
259checkerr("yield across", f)
260
261
262-- testing size of 'source' info; size of buffer for that info is
263-- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
264idsize = 60 - 1
265local function checksize (source)
266 -- syntax error
267 local _, msg = load("x", source)
268 msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
269 assert(msg:len() <= idsize)
270end
271
272for i = 60 - 10, 60 + 10 do -- check border cases around 60
273 checksize("@" .. string.rep("x", i)) -- file names
274 checksize(string.rep("x", i - 10)) -- string sources
275 checksize("=" .. string.rep("x", i)) -- exact sources
276end
277
278
279-- testing line error
280
281local function lineerror (s, l)
282 local err,msg = pcall(load(s))
283 local line = string.match(msg, ":(%d+):")
284 assert((line and line+0) == l)
285end
286
287lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
288lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3)
289lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4)
290lineerror("function a.x.y ()\na=a+1\nend", 1)
291
292lineerror("a = \na\n+\n{}", 3)
293lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6)
294lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3)
295
296lineerror("a\n=\n-\n\nprint\n;", 3)
297
298lineerror([[
299a
300(
30123)
302]], 1)
303
304lineerror([[
305local a = {x = 13}
306a
307.
308x
309(
31023
311)
312]], 2)
313
314lineerror([[
315local a = {x = 13}
316a
317.
318x
319(
32023 + a
321)
322]], 6)
323
324local p = [[
325 function g() f() end
326 function f(x) error('a', X) end
327g()
328]]
329X=3;lineerror((p), 3)
330X=0;lineerror((p), nil)
331X=1;lineerror((p), 2)
332X=2;lineerror((p), 1)
333
334
335if not _soft then
336 -- several tests that exaust the Lua stack
337 collectgarbage()
338 print"testing stack overflow"
339 C = 0
340 local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
341
342 local function checkstackmessage (m)
343 return (string.find(m, "^.-:%d+: stack overflow"))
344 end
345 -- repeated stack overflows (to check stack recovery)
346 assert(checkstackmessage(doit('y()')))
347 print('+')
348 assert(checkstackmessage(doit('y()')))
349 print('+')
350 assert(checkstackmessage(doit('y()')))
351 print('+')
352
353
354 -- error lines in stack overflow
355 C = 0
356 local l1
357 local function g(x)
358 l1 = debug.getinfo(x, "l").currentline; y()
359 end
360 local _, stackmsg = xpcall(g, debug.traceback, 1)
361 print('+')
362 local stack = {}
363 for line in string.gmatch(stackmsg, "[^\n]*") do
364 local curr = string.match(line, ":(%d+):")
365 if curr then table.insert(stack, tonumber(curr)) end
366 end
367 local i=1
368 while stack[i] ~= l1 do
369 assert(stack[i] == l)
370 i = i+1
371 end
372 assert(i > 15)
373
374
375 -- error in error handling
376 local res, msg = xpcall(error, error)
377 assert(not res and type(msg) == 'string')
378 print('+')
379
380 local function f (x)
381 if x==0 then error('a\n')
382 else
383 local aux = function () return f(x-1) end
384 local a,b = xpcall(aux, aux)
385 return a,b
386 end
387 end
388 f(3)
389
390 local function loop (x,y,z) return 1 + loop(x, y, z) end
391
392 local res, msg = xpcall(loop, function (m)
393 assert(string.find(m, "stack overflow"))
394 checkerr("error handling", loop)
395 assert(math.sin(0) == 0)
396 return 15
397 end)
398 assert(msg == 15)
399
400 local f = function ()
401 for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
402 end
403 checkerr("too many results", f)
404
405end
406
407
408do
409 -- non string messages
410 local t = {}
411 local res, msg = pcall(function () error(t) end)
412 assert(not res and msg == t)
413
414 res, msg = pcall(function () error(nil) end)
415 assert(not res and msg == nil)
416
417 local function f() error{msg='x'} end
418 res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
419 assert(msg.msg == 'xy')
420
421 -- 'assert' with extra arguments
422 res, msg = pcall(assert, false, "X", t)
423 assert(not res and msg == "X")
424
425 -- 'assert' with no message
426 res, msg = pcall(function () assert(false) end)
427 local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
428 assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
429
430 -- 'assert' with non-string messages
431 res, msg = pcall(assert, false, t)
432 assert(not res and msg == t)
433
434 res, msg = pcall(assert, nil, nil)
435 assert(not res and msg == nil)
436
437 -- 'assert' without arguments
438 res, msg = pcall(assert)
439 assert(not res and string.find(msg, "value expected"))
440end
441
442-- xpcall with arguments
443a, b, c = xpcall(string.find, error, "alo", "al")
444assert(a and b == 1 and c == 2)
445a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
446assert(not a and type(b) == "table" and c == nil)
447
448
449print("testing tokens in error messages")
450checksyntax("syntax error", "", "error", 1)
451checksyntax("1.000", "", "1.000", 1)
452checksyntax("[[a]]", "", "[[a]]", 1)
453checksyntax("'aa'", "", "'aa'", 1)
454checksyntax("while << do end", "", "<<", 1)
455checksyntax("for >> do end", "", ">>", 1)
456
457-- test invalid non-printable char in a chunk
458checksyntax("a\1a = 1", "", "<\\1>", 1)
459
460-- test 255 as first char in a chunk
461checksyntax("\255a = 1", "", "<\\255>", 1)
462
463doit('I = load("a=9+"); a=3')
464assert(a==3 and I == nil)
465print('+')
466
467lim = 1000
468if _soft then lim = 100 end
469for i=1,lim do
470 doit('a = ')
471 doit('a = 4+nil')
472end
473
474
475-- testing syntax limits
476
477local maxClevel = 200 -- LUAI_MAXCCALLS (in llimits.h)
478
479local function testrep (init, rep, close, repc)
480 local s = init .. string.rep(rep, maxClevel - 10) .. close ..
481 string.rep(repc, maxClevel - 10)
482 assert(load(s)) -- 190 levels is OK
483 s = init .. string.rep(rep, maxClevel + 1)
484 checkmessage(s, "too many C levels")
485end
486
487testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
488testrep("local a; a=", "{", "0", "}")
489testrep("local a; a=", "(", "2", ")")
490testrep("local a; ", "a(", "2", ")")
491testrep("", "do ", "", " end")
492testrep("", "while a do ", "", " end")
493testrep("local a; ", "if a then else ", "", " end")
494testrep("", "function foo () ", "", " end")
495testrep("local a; a=", "a..", "a", "")
496testrep("local a; a=", "a^", "a", "")
497
498checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
499
500
501-- testing other limits
502
503-- upvalues
504local lim = 127
505local s = "local function fooA ()\n local "
506for j = 1,lim do
507 s = s.."a"..j..", "
508end
509s = s.."b,c\n"
510s = s.."local function fooB ()\n local "
511for j = 1,lim do
512 s = s.."b"..j..", "
513end
514s = s.."b\n"
515s = s.."function fooC () return b+c"
516local c = 1+2
517for j = 1,lim do
518 s = s.."+a"..j.."+b"..j
519 c = c + 2
520end
521s = s.."\nend end end"
522local a,b = load(s)
523assert(c > 255 and string.find(b, "too many upvalues") and
524 string.find(b, "line 5"))
525
526-- local variables
527s = "\nfunction foo ()\n local "
528for j = 1,300 do
529 s = s.."a"..j..", "
530end
531s = s.."b\n"
532local a,b = load(s)
533assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
534
535mt.__index = oldmm
536
537print('OK')