errors.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. -- $Id: testes/errors.lua $
  2. -- See Copyright Notice in file lua.h
  3. print("testing errors")
  4. local debug = require"debug"
  5. -- avoid problems with 'strict' module (which may generate other error messages)
  6. local mt = getmetatable(_G) or {}
  7. local oldmm = mt.__index
  8. mt.__index = nil
  9. local function checkerr (msg, f, ...)
  10. local st, err = pcall(f, ...)
  11. assert(not st and string.find(err, msg))
  12. end
  13. local function doit (s)
  14. local f, msg = load(s)
  15. if not f then return msg end
  16. local cond, msg = pcall(f)
  17. return (not cond) and msg
  18. end
  19. local function checkmessage (prog, msg, debug)
  20. local m = doit(prog)
  21. if debug then print(m, msg) end
  22. assert(string.find(m, msg, 1, true))
  23. end
  24. local function checksyntax (prog, extra, token, line)
  25. local msg = doit(prog)
  26. if not string.find(token, "^<%a") and not string.find(token, "^char%(")
  27. then token = "'"..token.."'" end
  28. token = string.gsub(token, "(%p)", "%%%1")
  29. local pt = string.format([[^%%[string ".*"%%]:%d: .- near %s$]],
  30. line, token)
  31. assert(string.find(msg, pt))
  32. assert(string.find(msg, msg, 1, true))
  33. end
  34. -- test error message with no extra info
  35. assert(doit("error('hi', 0)") == 'hi')
  36. -- test nil error message
  37. assert(doit("error()") == "<no error object>")
  38. -- test common errors/errors that crashed in the past
  39. assert(doit("table.unpack({}, 1, n=2^30)"))
  40. assert(doit("a=math.sin()"))
  41. assert(not doit("tostring(1)") and doit("tostring()"))
  42. assert(doit"tonumber()")
  43. assert(doit"repeat until 1; a")
  44. assert(doit"return;;")
  45. assert(doit"assert(false)")
  46. assert(doit"assert(nil)")
  47. assert(doit("function a (... , ...) end"))
  48. assert(doit("function a (, ...) end"))
  49. assert(doit("local t={}; t = t[#t] + 1"))
  50. checksyntax([[
  51. local a = {4
  52. ]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
  53. do -- testing errors in goto/break
  54. local function checksyntax (prog, msg, line)
  55. local st, err = load(prog)
  56. assert(string.find(err, "line " .. line))
  57. assert(string.find(err, msg, 1, true))
  58. end
  59. checksyntax([[
  60. ::A:: a = 1
  61. ::A::
  62. ]], "label 'A' already defined", 1)
  63. checksyntax([[
  64. a = 1
  65. goto A
  66. do ::A:: end
  67. ]], "no visible label 'A'", 2)
  68. end
  69. if not T then
  70. (Message or print)
  71. ('\n >>> testC not active: skipping tests for messages in C <<<\n')
  72. else
  73. print "testing memory error message"
  74. local a = {}
  75. for i = 1, 10000 do a[i] = true end -- preallocate array
  76. collectgarbage()
  77. T.totalmem(T.totalmem() + 10000)
  78. -- force a memory error (by a small margin)
  79. local st, msg = pcall(function()
  80. for i = 1, 100000 do a[i] = tostring(i) end
  81. end)
  82. T.totalmem(0)
  83. assert(not st and msg == "not enough" .. " memory")
  84. -- stack space for luaL_traceback (bug in 5.4.6)
  85. local res = T.testC[[
  86. # push 16 elements on the stack
  87. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  88. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  89. pushnum 1; pushnum 1; pushnum 1; pushnum 1; pushnum 1;
  90. pushnum 1;
  91. # traceback should work with 4 remaining slots
  92. traceback xuxu 1;
  93. return 1
  94. ]]
  95. assert(string.find(res, "xuxu.-main chunk"))
  96. do -- tests for error messages about extra arguments from __call
  97. local function createobj (n)
  98. -- function that raises an error on its n-th argument
  99. local code = string.format("argerror %d 'msg'", n)
  100. local func = T.makeCfunc(code)
  101. -- create a chain of 2 __call objects
  102. local M = setmetatable({}, {__call = func})
  103. M = setmetatable({}, {__call = M})
  104. -- put it as a method for a new object
  105. return {foo = M}
  106. end
  107. _G.a = createobj(1) -- error in first (extra) argument
  108. checkmessage("a:foo()", "bad extra argument #1")
  109. _G.a = createobj(2) -- error in second (extra) argument
  110. checkmessage("a:foo()", "bad extra argument #2")
  111. _G.a = createobj(3) -- error in self (after two extra arguments)
  112. checkmessage("a:foo()", "bad self")
  113. _G.a = createobj(4) -- error in first regular argument (after self)
  114. checkmessage("a:foo()", "bad argument #1")
  115. end
  116. end
  117. -- tests for better error messages
  118. checkmessage("a = {} + 1", "arithmetic")
  119. checkmessage("a = {} | 1", "bitwise operation")
  120. checkmessage("a = {} < 1", "attempt to compare")
  121. checkmessage("a = {} <= 1", "attempt to compare")
  122. checkmessage("aaa=1; bbbb=2; aaa=math.sin(3)+bbbb(3)", "global 'bbbb'")
  123. checkmessage("aaa={}; do local aaa=1 end aaa:bbbb(3)", "method 'bbbb'")
  124. checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
  125. assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'"))
  126. checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
  127. checkmessage("aaa=(1)..{}", "a table value")
  128. -- bug in 5.4.6
  129. checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'")
  130. -- a similar bug, since 5.4.0
  131. checkmessage("print(('_ENV').x + 1)", "field 'x'")
  132. _G.aaa, _G.bbbb = nil
  133. -- calls
  134. checkmessage("local a; a(13)", "local 'a'")
  135. checkmessage([[
  136. local a = setmetatable({}, {__add = 34})
  137. a = a + 1
  138. ]], "metamethod 'add'")
  139. checkmessage([[
  140. local a = setmetatable({}, {__lt = {}})
  141. a = a > a
  142. ]], "metamethod 'lt'")
  143. -- tail calls
  144. checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
  145. checkmessage("aaa={}; do local aaa=1 end; return aaa:bbbb(3)", "method 'bbbb'")
  146. checkmessage("aaa = #print", "length of a function value")
  147. checkmessage("aaa = #3", "length of a number value")
  148. _G.aaa = nil
  149. checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
  150. checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
  151. checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
  152. checkmessage("local a,b,c; (function () a = b+1.1 end)()", "upvalue 'b'")
  153. assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
  154. -- upvalues being indexed do not go to the stack
  155. checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
  156. checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
  157. checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
  158. checkmessage("BB=1; local aaa={}; x=aaa+BB", "local 'aaa'")
  159. checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
  160. checkmessage("aaa=2; BB=nil;x=aaa*BB", "global 'BB'")
  161. checkmessage("aaa={}; x=-aaa", "global 'aaa'")
  162. -- short circuit
  163. checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = math.sin(1) and bbbb(3)",
  164. "local 'bbbb'")
  165. checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = bbbb(1) or aaa(3)",
  166. "local 'bbbb'")
  167. checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
  168. checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
  169. assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
  170. assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
  171. checkmessage("print(print < 10)", "function with number")
  172. checkmessage("print(print < print)", "two function values")
  173. checkmessage("print('10' < 10)", "string with number")
  174. checkmessage("print(10 < '23')", "number with string")
  175. -- float->integer conversions
  176. checkmessage("local a = 2.0^100; x = a << 2", "local a")
  177. checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
  178. checkmessage("local a = 10.1 << 2.0^100", "has no integer representation")
  179. checkmessage("local a = 2.0^100 & 1", "has no integer representation")
  180. checkmessage("local a = 2.0^100 & 1e100", "has no integer representation")
  181. checkmessage("local a = 2.0 | 1e40", "has no integer representation")
  182. checkmessage("local a = 2e100 ~ 1", "has no integer representation")
  183. checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
  184. checkmessage("string.rep('a', 3.3)", "has no integer representation")
  185. checkmessage("return 6e40 & 7", "has no integer representation")
  186. checkmessage("return 34 << 7e30", "has no integer representation")
  187. checkmessage("return ~-3e40", "has no integer representation")
  188. checkmessage("return ~-3.009", "has no integer representation")
  189. checkmessage("return 3.009 & 1", "has no integer representation")
  190. checkmessage("return 34 >> {}", "table value")
  191. checkmessage("aaa = 24 // 0", "divide by zero")
  192. checkmessage("aaa = 1 % 0", "'n%0'")
  193. -- type error for an object which is neither in an upvalue nor a register.
  194. -- The following code will try to index the value 10 that is stored in
  195. -- the metatable, without moving it to a register.
  196. checkmessage("local a = setmetatable({}, {__index = 10}).x",
  197. "attempt to index a number value")
  198. -- numeric for loops
  199. checkmessage("for i = {}, 10 do end", "table")
  200. checkmessage("for i = io.stdin, 10 do end", "FILE")
  201. checkmessage("for i = {}, 10 do end", "initial value")
  202. checkmessage("for i = 1, 'x', 10 do end", "string")
  203. checkmessage("for i = 1, {}, 10 do end", "limit")
  204. checkmessage("for i = 1, {} do end", "limit")
  205. checkmessage("for i = 1, 10, print do end", "step")
  206. checkmessage("for i = 1, 10, print do end", "function")
  207. -- passing light userdata instead of full userdata
  208. _G.D = debug
  209. checkmessage([[
  210. -- create light udata
  211. local x = D.upvalueid(function () return debug end, 1)
  212. D.setuservalue(x, {})
  213. ]], "light userdata")
  214. _G.D = nil
  215. do -- named objects (field '__name')
  216. checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
  217. _G.XX = setmetatable({}, {__name = "My Type"})
  218. assert(string.find(tostring(XX), "^My Type"))
  219. checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
  220. checkmessage("return XX + 1", "on a My Type value")
  221. checkmessage("return ~io.stdin", "on a FILE* value")
  222. checkmessage("return XX < XX", "two My Type values")
  223. checkmessage("return {} < XX", "table with My Type")
  224. checkmessage("return XX < io.stdin", "My Type with FILE*")
  225. _G.XX = nil
  226. if T then -- extra tests for 'luaL_tolstring'
  227. -- bug in 5.4.3; 'luaL_tolstring' with negative indices
  228. local x = setmetatable({}, {__name="TABLE"})
  229. assert(T.testC("Ltolstring -1; return 1", x) == tostring(x))
  230. local a, b = T.testC("pushint 10; Ltolstring -2; return 2", x)
  231. assert(a == 10 and b == tostring(x))
  232. setmetatable(x, {__tostring=function (o)
  233. assert(o == x)
  234. return "ABC"
  235. end})
  236. local a, b, c = T.testC("pushint 10; Ltolstring -2; return 3", x)
  237. assert(a == x and b == 10 and c == "ABC")
  238. end
  239. end
  240. -- global functions
  241. checkmessage("(io.write or print){}", "io.write")
  242. checkmessage("(collectgarbage or print){}", "collectgarbage")
  243. -- errors in functions without debug info
  244. do
  245. local f = function (a) return a + 1 end
  246. f = assert(load(string.dump(f, true)))
  247. assert(f(3) == 4)
  248. checkerr("^%?:%?:", f, {})
  249. -- code with a move to a local var ('OP_MOV A B' with A<B)
  250. f = function () local a; a = {}; return a + 2 end
  251. -- no debug info (so that 'a' is unknown)
  252. f = assert(load(string.dump(f, true)))
  253. -- symbolic execution should not get lost
  254. checkerr("^%?:%?:.*table value", f)
  255. end
  256. -- tests for field accesses after RK limit
  257. local t = {}
  258. for i = 1, 1000 do
  259. t[i] = "aaa = x" .. i
  260. end
  261. local s = table.concat(t, "; ")
  262. t = nil
  263. checkmessage(s.."; aaa = bbb + 1", "global 'bbb'")
  264. checkmessage("local _ENV=_ENV;"..s.."; aaa = bbb + 1", "global 'bbb'")
  265. checkmessage(s.."; local t = {}; aaa = t.bbb + 1", "field 'bbb'")
  266. -- cannot use 'self' opcode
  267. checkmessage(s.."; local t = {}; t:bbb()", "field 'bbb'")
  268. checkmessage([[aaa=9
  269. repeat until 3==3
  270. local x=math.sin(math.cos(3))
  271. if math.sin(1) == x then return math.sin(1) end -- tail call
  272. local a,b = 1, {
  273. {x='a'..'b'..'c', y='b', z=x},
  274. {1,2,3,4,5} or 3+3<=3+3,
  275. 3+1>3+1,
  276. {d = x and aaa[x or y]}}
  277. ]], "global 'aaa'")
  278. checkmessage([[
  279. local x,y = {},1
  280. if math.sin(1) == 0 then return 3 end -- return
  281. x.a()]], "field 'a'")
  282. checkmessage([[
  283. prefix = nil
  284. insert = nil
  285. while 1 do
  286. local a
  287. if nil then break end
  288. insert(prefix, a)
  289. end]], "global 'insert'")
  290. checkmessage([[ -- tail call
  291. return math.sin("a")
  292. ]], "sin")
  293. checkmessage([[collectgarbage("nooption")]], "invalid option")
  294. checkmessage([[x = print .. "a"]], "concatenate")
  295. checkmessage([[x = "a" .. false]], "concatenate")
  296. checkmessage([[x = {} .. 2]], "concatenate")
  297. checkmessage("getmetatable(io.stdin).__gc()", "no value")
  298. checkmessage([[
  299. local Var
  300. local function main()
  301. NoSuchName (function() Var=0 end)
  302. end
  303. main()
  304. ]], "global 'NoSuchName'")
  305. print'+'
  306. aaa = {}; setmetatable(aaa, {__index = string})
  307. checkmessage("aaa:sub()", "bad self")
  308. checkmessage("string.sub('a', {})", "#2")
  309. checkmessage("('a'):sub{}", "#1")
  310. checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
  311. checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
  312. _G.aaa = nil
  313. -- tests for errors in coroutines
  314. local function f (n)
  315. local c = coroutine.create(f)
  316. local a,b = coroutine.resume(c)
  317. return b
  318. end
  319. assert(string.find(f(), "C stack overflow"))
  320. checkmessage("coroutine.yield()", "outside a coroutine")
  321. f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
  322. checkerr("yield across", f)
  323. -- testing size of 'source' info; size of buffer for that info is
  324. -- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
  325. local idsize = 60 - 1
  326. local function checksize (source)
  327. -- syntax error
  328. local _, msg = load("x", source)
  329. msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
  330. assert(msg:len() <= idsize)
  331. end
  332. for i = 60 - 10, 60 + 10 do -- check border cases around 60
  333. checksize("@" .. string.rep("x", i)) -- file names
  334. checksize(string.rep("x", i - 10)) -- string sources
  335. checksize("=" .. string.rep("x", i)) -- exact sources
  336. end
  337. -- testing line error
  338. local function lineerror (s, l)
  339. local err,msg = pcall(load(s))
  340. local line = tonumber(string.match(msg, ":(%d+):"))
  341. assert(line == l or (not line and not l))
  342. end
  343. lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
  344. lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3)
  345. lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4)
  346. lineerror("function a.x.y ()\na=a+1\nend", 1)
  347. lineerror("a = \na\n+\n{}", 3)
  348. lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6)
  349. lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3)
  350. lineerror("a\n=\n-\n\nprint\n;", 3)
  351. lineerror([[
  352. a
  353. ( -- <<
  354. 23)
  355. ]], 2)
  356. lineerror([[
  357. local a = {x = 13}
  358. a
  359. .
  360. x
  361. ( -- <<
  362. 23
  363. )
  364. ]], 5)
  365. lineerror([[
  366. local a = {x = 13}
  367. a
  368. .
  369. x
  370. (
  371. 23 + a
  372. )
  373. ]], 6)
  374. local p = [[
  375. function g() f() end
  376. function f(x) error('a', XX) end
  377. g()
  378. ]]
  379. XX=3;lineerror((p), 3)
  380. XX=0;lineerror((p), false)
  381. XX=1;lineerror((p), 2)
  382. XX=2;lineerror((p), 1)
  383. _G.XX, _G.g, _G.f = nil
  384. lineerror([[
  385. local b = false
  386. if not b then
  387. error 'test'
  388. end]], 3)
  389. lineerror([[
  390. local b = false
  391. if not b then
  392. if not b then
  393. if not b then
  394. error 'test'
  395. end
  396. end
  397. end]], 5)
  398. lineerror([[
  399. _ENV = 1
  400. global function foo ()
  401. local a = 10
  402. return a
  403. end
  404. ]], 2)
  405. -- bug in 5.4.0
  406. lineerror([[
  407. local a = 0
  408. local b = 1
  409. local c = b % a
  410. ]], 3)
  411. do
  412. -- Force a negative estimate for base line. Error in instruction 2
  413. -- (after VARARGPREP, GETGLOBAL), with first absolute line information
  414. -- (forced by too many lines) in instruction 0.
  415. local s = string.format("%s return __A.x", string.rep("\n", 300))
  416. lineerror(s, 301)
  417. end
  418. if not _soft then
  419. -- several tests that exhaust the Lua stack
  420. collectgarbage()
  421. print"testing stack overflow"
  422. local C = 0
  423. -- get line where stack overflow will happen
  424. local l = debug.getinfo(1, "l").currentline + 1
  425. local function auxy () C=C+1; auxy() end -- produce a stack overflow
  426. function YY ()
  427. collectgarbage("stop") -- avoid running finalizers without stack space
  428. auxy()
  429. collectgarbage("restart")
  430. end
  431. local function checkstackmessage (m)
  432. print("(expected stack overflow after " .. C .. " calls)")
  433. C = 0 -- prepare next count
  434. return (string.find(m, "stack overflow"))
  435. end
  436. -- repeated stack overflows (to check stack recovery)
  437. assert(checkstackmessage(doit('YY()')))
  438. assert(checkstackmessage(doit('YY()')))
  439. assert(checkstackmessage(doit('YY()')))
  440. _G.YY = nil
  441. -- error lines in stack overflow
  442. local l1
  443. local function g(x)
  444. l1 = debug.getinfo(x, "l").currentline + 2
  445. collectgarbage("stop") -- avoid running finalizers without stack space
  446. auxy()
  447. collectgarbage("restart")
  448. end
  449. local _, stackmsg = xpcall(g, debug.traceback, 1)
  450. print('+')
  451. local stack = {}
  452. for line in string.gmatch(stackmsg, "[^\n]*") do
  453. local curr = string.match(line, ":(%d+):")
  454. if curr then table.insert(stack, tonumber(curr)) end
  455. end
  456. local i=1
  457. while stack[i] ~= l1 do
  458. assert(stack[i] == l)
  459. i = i+1
  460. end
  461. assert(i > 15)
  462. -- error in error handling
  463. local res, msg = xpcall(error, error)
  464. assert(not res and msg == 'error in error handling')
  465. print('+')
  466. local function f (x)
  467. if x==0 then error('a\n')
  468. else
  469. local aux = function () return f(x-1) end
  470. local a,b = xpcall(aux, aux)
  471. return a,b
  472. end
  473. end
  474. f(3)
  475. local function loop (x,y,z) return 1 + loop(x, y, z) end
  476. local res, msg = xpcall(loop, function (m)
  477. assert(string.find(m, "stack overflow"))
  478. checkerr("error handling", loop)
  479. assert(math.sin(0) == 0)
  480. return 15
  481. end)
  482. assert(msg == 15)
  483. local f = function ()
  484. for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
  485. end
  486. checkerr("too many results", f)
  487. end
  488. do -- errors in error handle that not necessarily go forever
  489. local function err (n) -- function to be used as message handler
  490. -- generate an error unless n is zero, so that there is a limited
  491. -- loop of errors
  492. if type(n) ~= "number" then -- some other error?
  493. return n -- report it
  494. elseif n == 0 then
  495. return "END" -- that will be the final message
  496. else error(n - 1) -- does the loop
  497. end
  498. end
  499. local res, msg = xpcall(error, err, 170)
  500. assert(not res and msg == "END")
  501. -- too many levels
  502. local res, msg = xpcall(error, err, 300)
  503. assert(not res and msg == "C stack overflow")
  504. end
  505. do
  506. -- non string messages
  507. local t = {}
  508. local res, msg = pcall(function () error(t) end)
  509. assert(not res and msg == t)
  510. res, msg = pcall(function () error(nil) end)
  511. assert(not res and msg == "<no error object>")
  512. local function f() error{msg='x'} end
  513. res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
  514. assert(msg.msg == 'xy')
  515. -- 'assert' with extra arguments
  516. res, msg = pcall(assert, false, "X", t)
  517. assert(not res and msg == "X")
  518. -- 'assert' with no message
  519. res, msg = pcall(function () assert(false) end)
  520. local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
  521. assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
  522. -- 'assert' with non-string messages
  523. res, msg = pcall(assert, false, t)
  524. assert(not res and msg == t)
  525. res, msg = pcall(assert, nil, nil)
  526. assert(not res and type(msg) == "string")
  527. -- 'assert' without arguments
  528. res, msg = pcall(assert)
  529. assert(not res and string.find(msg, "value expected"))
  530. end
  531. -- xpcall with arguments
  532. local a, b, c = xpcall(string.find, error, "alo", "al")
  533. assert(a and b == 1 and c == 2)
  534. a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
  535. assert(not a and type(b) == "table" and c == nil)
  536. print("testing tokens in error messages")
  537. checksyntax("syntax error", "", "error", 1)
  538. checksyntax("1.000", "", "1.000", 1)
  539. checksyntax("[[a]]", "", "[[a]]", 1)
  540. checksyntax("'aa'", "", "'aa'", 1)
  541. checksyntax("while << do end", "", "<<", 1)
  542. checksyntax("for >> do end", "", ">>", 1)
  543. -- test invalid non-printable char in a chunk
  544. checksyntax("a\1a = 1", "", "<\\1>", 1)
  545. -- test 255 as first char in a chunk
  546. checksyntax("\255a = 1", "", "<\\255>", 1)
  547. doit('I = load("a=9+"); aaa=3')
  548. assert(_G.aaa==3 and not _G.I)
  549. _G.I,_G.aaa = nil
  550. print('+')
  551. local lim = 1000
  552. if _soft then lim = 100 end
  553. for i=1,lim do
  554. doit('a = ')
  555. doit('a = 4+nil')
  556. end
  557. -- testing syntax limits
  558. local function testrep (init, rep, close, repc, finalresult)
  559. local function gencode (n)
  560. return init .. string.rep(rep, n) .. close .. string.rep(repc, n)
  561. end
  562. local res, msg = load(gencode(100)) -- 100 levels is OK
  563. assert(res)
  564. if (finalresult) then
  565. assert(res() == finalresult)
  566. end
  567. local res, msg = load(gencode(500)) -- 500 levels not ok
  568. assert(not res and (string.find(msg, "too many") or
  569. string.find(msg, "overflow")))
  570. end
  571. testrep("local a", ",a", ";", "") -- local variables
  572. testrep("local a", ",a", "= 1", ",1") -- local variables initialized
  573. testrep("local a", ",a", "= f()", "") -- local variables initialized
  574. testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
  575. testrep("local a; a=", "{", "0", "}") -- constructors
  576. testrep("return ", "(", "2", ")", 2) -- parentheses
  577. -- nested calls (a(a(a(a(...)))))
  578. testrep("local function a (x) return x end; return ", "a(", "2.2", ")", 2.2)
  579. testrep("", "do ", "", " end")
  580. testrep("", "while a do ", "", " end")
  581. testrep("local a; ", "if a then else ", "", " end")
  582. testrep("", "function foo () ", "", " end")
  583. testrep("local a = ''; return ", "a..", "'a'", "", "a")
  584. testrep("local a = 1; return ", "a^", "a", "", 1)
  585. checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
  586. -- testing other limits
  587. -- upvalues
  588. local lim = 127
  589. local s = "local function fooA ()\n local "
  590. for j = 1,lim do
  591. s = s.."a"..j..", "
  592. end
  593. s = s.."b,c\n"
  594. s = s.."local function fooB ()\n local "
  595. for j = 1,lim do
  596. s = s.."b"..j..", "
  597. end
  598. s = s.."b\n"
  599. s = s.."function fooC () return b+c"
  600. local c = 1+2
  601. for j = 1,lim do
  602. s = s.."+a"..j.."+b"..j
  603. c = c + 2
  604. end
  605. s = s.."\nend end end"
  606. local a,b = load(s)
  607. assert(c > 255 and string.find(b, "too many upvalues") and
  608. string.find(b, "line 5"))
  609. -- local variables
  610. s = "\nfunction foo ()\n local "
  611. for j = 1,200 do
  612. s = s.."a"..j..", "
  613. end
  614. s = s.."b\n"
  615. local a,b = load(s)
  616. assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
  617. mt.__index = oldmm
  618. print('OK')