diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 14:46:37 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-12-17 14:46:37 -0200 |
commit | 063d4e4543088e7a21965bda8ee5a0f952a9029e (patch) | |
tree | 6c3f2f8e98c26f071a94a32f9f2754396a66a9de /testes/errors.lua | |
parent | e354c6355e7f48e087678ec49e340ca0696725b1 (diff) | |
download | lua-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.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') | ||