diff options
Diffstat (limited to 'testes/errors.lua')
-rw-r--r-- | testes/errors.lua | 537 |
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 | |||
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 f == nil 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) | ||
28 | local m = doit(prog) | ||
29 | assert(string.find(m, msg, 1, true)) | ||
30 | end | ||
31 | |||
32 | local 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)) | ||
41 | end | ||
42 | |||
43 | |||
44 | -- test error message with no extra info | ||
45 | assert(doit("error('hi', 0)") == 'hi') | ||
46 | |||
47 | -- test error message with no info | ||
48 | assert(doit("error()") == nil) | ||
49 | |||
50 | |||
51 | -- test common errors/errors that crashed in the past | ||
52 | assert(doit("table.unpack({}, 1, n=2^30)")) | ||
53 | assert(doit("a=math.sin()")) | ||
54 | assert(not doit("tostring(1)") and doit("tostring()")) | ||
55 | assert(doit"tonumber()") | ||
56 | assert(doit"repeat until 1; a") | ||
57 | assert(doit"return;;") | ||
58 | assert(doit"assert(false)") | ||
59 | assert(doit"assert(nil)") | ||
60 | assert(doit("function a (... , ...) end")) | ||
61 | assert(doit("function a (, ...) end")) | ||
62 | assert(doit("local t={}; t = t[#t] + 1")) | ||
63 | |||
64 | checksyntax([[ | ||
65 | local a = {4 | ||
66 | |||
67 | ]], "'}' expected (to close '{' at line 1)", "<eof>", 3) | ||
68 | |||
69 | |||
70 | -- tests for better error messages | ||
71 | |||
72 | checkmessage("a = {} + 1", "arithmetic") | ||
73 | checkmessage("a = {} | 1", "bitwise operation") | ||
74 | checkmessage("a = {} < 1", "attempt to compare") | ||
75 | checkmessage("a = {} <= 1", "attempt to compare") | ||
76 | |||
77 | checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'") | ||
78 | checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'") | ||
79 | checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'") | ||
80 | assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'")) | ||
81 | checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number") | ||
82 | checkmessage("a=(1)..{}", "a table value") | ||
83 | |||
84 | checkmessage("a = #print", "length of a function value") | ||
85 | checkmessage("a = #3", "length of a number value") | ||
86 | |||
87 | aaa = nil | ||
88 | checkmessage("aaa.bbb:ddd(9)", "global 'aaa'") | ||
89 | checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'") | ||
90 | checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'") | ||
91 | checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'") | ||
92 | assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)") | ||
93 | |||
94 | -- upvalues being indexed do not go to the stack | ||
95 | checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'") | ||
96 | checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'") | ||
97 | |||
98 | checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'") | ||
99 | |||
100 | checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'") | ||
101 | checkmessage("aaa={}; x=3/aaa", "global 'aaa'") | ||
102 | checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'") | ||
103 | checkmessage("aaa={}; x=-aaa", "global 'aaa'") | ||
104 | |||
105 | -- short circuit | ||
106 | checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)", | ||
107 | "local 'bbbb'") | ||
108 | checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'") | ||
109 | checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'") | ||
110 | checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value") | ||
111 | assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'")) | ||
112 | assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'")) | ||
113 | |||
114 | checkmessage("print(print < 10)", "function with number") | ||
115 | checkmessage("print(print < print)", "two function values") | ||
116 | checkmessage("print('10' < 10)", "string with number") | ||
117 | checkmessage("print(10 < '23')", "number with string") | ||
118 | |||
119 | -- float->integer conversions | ||
120 | checkmessage("local a = 2.0^100; x = a << 2", "local a") | ||
121 | checkmessage("local a = 1 >> 2.0^100", "has no integer representation") | ||
122 | checkmessage("local a = '10' << 2.0^100", "has no integer representation") | ||
123 | checkmessage("local a = 2.0^100 & 1", "has no integer representation") | ||
124 | checkmessage("local a = 2.0^100 & '1'", "has no integer representation") | ||
125 | checkmessage("local a = 2.0 | 1e40", "has no integer representation") | ||
126 | checkmessage("local a = 2e100 ~ 1", "has no integer representation") | ||
127 | checkmessage("string.sub('a', 2.0^100)", "has no integer representation") | ||
128 | checkmessage("string.rep('a', 3.3)", "has no integer representation") | ||
129 | checkmessage("return 6e40 & 7", "has no integer representation") | ||
130 | checkmessage("return 34 << 7e30", "has no integer representation") | ||
131 | checkmessage("return ~-3e40", "has no integer representation") | ||
132 | checkmessage("return ~-3.009", "has no integer representation") | ||
133 | checkmessage("return 3.009 & 1", "has no integer representation") | ||
134 | checkmessage("return 34 >> {}", "table value") | ||
135 | checkmessage("a = 24 // 0", "divide by zero") | ||
136 | checkmessage("a = 1 % 0", "'n%0'") | ||
137 | |||
138 | |||
139 | -- passing light userdata instead of full userdata | ||
140 | _G.D = debug | ||
141 | checkmessage([[ | ||
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 | |||
148 | do -- 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 | ||
159 | end | ||
160 | |||
161 | -- global functions | ||
162 | checkmessage("(io.write or print){}", "io.write") | ||
163 | checkmessage("(collectgarbage or print){}", "collectgarbage") | ||
164 | |||
165 | -- errors in functions without debug info | ||
166 | do | ||
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) | ||
178 | end | ||
179 | |||
180 | |||
181 | -- tests for field accesses after RK limit | ||
182 | local t = {} | ||
183 | for i = 1, 1000 do | ||
184 | t[i] = "a = x" .. i | ||
185 | end | ||
186 | local s = table.concat(t, "; ") | ||
187 | t = nil | ||
188 | checkmessage(s.."; a = bbb + 1", "global 'bbb'") | ||
189 | checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'") | ||
190 | checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'") | ||
191 | checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'") | ||
192 | |||
193 | checkmessage([[aaa=9 | ||
194 | repeat until 3==3 | ||
195 | local x=math.sin(math.cos(3)) | ||
196 | if math.sin(1) == x then return math.sin(1) end -- tail call | ||
197 | local 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 | |||
204 | checkmessage([[ | ||
205 | local x,y = {},1 | ||
206 | if math.sin(1) == 0 then return 3 end -- return | ||
207 | x.a()]], "field 'a'") | ||
208 | |||
209 | checkmessage([[ | ||
210 | prefix = nil | ||
211 | insert = nil | ||
212 | while 1 do | ||
213 | local a | ||
214 | if nil then break end | ||
215 | insert(prefix, a) | ||
216 | end]], "global 'insert'") | ||
217 | |||
218 | checkmessage([[ -- tail call | ||
219 | return math.sin("a") | ||
220 | ]], "'sin'") | ||
221 | |||
222 | checkmessage([[collectgarbage("nooption")]], "invalid option") | ||
223 | |||
224 | checkmessage([[x = print .. "a"]], "concatenate") | ||
225 | checkmessage([[x = "a" .. false]], "concatenate") | ||
226 | checkmessage([[x = {} .. 2]], "concatenate") | ||
227 | |||
228 | checkmessage("getmetatable(io.stdin).__gc()", "no value") | ||
229 | |||
230 | checkmessage([[ | ||
231 | local Var | ||
232 | local function main() | ||
233 | NoSuchName (function() Var=0 end) | ||
234 | end | ||
235 | main() | ||
236 | ]], "global 'NoSuchName'") | ||
237 | print'+' | ||
238 | |||
239 | a = {}; setmetatable(a, {__index = string}) | ||
240 | checkmessage("a:sub()", "bad self") | ||
241 | checkmessage("string.sub('a', {})", "#2") | ||
242 | checkmessage("('a'):sub{}", "#1") | ||
243 | |||
244 | checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'") | ||
245 | checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'") | ||
246 | |||
247 | -- tests for errors in coroutines | ||
248 | |||
249 | local function f (n) | ||
250 | local c = coroutine.create(f) | ||
251 | local a,b = coroutine.resume(c) | ||
252 | return b | ||
253 | end | ||
254 | assert(string.find(f(), "C stack overflow")) | ||
255 | |||
256 | checkmessage("coroutine.yield()", "outside a coroutine") | ||
257 | |||
258 | f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end) | ||
259 | checkerr("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'. | ||
264 | idsize = 60 - 1 | ||
265 | local 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) | ||
270 | end | ||
271 | |||
272 | for 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 | ||
276 | end | ||
277 | |||
278 | |||
279 | -- testing line error | ||
280 | |||
281 | local 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) | ||
285 | end | ||
286 | |||
287 | lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2) | ||
288 | lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3) | ||
289 | lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4) | ||
290 | lineerror("function a.x.y ()\na=a+1\nend", 1) | ||
291 | |||
292 | lineerror("a = \na\n+\n{}", 3) | ||
293 | lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6) | ||
294 | lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3) | ||
295 | |||
296 | lineerror("a\n=\n-\n\nprint\n;", 3) | ||
297 | |||
298 | lineerror([[ | ||
299 | a | ||
300 | ( | ||
301 | 23) | ||
302 | ]], 1) | ||
303 | |||
304 | lineerror([[ | ||
305 | local a = {x = 13} | ||
306 | a | ||
307 | . | ||
308 | x | ||
309 | ( | ||
310 | 23 | ||
311 | ) | ||
312 | ]], 2) | ||
313 | |||
314 | lineerror([[ | ||
315 | local a = {x = 13} | ||
316 | a | ||
317 | . | ||
318 | x | ||
319 | ( | ||
320 | 23 + a | ||
321 | ) | ||
322 | ]], 6) | ||
323 | |||
324 | local p = [[ | ||
325 | function g() f() end | ||
326 | function f(x) error('a', X) end | ||
327 | g() | ||
328 | ]] | ||
329 | X=3;lineerror((p), 3) | ||
330 | X=0;lineerror((p), nil) | ||
331 | X=1;lineerror((p), 2) | ||
332 | X=2;lineerror((p), 1) | ||
333 | |||
334 | |||
335 | if 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 | |||
405 | end | ||
406 | |||
407 | |||
408 | do | ||
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")) | ||
440 | end | ||
441 | |||
442 | -- xpcall with arguments | ||
443 | a, b, c = xpcall(string.find, error, "alo", "al") | ||
444 | assert(a and b == 1 and c == 2) | ||
445 | a, b, c = xpcall(string.find, function (x) return {} end, true, "al") | ||
446 | assert(not a and type(b) == "table" and c == nil) | ||
447 | |||
448 | |||
449 | print("testing tokens in error messages") | ||
450 | checksyntax("syntax error", "", "error", 1) | ||
451 | checksyntax("1.000", "", "1.000", 1) | ||
452 | checksyntax("[[a]]", "", "[[a]]", 1) | ||
453 | checksyntax("'aa'", "", "'aa'", 1) | ||
454 | checksyntax("while << do end", "", "<<", 1) | ||
455 | checksyntax("for >> do end", "", ">>", 1) | ||
456 | |||
457 | -- test invalid non-printable char in a chunk | ||
458 | checksyntax("a\1a = 1", "", "<\\1>", 1) | ||
459 | |||
460 | -- test 255 as first char in a chunk | ||
461 | checksyntax("\255a = 1", "", "<\\255>", 1) | ||
462 | |||
463 | doit('I = load("a=9+"); a=3') | ||
464 | assert(a==3 and I == nil) | ||
465 | print('+') | ||
466 | |||
467 | lim = 1000 | ||
468 | if _soft then lim = 100 end | ||
469 | for i=1,lim do | ||
470 | doit('a = ') | ||
471 | doit('a = 4+nil') | ||
472 | end | ||
473 | |||
474 | |||
475 | -- testing syntax limits | ||
476 | |||
477 | local maxClevel = 200 -- LUAI_MAXCCALLS (in llimits.h) | ||
478 | |||
479 | local 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") | ||
485 | end | ||
486 | |||
487 | testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment | ||
488 | testrep("local a; a=", "{", "0", "}") | ||
489 | testrep("local a; a=", "(", "2", ")") | ||
490 | testrep("local a; ", "a(", "2", ")") | ||
491 | testrep("", "do ", "", " end") | ||
492 | testrep("", "while a do ", "", " end") | ||
493 | testrep("local a; ", "if a then else ", "", " end") | ||
494 | testrep("", "function foo () ", "", " end") | ||
495 | testrep("local a; a=", "a..", "a", "") | ||
496 | testrep("local a; a=", "a^", "a", "") | ||
497 | |||
498 | checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers") | ||
499 | |||
500 | |||
501 | -- testing other limits | ||
502 | |||
503 | -- upvalues | ||
504 | local lim = 127 | ||
505 | local s = "local function fooA ()\n local " | ||
506 | for j = 1,lim do | ||
507 | s = s.."a"..j..", " | ||
508 | end | ||
509 | s = s.."b,c\n" | ||
510 | s = s.."local function fooB ()\n local " | ||
511 | for j = 1,lim do | ||
512 | s = s.."b"..j..", " | ||
513 | end | ||
514 | s = s.."b\n" | ||
515 | s = s.."function fooC () return b+c" | ||
516 | local c = 1+2 | ||
517 | for j = 1,lim do | ||
518 | s = s.."+a"..j.."+b"..j | ||
519 | c = c + 2 | ||
520 | end | ||
521 | s = s.."\nend end end" | ||
522 | local a,b = load(s) | ||
523 | assert(c > 255 and string.find(b, "too many upvalues") and | ||
524 | string.find(b, "line 5")) | ||
525 | |||
526 | -- local variables | ||
527 | s = "\nfunction foo ()\n local " | ||
528 | for j = 1,300 do | ||
529 | s = s.."a"..j..", " | ||
530 | end | ||
531 | s = s.."b\n" | ||
532 | local a,b = load(s) | ||
533 | assert(string.find(b, "line 2") and string.find(b, "too many local variables")) | ||
534 | |||
535 | mt.__index = oldmm | ||
536 | |||
537 | print('OK') | ||