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