summaryrefslogtreecommitdiff
path: root/testes/api.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/api.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/api.lua')
-rw-r--r--testes/api.lua1172
1 files changed, 1172 insertions, 0 deletions
diff --git a/testes/api.lua b/testes/api.lua
new file mode 100644
index 00000000..c27ee97f
--- /dev/null
+++ b/testes/api.lua
@@ -0,0 +1,1172 @@
1-- $Id: api.lua,v 1.147 2016/11/07 13:06:25 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4if T==nil then
5 (Message or print)('\n >>> testC not active: skipping API tests <<<\n')
6 return
7end
8
9local debug = require "debug"
10
11local pack = table.pack
12
13
14function tcheck (t1, t2)
15 assert(t1.n == (t2.n or #t2) + 1)
16 for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end
17end
18
19
20local function checkerr (msg, f, ...)
21 local stat, err = pcall(f, ...)
22 assert(not stat and string.find(err, msg))
23end
24
25
26print('testing C API')
27
28a = T.testC("pushvalue R; return 1")
29assert(a == debug.getregistry())
30
31
32-- absindex
33assert(T.testC("settop 10; absindex -1; return 1") == 10)
34assert(T.testC("settop 5; absindex -5; return 1") == 1)
35assert(T.testC("settop 10; absindex 1; return 1") == 1)
36assert(T.testC("settop 10; absindex R; return 1") < -10)
37
38-- testing alignment
39a = T.d2s(12458954321123.0)
40assert(a == string.pack("d", 12458954321123.0))
41assert(T.s2d(a) == 12458954321123.0)
42
43a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
44assert(a == 2 and b == 3 and not c)
45
46f = T.makeCfunc("pushnum 1; pushnum 2; pushnum 3; return 2")
47a,b,c = f()
48assert(a == 2 and b == 3 and not c)
49
50-- test that all trues are equal
51a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
52assert(a == b and a == true and c == false)
53a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\
54 tobool -3; tobool -3; tobool -3; return 3"
55assert(a==false and b==true and c==false)
56
57
58a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
59assert(a == 40 and b == 5 and not c)
60
61t = pack(T.testC("settop 5; return *", 2, 3))
62tcheck(t, {n=4,2,3})
63
64t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
65assert(t.n == 10 and t[1] == nil and t[10] == nil)
66
67t = pack(T.testC("remove -2; return *", 2, 3, 4))
68tcheck(t, {n=2,2,4})
69
70t = pack(T.testC("insert -1; return *", 2, 3))
71tcheck(t, {n=2,2,3})
72
73t = pack(T.testC("insert 3; return *", 2, 3, 4, 5))
74tcheck(t, {n=4,2,5,3,4})
75
76t = pack(T.testC("replace 2; return *", 2, 3, 4, 5))
77tcheck(t, {n=3,5,3,4})
78
79t = pack(T.testC("replace -2; return *", 2, 3, 4, 5))
80tcheck(t, {n=3,2,3,5})
81
82t = pack(T.testC("remove 3; return *", 2, 3, 4, 5))
83tcheck(t, {n=3,2,4,5})
84
85t = pack(T.testC("copy 3 4; return *", 2, 3, 4, 5))
86tcheck(t, {n=4,2,3,3,5})
87
88t = pack(T.testC("copy -3 -1; return *", 2, 3, 4, 5))
89tcheck(t, {n=4,2,3,4,3})
90
91do -- testing 'rotate'
92 local t = {10, 20, 30, 40, 50, 60}
93 for i = -6, 6 do
94 local s = string.format("rotate 2 %d; return 7", i)
95 local t1 = pack(T.testC(s, 10, 20, 30, 40, 50, 60))
96 tcheck(t1, t)
97 table.insert(t, 1, table.remove(t))
98 end
99
100 t = pack(T.testC("rotate -2 1; return *", 10, 20, 30, 40))
101 tcheck(t, {10, 20, 40, 30})
102 t = pack(T.testC("rotate -2 -1; return *", 10, 20, 30, 40))
103 tcheck(t, {10, 20, 40, 30})
104
105 -- some corner cases
106 t = pack(T.testC("rotate -1 0; return *", 10, 20, 30, 40))
107 tcheck(t, {10, 20, 30, 40})
108 t = pack(T.testC("rotate -1 1; return *", 10, 20, 30, 40))
109 tcheck(t, {10, 20, 30, 40})
110 t = pack(T.testC("rotate 5 -1; return *", 10, 20, 30, 40))
111 tcheck(t, {10, 20, 30, 40})
112end
113
114-- testing non-function message handlers
115do
116 local f = T.makeCfunc[[
117 getglobal error
118 pushstring bola
119 pcall 1 1 1 # call 'error' with given handler
120 pushstatus
121 return 2 # return error message and status
122 ]]
123
124 local msg, st = f({}) -- invalid handler
125 assert(st == "ERRERR" and string.find(msg, "error handling"))
126 local msg, st = f(nil) -- invalid handler
127 assert(st == "ERRERR" and string.find(msg, "error handling"))
128
129 local a = setmetatable({}, {__call = function (_, x) return x:upper() end})
130 local msg, st = f(a) -- callable handler
131 assert(st == "ERRRUN" and msg == "BOLA")
132end
133
134t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
135 insert 2; pushvalue 1; remove 1; insert 1; \
136 insert -2; pushvalue -2; remove -3; return *",
137 2, 3, 4, 5, 10, 40, 90))
138tcheck(t, {n=7,2,3,4,5,10,40,90})
139
140t = pack(T.testC("concat 5; return *", "alo", 2, 3, "joao", 12))
141tcheck(t, {n=1,"alo23joao12"})
142
143-- testing MULTRET
144t = pack(T.testC("call 2,-1; return *",
145 function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
146tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
147
148do -- test returning more results than fit in the caller stack
149 local a = {}
150 for i=1,1000 do a[i] = true end; a[999] = 10
151 local b = T.testC([[pcall 1 -1 0; pop 1; tostring -1; return 1]],
152 table.unpack, a)
153 assert(b == "10")
154end
155
156
157-- testing globals
158_G.a = 14; _G.b = "a31"
159local a = {T.testC[[
160 getglobal a;
161 getglobal b;
162 getglobal b;
163 setglobal a;
164 return *
165]]}
166assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.a == "a31")
167
168
169-- testing arith
170assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5)
171assert(T.testC("pushnum 10; pushnum 20; arith -; return 1") == -10)
172assert(T.testC("pushnum 10; pushnum -20; arith *; return 1") == -200)
173assert(T.testC("pushnum 10; pushnum 3; arith ^; return 1") == 1000)
174assert(T.testC("pushnum 10; pushstring 20; arith /; return 1") == 0.5)
175assert(T.testC("pushstring 10; pushnum 20; arith -; return 1") == -10)
176assert(T.testC("pushstring 10; pushstring -20; arith *; return 1") == -200)
177assert(T.testC("pushstring 10; pushstring 3; arith ^; return 1") == 1000)
178assert(T.testC("arith /; return 1", 2, 0) == 10.0/0)
179a = T.testC("pushnum 10; pushint 3; arith \\; return 1")
180assert(a == 3.0 and math.type(a) == "float")
181a = T.testC("pushint 10; pushint 3; arith \\; return 1")
182assert(a == 3 and math.type(a) == "integer")
183a = assert(T.testC("pushint 10; pushint 3; arith +; return 1"))
184assert(a == 13 and math.type(a) == "integer")
185a = assert(T.testC("pushnum 10; pushint 3; arith +; return 1"))
186assert(a == 13 and math.type(a) == "float")
187a,b,c = T.testC([[pushnum 1;
188 pushstring 10; arith _;
189 pushstring 5; return 3]])
190assert(a == 1 and b == -10 and c == "5")
191mt = {__add = function (a,b) return setmetatable({a[1] + b[1]}, mt) end,
192 __mod = function (a,b) return setmetatable({a[1] % b[1]}, mt) end,
193 __unm = function (a) return setmetatable({a[1]* 2}, mt) end}
194a,b,c = setmetatable({4}, mt),
195 setmetatable({8}, mt),
196 setmetatable({-3}, mt)
197x,y,z = T.testC("arith +; return 2", 10, a, b)
198assert(x == 10 and y[1] == 12 and z == nil)
199assert(T.testC("arith %; return 1", a, c)[1] == 4%-3)
200assert(T.testC("arith _; arith +; arith %; return 1", b, a, c)[1] ==
201 8 % (4 + (-3)*2))
202
203-- errors in arithmetic
204checkerr("divide by zero", T.testC, "arith \\", 10, 0)
205checkerr("%%0", T.testC, "arith %", 10, 0)
206
207
208-- testing lessthan and lessequal
209assert(T.testC("compare LT 2 5, return 1", 3, 2, 2, 4, 2, 2))
210assert(T.testC("compare LE 2 5, return 1", 3, 2, 2, 4, 2, 2))
211assert(not T.testC("compare LT 3 4, return 1", 3, 2, 2, 4, 2, 2))
212assert(T.testC("compare LE 3 4, return 1", 3, 2, 2, 4, 2, 2))
213assert(T.testC("compare LT 5 2, return 1", 4, 2, 2, 3, 2, 2))
214assert(not T.testC("compare LT 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
215assert(not T.testC("compare LT -3 2, return 1", "3", "2", "2", "4", "2", "2"))
216
217-- non-valid indices produce false
218assert(not T.testC("compare LT 1 4, return 1"))
219assert(not T.testC("compare LE 9 1, return 1"))
220assert(not T.testC("compare EQ 9 9, return 1"))
221
222local b = {__lt = function (a,b) return a[1] < b[1] end}
223local a1,a3,a4 = setmetatable({1}, b),
224 setmetatable({3}, b),
225 setmetatable({4}, b)
226assert(T.testC("compare LT 2 5, return 1", a3, 2, 2, a4, 2, 2))
227assert(T.testC("compare LE 2 5, return 1", a3, 2, 2, a4, 2, 2))
228assert(T.testC("compare LT 5 -6, return 1", a4, 2, 2, a3, 2, 2))
229a,b = T.testC("compare LT 5 -6, return 2", a1, 2, 2, a3, 2, 20)
230assert(a == 20 and b == false)
231a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a3, 2, 20)
232assert(a == 20 and b == false)
233a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a1, 2, 20)
234assert(a == 20 and b == true)
235
236-- testing length
237local t = setmetatable({x = 20}, {__len = function (t) return t.x end})
238a,b,c = T.testC([[
239 len 2;
240 Llen 2;
241 objsize 2;
242 return 3
243]], t)
244assert(a == 20 and b == 20 and c == 0)
245
246t.x = "234"; t[1] = 20
247a,b,c = T.testC([[
248 len 2;
249 Llen 2;
250 objsize 2;
251 return 3
252]], t)
253assert(a == "234" and b == 234 and c == 1)
254
255t.x = print; t[1] = 20
256a,c = T.testC([[
257 len 2;
258 objsize 2;
259 return 2
260]], t)
261assert(a == print and c == 1)
262
263
264-- testing __concat
265
266a = setmetatable({x="u"}, {__concat = function (a,b) return a.x..'.'..b.x end})
267x,y = T.testC([[
268 pushnum 5
269 pushvalue 2;
270 pushvalue 2;
271 concat 2;
272 pushvalue -2;
273 return 2;
274]], a, a)
275assert(x == a..a and y == 5)
276
277-- concat with 0 elements
278assert(T.testC("concat 0; return 1") == "")
279
280-- concat with 1 element
281assert(T.testC("concat 1; return 1", "xuxu") == "xuxu")
282
283
284
285-- testing lua_is
286
287function B(x) return x and 1 or 0 end
288
289function count (x, n)
290 n = n or 2
291 local prog = [[
292 isnumber %d;
293 isstring %d;
294 isfunction %d;
295 iscfunction %d;
296 istable %d;
297 isuserdata %d;
298 isnil %d;
299 isnull %d;
300 return 8
301 ]]
302 prog = string.format(prog, n, n, n, n, n, n, n, n)
303 local a,b,c,d,e,f,g,h = T.testC(prog, x)
304 return B(a)+B(b)+B(c)+B(d)+B(e)+B(f)+B(g)+(100*B(h))
305end
306
307assert(count(3) == 2)
308assert(count('alo') == 1)
309assert(count('32') == 2)
310assert(count({}) == 1)
311assert(count(print) == 2)
312assert(count(function () end) == 1)
313assert(count(nil) == 1)
314assert(count(io.stdin) == 1)
315assert(count(nil, 15) == 100)
316
317
318-- testing lua_to...
319
320function to (s, x, n)
321 n = n or 2
322 return T.testC(string.format("%s %d; return 1", s, n), x)
323end
324
325local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues)
326assert(debug.getupvalue(hfunc, 1))
327assert(to("tostring", {}) == nil)
328assert(to("tostring", "alo") == "alo")
329assert(to("tostring", 12) == "12")
330assert(to("tostring", 12, 3) == nil)
331assert(to("objsize", {}) == 0)
332assert(to("objsize", {1,2,3}) == 3)
333assert(to("objsize", "alo\0\0a") == 6)
334assert(to("objsize", T.newuserdata(0)) == 0)
335assert(to("objsize", T.newuserdata(101)) == 101)
336assert(to("objsize", 124) == 0)
337assert(to("objsize", true) == 0)
338assert(to("tonumber", {}) == 0)
339assert(to("tonumber", "12") == 12)
340assert(to("tonumber", "s2") == 0)
341assert(to("tonumber", 1, 20) == 0)
342assert(to("topointer", 10) == 0)
343assert(to("topointer", true) == 0)
344assert(to("topointer", T.pushuserdata(20)) == 20)
345assert(to("topointer", io.read) ~= 0) -- light C function
346assert(to("topointer", hfunc) ~= 0) -- "heavy" C function
347assert(to("topointer", function () end) ~= 0) -- Lua function
348assert(to("topointer", io.stdin) ~= 0) -- full userdata
349assert(to("func2num", 20) == 0)
350assert(to("func2num", T.pushuserdata(10)) == 0)
351assert(to("func2num", io.read) ~= 0) -- light C function
352assert(to("func2num", hfunc) ~= 0) -- "heavy" C function (with upvalue)
353a = to("tocfunction", math.deg)
354assert(a(3) == math.deg(3) and a == math.deg)
355
356
357print("testing panic function")
358do
359 -- trivial error
360 assert(T.checkpanic("pushstring hi; error") == "hi")
361
362 -- using the stack inside panic
363 assert(T.checkpanic("pushstring hi; error;",
364 [[checkstack 5 XX
365 pushstring ' alo'
366 pushstring ' mundo'
367 concat 3]]) == "hi alo mundo")
368
369 -- "argerror" without frames
370 assert(T.checkpanic("loadstring 4") ==
371 "bad argument #4 (string expected, got no value)")
372
373
374 -- memory error
375 T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k)
376 assert(T.checkpanic("newuserdata 20000") == "not enough memory")
377 T.totalmem(0) -- restore high limit
378
379 -- stack error
380 if not _soft then
381 local msg = T.checkpanic[[
382 pushstring "function f() f() end"
383 loadstring -1; call 0 0
384 getglobal f; call 0 0
385 ]]
386 assert(string.find(msg, "stack overflow"))
387 end
388
389end
390
391-- testing deep C stack
392if not _soft then
393 print("testing stack overflow")
394 collectgarbage("stop")
395 checkerr("XXXX", T.testC, "checkstack 1000023 XXXX") -- too deep
396 -- too deep (with no message)
397 checkerr("^stack overflow$", T.testC, "checkstack 1000023 ''")
398 local s = string.rep("pushnil;checkstack 1 XX;", 1000000)
399 checkerr("overflow", T.testC, s)
400 collectgarbage("restart")
401 print'+'
402end
403
404local lim = _soft and 500 or 12000
405local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"}
406for i = 1,lim do
407 prog[#prog + 1] = "pushnum " .. i
408 prog[#prog + 1] = "pushnum " .. i * 10
409end
410
411prog[#prog + 1] = "rawgeti R 2" -- get global table in registry
412prog[#prog + 1] = "insert " .. -(2*lim + 2)
413
414for i = 1,lim do
415 prog[#prog + 1] = "settable " .. -(2*(lim - i + 1) + 1)
416end
417
418prog[#prog + 1] = "return 2"
419
420prog = table.concat(prog, ";")
421local g, t = T.testC(prog)
422assert(g == _G)
423for i = 1,lim do assert(t[i] == i*10); t[i] = nil end
424assert(next(t) == nil)
425prog, g, t = nil
426
427-- testing errors
428
429a = T.testC([[
430 loadstring 2; pcall 0 1 0;
431 pushvalue 3; insert -2; pcall 1 1 0;
432 pcall 0 0 0;
433 return 1
434]], "x=150", function (a) assert(a==nil); return 3 end)
435
436assert(type(a) == 'string' and x == 150)
437
438function check3(p, ...)
439 local arg = {...}
440 assert(#arg == 3)
441 assert(string.find(arg[3], p))
442end
443check3(":1:", T.testC("loadstring 2; return *", "x="))
444check3("%.", T.testC("loadfile 2; return *", "."))
445check3("xxxx", T.testC("loadfile 2; return *", "xxxx"))
446
447-- test errors in non protected threads
448function checkerrnopro (code, msg)
449 local th = coroutine.create(function () end) -- create new thread
450 local stt, err = pcall(T.testC, th, code) -- run code there
451 assert(not stt and string.find(err, msg))
452end
453
454if not _soft then
455 checkerrnopro("pushnum 3; call 0 0", "attempt to call")
456 print"testing stack overflow in unprotected thread"
457 function f () f() end
458 checkerrnopro("getglobal 'f'; call 0 0;", "stack overflow")
459end
460print"+"
461
462
463-- testing table access
464
465do -- getp/setp
466 local a = {}
467 T.testC("rawsetp 2 1", a, 20)
468 assert(a[T.pushuserdata(1)] == 20)
469 assert(T.testC("rawgetp 2 1; return 1", a) == 20)
470end
471
472a = {x=0, y=12}
473x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
474 a, 3, "y", 4, "x")
475assert(x == 0 and y == 12)
476T.testC("settable -5", a, 3, 4, "x", 15)
477assert(a.x == 15)
478a[a] = print
479x = T.testC("gettable 2; return 1", a) -- table and key are the same object!
480assert(x == print)
481T.testC("settable 2", a, "x") -- table and key are the same object!
482assert(a[a] == "x")
483
484b = setmetatable({p = a}, {})
485getmetatable(b).__index = function (t, i) return t.p[i] end
486k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
487assert(x == 15 and k == 35)
488k = T.testC("getfield 2 y, return 1", b)
489assert(k == 12)
490getmetatable(b).__index = function (t, i) return a[i] end
491getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
492y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
493assert(y == 12)
494k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
495assert(a.x == 16 and k == 4)
496a[b] = 'xuxu'
497y = T.testC("gettable 2, return 1", b)
498assert(y == 'xuxu')
499T.testC("settable 2", b, 19)
500assert(a[b] == 19)
501
502--
503do -- testing getfield/setfield with long keys
504 local t = {_012345678901234567890123456789012345678901234567890123456789 = 32}
505 local a = T.testC([[
506 getfield 2 _012345678901234567890123456789012345678901234567890123456789
507 return 1
508 ]], t)
509 assert(a == 32)
510 local a = T.testC([[
511 pushnum 33
512 setglobal _012345678901234567890123456789012345678901234567890123456789
513 ]])
514 assert(_012345678901234567890123456789012345678901234567890123456789 == 33)
515 _012345678901234567890123456789012345678901234567890123456789 = nil
516end
517
518-- testing next
519a = {}
520t = pack(T.testC("next; return *", a, nil))
521tcheck(t, {n=1,a})
522a = {a=3}
523t = pack(T.testC("next; return *", a, nil))
524tcheck(t, {n=3,a,'a',3})
525t = pack(T.testC("next; pop 1; next; return *", a, nil))
526tcheck(t, {n=1,a})
527
528
529
530-- testing upvalues
531
532do
533 local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
534 t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
535 assert(b == 10 and c == 20 and type(t) == 'table')
536 a, b = A([[tostring U3; tonumber U4; return 2]])
537 assert(a == nil and b == 0)
538 A([[pushnum 100; pushnum 200; replace U2; replace U1]])
539 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
540 assert(b == 100 and c == 200)
541 A([[replace U2; replace U1]], {x=1}, {x=2})
542 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
543 assert(b.x == 1 and c.x == 2)
544 T.checkmemory()
545end
546
547
548-- testing absent upvalues from C-function pointers
549assert(T.testC[[isnull U1; return 1]] == true)
550assert(T.testC[[isnull U100; return 1]] == true)
551assert(T.testC[[pushvalue U1; return 1]] == nil)
552
553local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
554assert(T.upvalue(f, 1) == 10 and
555 T.upvalue(f, 2) == 20 and
556 T.upvalue(f, 3) == nil)
557T.upvalue(f, 2, "xuxu")
558assert(T.upvalue(f, 2) == "xuxu")
559
560
561-- large closures
562do
563 local A = "checkstack 300 msg;" ..
564 string.rep("pushnum 10;", 255) ..
565 "pushcclosure 255; return 1"
566 A = T.testC(A)
567 for i=1,255 do
568 assert(A(("pushvalue U%d; return 1"):format(i)) == 10)
569 end
570 assert(A("isnull U256; return 1"))
571 assert(not A("isnil U256; return 1"))
572end
573
574
575
576-- testing get/setuservalue
577-- bug in 5.1.2
578checkerr("got number", debug.setuservalue, 3, {})
579checkerr("got nil", debug.setuservalue, nil, {})
580checkerr("got light userdata", debug.setuservalue, T.pushuserdata(1), {})
581
582local b = T.newuserdata(0)
583assert(debug.getuservalue(b) == nil)
584for _, v in pairs{true, false, 4.56, print, {}, b, "XYZ"} do
585 assert(debug.setuservalue(b, v) == b)
586 assert(debug.getuservalue(b) == v)
587end
588
589assert(debug.getuservalue(4) == nil)
590
591debug.setuservalue(b, function () return 10 end)
592collectgarbage() -- function should not be collected
593assert(debug.getuservalue(b)() == 10)
594
595debug.setuservalue(b, 134)
596collectgarbage() -- number should not be a problem for collector
597assert(debug.getuservalue(b) == 134)
598
599-- test barrier for uservalues
600T.gcstate("atomic")
601assert(T.gccolor(b) == "black")
602debug.setuservalue(b, {x = 100})
603T.gcstate("pause") -- complete collection
604assert(debug.getuservalue(b).x == 100) -- uvalue should be there
605
606-- long chain of userdata
607for i = 1, 1000 do
608 local bb = T.newuserdata(0)
609 debug.setuservalue(bb, b)
610 b = bb
611end
612collectgarbage() -- nothing should not be collected
613for i = 1, 1000 do
614 b = debug.getuservalue(b)
615end
616assert(debug.getuservalue(b).x == 100)
617b = nil
618
619
620-- testing locks (refs)
621
622-- reuse of references
623local i = T.ref{}
624T.unref(i)
625assert(T.ref{} == i)
626
627Arr = {}
628Lim = 100
629for i=1,Lim do -- lock many objects
630 Arr[i] = T.ref({})
631end
632
633assert(T.ref(nil) == -1 and T.getref(-1) == nil)
634T.unref(-1); T.unref(-1)
635
636for i=1,Lim do -- unlock all them
637 T.unref(Arr[i])
638end
639
640function printlocks ()
641 local f = T.makeCfunc("gettable R; return 1")
642 local n = f("n")
643 print("n", n)
644 for i=0,n do
645 print(i, f(i))
646 end
647end
648
649
650for i=1,Lim do -- lock many objects
651 Arr[i] = T.ref({})
652end
653
654for i=1,Lim,2 do -- unlock half of them
655 T.unref(Arr[i])
656end
657
658assert(type(T.getref(Arr[2])) == 'table')
659
660
661assert(T.getref(-1) == nil)
662
663
664a = T.ref({})
665
666collectgarbage()
667
668assert(type(T.getref(a)) == 'table')
669
670
671-- colect in cl the `val' of all collected userdata
672tt = {}
673cl = {n=0}
674A = nil; B = nil
675local F
676F = function (x)
677 local udval = T.udataval(x)
678 table.insert(cl, udval)
679 local d = T.newuserdata(100) -- cria lixo
680 d = nil
681 assert(debug.getmetatable(x).__gc == F)
682 assert(load("table.insert({}, {})"))() -- cria mais lixo
683 collectgarbage() -- forca coleta de lixo durante coleta!
684 assert(debug.getmetatable(x).__gc == F) -- coleta anterior nao melou isso?
685 local dummy = {} -- cria lixo durante coleta
686 if A ~= nil then
687 assert(type(A) == "userdata")
688 assert(T.udataval(A) == B)
689 debug.getmetatable(A) -- just acess it
690 end
691 A = x -- ressucita userdata
692 B = udval
693 return 1,2,3
694end
695tt.__gc = F
696
697-- test whether udate collection frees memory in the right time
698do
699 collectgarbage();
700 collectgarbage();
701 local x = collectgarbage("count");
702 local a = T.newuserdata(5001)
703 assert(T.testC("objsize 2; return 1", a) == 5001)
704 assert(collectgarbage("count") >= x+4)
705 a = nil
706 collectgarbage();
707 assert(collectgarbage("count") <= x+1)
708 -- udata without finalizer
709 x = collectgarbage("count")
710 collectgarbage("stop")
711 for i=1,1000 do T.newuserdata(0) end
712 assert(collectgarbage("count") > x+10)
713 collectgarbage()
714 assert(collectgarbage("count") <= x+1)
715 -- udata with finalizer
716 collectgarbage()
717 x = collectgarbage("count")
718 collectgarbage("stop")
719 a = {__gc = function () end}
720 for i=1,1000 do debug.setmetatable(T.newuserdata(0), a) end
721 assert(collectgarbage("count") >= x+10)
722 collectgarbage() -- this collection only calls TM, without freeing memory
723 assert(collectgarbage("count") >= x+10)
724 collectgarbage() -- now frees memory
725 assert(collectgarbage("count") <= x+1)
726 collectgarbage("restart")
727end
728
729
730collectgarbage("stop")
731
732-- create 3 userdatas with tag `tt'
733a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
734b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
735c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
736
737-- create userdata without meta table
738x = T.newuserdata(4)
739y = T.newuserdata(0)
740
741checkerr("FILE%* expected, got userdata", io.input, a)
742checkerr("FILE%* expected, got userdata", io.input, x)
743
744assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
745
746d=T.ref(a);
747e=T.ref(b);
748f=T.ref(c);
749t = {T.getref(d), T.getref(e), T.getref(f)}
750assert(t[1] == a and t[2] == b and t[3] == c)
751
752t=nil; a=nil; c=nil;
753T.unref(e); T.unref(f)
754
755collectgarbage()
756
757-- check that unref objects have been collected
758assert(#cl == 1 and cl[1] == nc)
759
760x = T.getref(d)
761assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
762x =nil
763tt.b = b -- create cycle
764tt=nil -- frees tt for GC
765A = nil
766b = nil
767T.unref(d);
768n5 = T.newuserdata(0)
769debug.setmetatable(n5, {__gc=F})
770n5 = T.udataval(n5)
771collectgarbage()
772assert(#cl == 4)
773-- check order of collection
774assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
775
776collectgarbage"restart"
777
778
779a, na = {}, {}
780for i=30,1,-1 do
781 a[i] = T.newuserdata(0)
782 debug.setmetatable(a[i], {__gc=F})
783 na[i] = T.udataval(a[i])
784end
785cl = {}
786a = nil; collectgarbage()
787assert(#cl == 30)
788for i=1,30 do assert(cl[i] == na[i]) end
789na = nil
790
791
792for i=2,Lim,2 do -- unlock the other half
793 T.unref(Arr[i])
794end
795
796x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
797assert(T.testC("objsize 2; return 1", x) == 41)
798cl = {}
799a = {[x] = 1}
800x = T.udataval(x)
801collectgarbage()
802-- old `x' cannot be collected (`a' still uses it)
803assert(#cl == 0)
804for n in pairs(a) do a[n] = nil end
805collectgarbage()
806assert(#cl == 1 and cl[1] == x) -- old `x' must be collected
807
808-- testing lua_equal
809assert(T.testC("compare EQ 2 4; return 1", print, 1, print, 20))
810assert(T.testC("compare EQ 3 2; return 1", 'alo', "alo"))
811assert(T.testC("compare EQ 2 3; return 1", nil, nil))
812assert(not T.testC("compare EQ 2 3; return 1", {}, {}))
813assert(not T.testC("compare EQ 2 3; return 1"))
814assert(not T.testC("compare EQ 2 3; return 1", 3))
815
816-- testing lua_equal with fallbacks
817do
818 local map = {}
819 local t = {__eq = function (a,b) return map[a] == map[b] end}
820 local function f(x)
821 local u = T.newuserdata(0)
822 debug.setmetatable(u, t)
823 map[u] = x
824 return u
825 end
826 assert(f(10) == f(10))
827 assert(f(10) ~= f(11))
828 assert(T.testC("compare EQ 2 3; return 1", f(10), f(10)))
829 assert(not T.testC("compare EQ 2 3; return 1", f(10), f(20)))
830 t.__eq = nil
831 assert(f(10) ~= f(10))
832end
833
834print'+'
835
836
837
838-- testing changing hooks during hooks
839_G.t = {}
840T.sethook([[
841 # set a line hook after 3 count hooks
842 sethook 4 0 '
843 getglobal t;
844 pushvalue -3; append -2
845 pushvalue -2; append -2
846 ']], "c", 3)
847local a = 1 -- counting
848a = 1 -- counting
849a = 1 -- count hook (set line hook)
850a = 1 -- line hook
851a = 1 -- line hook
852debug.sethook()
853t = _G.t
854assert(t[1] == "line")
855line = t[2]
856assert(t[3] == "line" and t[4] == line + 1)
857assert(t[5] == "line" and t[6] == line + 2)
858assert(t[7] == nil)
859
860
861-------------------------------------------------------------------------
862do -- testing errors during GC
863 local a = {}
864 for i=1,20 do
865 a[i] = T.newuserdata(i) -- creates several udata
866 end
867 for i=1,20,2 do -- mark half of them to raise errors during GC
868 debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
869 end
870 for i=2,20,2 do -- mark the other half to count and to create more garbage
871 debug.setmetatable(a[i], {__gc = function (x) load("A=A+1")() end})
872 end
873 _G.A = 0
874 a = 0
875 while 1 do
876 local stat, msg = pcall(collectgarbage)
877 if stat then
878 break -- stop when no more errors
879 else
880 a = a + 1
881 assert(string.find(msg, "__gc"))
882 end
883 end
884 assert(a == 10) -- number of errors
885
886 assert(A == 10) -- number of normal collections
887end
888-------------------------------------------------------------------------
889-- test for userdata vals
890do
891 local a = {}; local lim = 30
892 for i=0,lim do a[i] = T.pushuserdata(i) end
893 for i=0,lim do assert(T.udataval(a[i]) == i) end
894 for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
895 for i=0,lim do a[a[i]] = i end
896 for i=0,lim do a[T.pushuserdata(i)] = i end
897 assert(type(tostring(a[1])) == "string")
898end
899
900
901-------------------------------------------------------------------------
902-- testing multiple states
903T.closestate(T.newstate());
904L1 = T.newstate()
905assert(L1)
906
907assert(T.doremote(L1, "X='a'; return 'a'") == 'a')
908
909
910assert(#pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")) == 0)
911
912a, b = T.doremote(L1, "return f()")
913assert(a == 'alo' and b == '3')
914
915T.doremote(L1, "_ERRORMESSAGE = nil")
916-- error: `sin' is not defined
917a, _, b = T.doremote(L1, "return sin(1)")
918assert(a == nil and b == 2) -- 2 == run-time error
919
920-- error: syntax error
921a, b, c = T.doremote(L1, "return a+")
922assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
923
924T.loadlib(L1)
925a, b, c = T.doremote(L1, [[
926 string = require'string'
927 a = require'_G'; assert(a == _G and require("_G") == a)
928 io = require'io'; assert(type(io.read) == "function")
929 assert(require("io") == io)
930 a = require'table'; assert(type(a.insert) == "function")
931 a = require'debug'; assert(type(a.getlocal) == "function")
932 a = require'math'; assert(type(a.sin) == "function")
933 return string.sub('okinama', 1, 2)
934]])
935assert(a == "ok")
936
937T.closestate(L1);
938
939
940L1 = T.newstate()
941T.loadlib(L1)
942T.doremote(L1, "a = {}")
943T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
944 settable -3]])
945assert(T.doremote(L1, "return a.x") == "1")
946
947T.closestate(L1)
948
949L1 = nil
950
951print('+')
952
953-------------------------------------------------------------------------
954-- testing memory limits
955-------------------------------------------------------------------------
956checkerr("block too big", T.newuserdata, math.maxinteger)
957collectgarbage()
958T.totalmem(T.totalmem()+5000) -- set low memory limit (+5k)
959checkerr("not enough memory", load"local a={}; for i=1,100000 do a[i]=i end")
960T.totalmem(0) -- restore high limit
961
962-- test memory errors; increase memory limit in small steps, so that
963-- we get memory errors in different parts of a given task, up to there
964-- is enough memory to complete the task without errors
965function testamem (s, f)
966 collectgarbage(); collectgarbage()
967 local M = T.totalmem()
968 local oldM = M
969 local a,b = nil
970 while 1 do
971 M = M+7 -- increase memory limit in small steps
972 T.totalmem(M)
973 a, b = pcall(f)
974 T.totalmem(0) -- restore high limit
975 if a and b then break end -- stop when no more errors
976 collectgarbage()
977 if not a and not -- `real' error?
978 (string.find(b, "memory") or string.find(b, "overflow")) then
979 error(b, 0) -- propagate it
980 end
981 end
982 print("\nlimit for " .. s .. ": " .. M-oldM)
983 return b
984end
985
986
987-- testing memory errors when creating a new state
988
989b = testamem("state creation", T.newstate)
990T.closestate(b); -- close new state
991
992
993-- testing threads
994
995-- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1)
996mt = T.testC("rawgeti R 1; return 1")
997assert(type(mt) == "thread" and coroutine.running() == mt)
998
999
1000
1001function expand (n,s)
1002 if n==0 then return "" end
1003 local e = string.rep("=", n)
1004 return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
1005 e, s, expand(n-1,s), e)
1006end
1007
1008G=0; collectgarbage(); a =collectgarbage("count")
1009load(expand(20,"G=G+1"))()
1010assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
1011
1012testamem("thread creation", function ()
1013 return T.doonnewstack("x=1") == 0 -- try to create thread
1014end)
1015
1016
1017-- testing memory x compiler
1018
1019testamem("loadstring", function ()
1020 return load("x=1") -- try to do load a string
1021end)
1022
1023
1024local testprog = [[
1025local function foo () return end
1026local t = {"x"}
1027a = "aaa"
1028for i = 1, #t do a=a..t[i] end
1029return true
1030]]
1031
1032-- testing memory x dofile
1033_G.a = nil
1034local t =os.tmpname()
1035local f = assert(io.open(t, "w"))
1036f:write(testprog)
1037f:close()
1038testamem("dofile", function ()
1039 local a = loadfile(t)
1040 return a and a()
1041end)
1042assert(os.remove(t))
1043assert(_G.a == "aaax")
1044
1045
1046-- other generic tests
1047
1048testamem("string creation", function ()
1049 local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
1050 return (a == 'ablo ablo')
1051end)
1052
1053testamem("dump/undump", function ()
1054 local a = load(testprog)
1055 local b = a and string.dump(a)
1056 a = b and load(b)
1057 return a and a()
1058end)
1059
1060local t = os.tmpname()
1061testamem("file creation", function ()
1062 local f = assert(io.open(t, 'w'))
1063 assert (not io.open"nomenaoexistente")
1064 io.close(f);
1065 return not loadfile'nomenaoexistente'
1066end)
1067assert(os.remove(t))
1068
1069testamem("table creation", function ()
1070 local a, lim = {}, 10
1071 for i=1,lim do a[i] = i; a[i..'a'] = {} end
1072 return (type(a[lim..'a']) == 'table' and a[lim] == lim)
1073end)
1074
1075testamem("constructors", function ()
1076 local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
1077 return (type(a) == 'table' and a.e == 5)
1078end)
1079
1080local a = 1
1081close = nil
1082testamem("closure creation", function ()
1083 function close (b,c)
1084 return function (x) return a+b+c+x end
1085 end
1086 return (close(2,3)(4) == 10)
1087end)
1088
1089testamem("coroutines", function ()
1090 local a = coroutine.wrap(function ()
1091 coroutine.yield(string.rep("a", 10))
1092 return {}
1093 end)
1094 assert(string.len(a()) == 10)
1095 return a()
1096end)
1097
1098do -- auxiliary buffer
1099 local lim = 100
1100 local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
1101 testamem("auxiliary buffer", function ()
1102 return (#table.concat(a, ",") == 20*lim + lim - 1)
1103 end)
1104end
1105
1106print'+'
1107
1108-- testing some auxlib functions
1109local function gsub (a, b, c)
1110 a, b = T.testC("gsub 2 3 4; gettop; return 2", a, b, c)
1111 assert(b == 5)
1112 return a
1113end
1114
1115assert(gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
1116assert(gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
1117assert(gsub("", "alo", "//") == "")
1118assert(gsub("...", ".", "/.") == "/././.")
1119assert(gsub("...", "...", "") == "")
1120
1121
1122-- testing luaL_newmetatable
1123local mt_xuxu, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1124assert(type(mt_xuxu) == "table" and res and top == 3)
1125local d, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1126assert(mt_xuxu == d and not res and top == 3)
1127d, res, top = T.testC("newmetatable xuxu1; gettop; return 3")
1128assert(mt_xuxu ~= d and res and top == 3)
1129
1130x = T.newuserdata(0);
1131y = T.newuserdata(0);
1132T.testC("pushstring xuxu; gettable R; setmetatable 2", x)
1133assert(getmetatable(x) == mt_xuxu)
1134
1135-- testing luaL_testudata
1136-- correct metatable
1137local res1, res2, top = T.testC([[testudata -1 xuxu
1138 testudata 2 xuxu
1139 gettop
1140 return 3]], x)
1141assert(res1 and res2 and top == 4)
1142
1143-- wrong metatable
1144res1, res2, top = T.testC([[testudata -1 xuxu1
1145 testudata 2 xuxu1
1146 gettop
1147 return 3]], x)
1148assert(not res1 and not res2 and top == 4)
1149
1150-- non-existent type
1151res1, res2, top = T.testC([[testudata -1 xuxu2
1152 testudata 2 xuxu2
1153 gettop
1154 return 3]], x)
1155assert(not res1 and not res2 and top == 4)
1156
1157-- userdata has no metatable
1158res1, res2, top = T.testC([[testudata -1 xuxu
1159 testudata 2 xuxu
1160 gettop
1161 return 3]], y)
1162assert(not res1 and not res2 and top == 4)
1163
1164-- erase metatables
1165do
1166 local r = debug.getregistry()
1167 assert(r.xuxu == mt_xuxu and r.xuxu1 == d)
1168 r.xuxu = nil; r.xuxu1 = nil
1169end
1170
1171print'OK'
1172