@@ -0,0 +1,1296 @@
1+if T == nil then
2+(Message or print)("
3+ >>> testC not active: skipping API tests <<<
4+")
5+return
6+end
7+local debug = require("debug")
8+local pack = table.pack
9+local MEMERRMSG = "not enough memory"
10+local function tcheck
11+(t1,t2)
12+assert(t1.n == (t2.n or # t2) + 1)
13+for i = 2, t1.n
14+do
15+assert(t1[i] == t2[i - 1])
16+end
17+end
18+local function checkerr
19+(msg,f, ...)
20+local stat,err = pcall(f,...)
21+assert(not stat and string.find(err,msg))
22+end
23+print("testing C API")
24+local a = T.testC("pushvalue R; return 1")
25+assert(a == debug.getregistry())
26+assert(T.testC("settop 10; absindex -1; return 1") == 10)
27+assert(T.testC("settop 5; absindex -5; return 1") == 1)
28+assert(T.testC("settop 10; absindex 1; return 1") == 1)
29+assert(T.testC("settop 10; absindex R; return 1") < - 10)
30+a=T.d2s(12458954321123)
31+assert(a == string.pack("d",12458954321123))
32+assert(T.s2d(a) == 12458954321123)
33+local a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
34+assert(a == 2 and b == 3 and not c)
35+local f = T.makeCfunc("pushnum 1; pushnum 2; pushnum 3; return 2")
36+a,b,c=f()
37+assert(a == 2 and b == 3 and not c)
38+a,b,c=T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
39+assert(a == b and a == true and c == false)
40+a,b,c=T.testC("pushbool 0; pushbool 10; pushnil;
41+ tobool -3; tobool -3; tobool -3; return 3")
42+assert(a == false and b == true and c == false)
43+a,b,c=T.testC("gettop; return 2",10,20,30,40)
44+assert(a == 40 and b == 5 and not c)
45+local t = pack(T.testC("settop 5; return *",2,3))
46+tcheck(t,{["n"] = 4,2,3})
47+t=pack(T.testC("settop 0; settop 15; return 10",3,1,23))
48+assert(t.n == 10 and t[1] == nil and t[10] == nil)
49+t=pack(T.testC("remove -2; return *",2,3,4))
50+tcheck(t,{["n"] = 2,2,4})
51+t=pack(T.testC("insert -1; return *",2,3))
52+tcheck(t,{["n"] = 2,2,3})
53+t=pack(T.testC("insert 3; return *",2,3,4,5))
54+tcheck(t,{["n"] = 4,2,5,3,4})
55+t=pack(T.testC("replace 2; return *",2,3,4,5))
56+tcheck(t,{["n"] = 3,5,3,4})
57+t=pack(T.testC("replace -2; return *",2,3,4,5))
58+tcheck(t,{["n"] = 3,2,3,5})
59+t=pack(T.testC("remove 3; return *",2,3,4,5))
60+tcheck(t,{["n"] = 3,2,4,5})
61+t=pack(T.testC("copy 3 4; return *",2,3,4,5))
62+tcheck(t,{["n"] = 4,2,3,3,5})
63+t=pack(T.testC("copy -3 -1; return *",2,3,4,5))
64+tcheck(t,{["n"] = 4,2,3,4,3})
65+local t = {10,20,30,40,50,60}
66+for i = - 6, 6
67+do
68+local s = string.format("rotate 2 %d; return 7",i)
69+local t1 = pack(T.testC(s,10,20,30,40,50,60))
70+tcheck(t1,t)
71+table.insert(t,1,table.remove(t))
72+end
73+t=pack(T.testC("rotate -2 1; return *",10,20,30,40))
74+tcheck(t,{10,20,40,30})
75+t=pack(T.testC("rotate -2 -1; return *",10,20,30,40))
76+tcheck(t,{10,20,40,30})
77+t=pack(T.testC("rotate -1 0; return *",10,20,30,40))
78+tcheck(t,{10,20,30,40})
79+t=pack(T.testC("rotate -1 1; return *",10,20,30,40))
80+tcheck(t,{10,20,30,40})
81+t=pack(T.testC("rotate 5 -1; return *",10,20,30,40))
82+tcheck(t,{10,20,30,40})
83+T.testC(" warningC "#This shold be a"
84+ warningC " single "
85+ warning "warning"
86+ warningC "#This should be "
87+ warning "another one"
88+")
89+local f = T.makeCfunc(" getglobal error
90+ pushstring bola
91+ pcall 1 1 1 # call 'error' with given handler
92+ pushstatus
93+ return 2 # return error message and status
94+ ")
95+local msg,st = f(string.upper)
96+assert(st == "ERRRUN" and msg == "BOLA")
97+local msg,st = f(string.len)
98+assert(st == "ERRRUN" and msg == 4)
99+t=pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2;
100+ insert 2; pushvalue 1; remove 1; insert 1;
101+ insert -2; pushvalue -2; remove -3; return *",2,3,4,5,10,40,90))
102+tcheck(t,{["n"] = 7,2,3,4,5,10,40,90})
103+t=pack(T.testC("concat 5; return *","alo",2,3,"joao",12))
104+tcheck(t,{["n"] = 1,"alo23joao12"})
105+t=pack(T.testC("call 2,-1; return *",(a,b)
106+return 1,2,3,4,a,b
107+end,"alo","joao"))
108+tcheck(t,{["n"] = 6,1,2,3,4,"alo","joao"})
109+local a = {}
110+for i = 1, 1e3
111+do
112+a[i]=true
113+end
114+;
115+a[999]=10
116+local b = T.testC("pcall 1 -1 0; pop 1; tostring -1; return 1",table.unpack,a)
117+assert(b == "10")
118+_G.AA=14
119+;
120+_G.BB="a31"
121+local a = {T.testC(" getglobal AA;
122+ getglobal BB;
123+ getglobal BB;
124+ setglobal AA;
125+ return *
126+")}
127+assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.AA == "a31")
128+_G.AA,_G.BB=nil
129+assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5)
130+assert(T.testC("pushnum 10; pushnum 20; arith -; return 1") == - 10)
131+assert(T.testC("pushnum 10; pushnum -20; arith *; return 1") == - 200)
132+assert(T.testC("pushnum 10; pushnum 3; arith ^; return 1") == 1e3)
133+assert(T.testC("pushnum 10; pushstring 20; arith /; return 1") == 0.5)
134+assert(T.testC("pushstring 10; pushnum 20; arith -; return 1") == - 10)
135+assert(T.testC("pushstring 10; pushstring -20; arith *; return 1") == - 200)
136+assert(T.testC("pushstring 10; pushstring 3; arith ^; return 1") == 1e3)
137+assert(T.testC("arith /; return 1",2,0) == 10 / 0)
138+a=T.testC("pushnum 10; pushint 3; arith \; return 1")
139+assert(a == 3 and math.type(a) == "float")
140+a=T.testC("pushint 10; pushint 3; arith \; return 1")
141+assert(a == 3 and math.type(a) == "integer")
142+a=assert(T.testC("pushint 10; pushint 3; arith +; return 1"))
143+assert(a == 13 and math.type(a) == "integer")
144+a=assert(T.testC("pushnum 10; pushint 3; arith +; return 1"))
145+assert(a == 13 and math.type(a) == "float")
146+a,b,c=T.testC("pushnum 1;
147+ pushstring 10; arith _;
148+ pushstring 5; return 3")
149+assert(a == 1 and b == - 10 and c == "5")
150+local mt = {["__add"] = (a,b)
151+return setmetatable({a[1] + b[1]},mt)
152+end,["__mod"] = (a,b)
153+return setmetatable({a[1] % b[1]},mt)
154+end,["__unm"] = (a)
155+return setmetatable({a[1] * 2},mt)
156+end}
157+a,b,c=setmetatable({4},mt),setmetatable({8},mt),setmetatable({- 3},mt)
158+local x,y,z = T.testC("arith +; return 2",10,a,b)
159+assert(x == 10 and y[1] == 12 and z == nil)
160+assert(T.testC("arith %; return 1",a,c)[1] == 4 % - 3)
161+assert(T.testC("arith _; arith +; arith %; return 1",b,a,c)[1] == 8 % (4 + (- 3) * 2))
162+checkerr("divide by zero",T.testC,"arith \",10,0)
163+checkerr("%%0",T.testC,"arith %",10,0)
164+assert(T.testC("compare LT 2 5, return 1",3,2,2,4,2,2))
165+assert(T.testC("compare LE 2 5, return 1",3,2,2,4,2,2))
166+assert(not T.testC("compare LT 3 4, return 1",3,2,2,4,2,2))
167+assert(T.testC("compare LE 3 4, return 1",3,2,2,4,2,2))
168+assert(T.testC("compare LT 5 2, return 1",4,2,2,3,2,2))
169+assert(not T.testC("compare LT 2 -3, return 1","4","2","2","3","2","2"))
170+assert(not T.testC("compare LT -3 2, return 1","3","2","2","4","2","2"))
171+assert(not T.testC("compare LT 1 4, return 1"))
172+assert(not T.testC("compare LE 9 1, return 1"))
173+assert(not T.testC("compare EQ 9 9, return 1"))
174+local b = {["__lt"] = (a,b)
175+return a[1] < b[1]
176+end}
177+local a1,a3,a4 = setmetatable({1},b),setmetatable({3},b),setmetatable({4},b)
178+assert(T.testC("compare LT 2 5, return 1",a3,2,2,a4,2,2))
179+assert(T.testC("compare LE 2 5, return 1",a3,2,2,a4,2,2))
180+assert(T.testC("compare LT 5 -6, return 1",a4,2,2,a3,2,2))
181+a,b=T.testC("compare LT 5 -6, return 2",a1,2,2,a3,2,20)
182+assert(a == 20 and b == false)
183+a,b=T.testC("compare LE 5 -6, return 2",a1,2,2,a3,2,20)
184+assert(a == 20 and b == false)
185+a,b=T.testC("compare LE 5 -6, return 2",a1,2,2,a1,2,20)
186+assert(a == 20 and b == true)
187+local mt = {["__lt"] = (a,b)
188+return a[1] < b[1]
189+end,["__le"] = (a,b)
190+return a[1] <= b[1]
191+end,["__eq"] = (a,b)
192+return a[1] == b[1]
193+end}
194+local function O
195+(x)
196+return setmetatable({x},mt)
197+end
198+local a,b = T.testC("compare LT 2 3; pushint 10; return 2",O(1),O(2))
199+assert(a == true and b == 10)
200+local a,b = T.testC("compare LE 2 3; pushint 10; return 2",O(3),O(2))
201+assert(a == false and b == 10)
202+local a,b = T.testC("compare EQ 2 3; pushint 10; return 2",O(3),O(3))
203+assert(a == true and b == 10)
204+local t = setmetatable({["x"] = 20},{["__len"] = (t)
205+return t.x
206+end})
207+a,b,c=T.testC(" len 2;
208+ Llen 2;
209+ objsize 2;
210+ return 3
211+",t)
212+assert(a == 20 and b == 20 and c == 0)
213+t.x="234"
214+;
215+t[1]=20
216+a,b,c=T.testC(" len 2;
217+ Llen 2;
218+ objsize 2;
219+ return 3
220+",t)
221+assert(a == "234" and b == 234 and c == 1)
222+t.x=print
223+;
224+t[1]=20
225+a,c=T.testC(" len 2;
226+ objsize 2;
227+ return 2
228+",t)
229+assert(a == print and c == 1)
230+a=setmetatable({["x"] = "u"},{["__concat"] = (a,b)
231+return a.x .. "." .. b.x
232+end})
233+x,y=T.testC(" pushnum 5
234+ pushvalue 2;
235+ pushvalue 2;
236+ concat 2;
237+ pushvalue -2;
238+ return 2;
239+",a,a)
240+assert(x == a .. a and y == 5)
241+assert(T.testC("concat 0; return 1") == "")
242+assert(T.testC("concat 1; return 1","xuxu") == "xuxu")
243+local function B
244+(x)
245+return x and 1 or 0
246+end
247+local function count
248+(x,n)
249+n=n or 2
250+local prog = " isnumber %d;
251+ isstring %d;
252+ isfunction %d;
253+ iscfunction %d;
254+ istable %d;
255+ isuserdata %d;
256+ isnil %d;
257+ isnull %d;
258+ return 8
259+ "
260+prog=string.format(prog,n,n,n,n,n,n,n,n)
261+local a,b,c,d,e,f,g,h = T.testC(prog,x)
262+return B(a) + B(b) + B(c) + B(d) + B(e) + B(f) + B(g) + (100 * B(h))
263+end
264+assert(count(3) == 2)
265+assert(count("alo") == 1)
266+assert(count("32") == 2)
267+assert(count({}) == 1)
268+assert(count(print) == 2)
269+assert(count(()
270+
271+end) == 1)
272+assert(count(nil) == 1)
273+assert(count(io.stdin) == 1)
274+assert(count(nil,15) == 100)
275+local function to
276+(s,x,n)
277+n=n or 2
278+return T.testC(string.format("%s %d; return 1",s,n),x)
279+end
280+local null = T.pushuserdata(0)
281+local hfunc = string.gmatch("","")
282+assert(debug.getupvalue(hfunc,1))
283+assert(to("tostring",{}) == nil)
284+assert(to("tostring","alo") == "alo")
285+assert(to("tostring",12) == "12")
286+assert(to("tostring",12,3) == nil)
287+assert(to("objsize",{}) == 0)
288+assert(to("objsize",{1,2,3}) == 3)
289+assert(to("objsize","aloa") == 6)
290+assert(to("objsize",T.newuserdata(0)) == 0)
291+assert(to("objsize",T.newuserdata(101)) == 101)
292+assert(to("objsize",124) == 0)
293+assert(to("objsize",true) == 0)
294+assert(to("tonumber",{}) == 0)
295+assert(to("tonumber","12") == 12)
296+assert(to("tonumber","s2") == 0)
297+assert(to("tonumber",1,20) == 0)
298+assert(to("topointer",10) == null)
299+assert(to("topointer",true) == null)
300+assert(to("topointer",nil) == null)
301+assert(to("topointer","abc") ~= null)
302+assert(to("topointer",string.rep("x",10)) == to("topointer",string.rep("x",10)))
303+local s1 = string.rep("x",300)
304+local s2 = string.rep("x",300)
305+assert(to("topointer",s1) ~= to("topointer",s2))
306+assert(to("topointer",T.pushuserdata(20)) ~= null)
307+assert(to("topointer",io.read) ~= null)
308+assert(to("topointer",hfunc) ~= null)
309+assert(to("topointer",()
310+
311+end) ~= null)
312+assert(to("topointer",io.stdin) ~= null)
313+assert(to("func2num",20) == 0)
314+assert(to("func2num",T.pushuserdata(10)) == 0)
315+assert(to("func2num",io.read) ~= 0)
316+assert(to("func2num",hfunc) ~= 0)
317+a=to("tocfunction",math.deg)
318+assert(a(3) == math.deg(3) and a == math.deg)
319+print("testing panic function")
320+assert(T.checkpanic("pushstring hi; error") == "hi")
321+assert(T.checkpanic("pushstring hi; error;","checkstack 5 XX
322+ pushstring ' alo'
323+ pushstring ' mundo'
324+ concat 3") == "hi alo mundo")
325+assert(T.checkpanic("loadstring 4") == "bad argument #4 (string expected, got no value)")
326+T.totalmem(T.totalmem() + 1e4)
327+assert(T.checkpanic("newuserdata 20000") == MEMERRMSG)
328+T.totalmem(0)
329+if not _soft then
330+local msg = T.checkpanic(" pushstring "function f() f() end"
331+ loadstring -1; call 0 0
332+ getglobal f; call 0 0
333+ ")
334+assert(string.find(msg,"stack overflow"))
335+end
336+assert(T.checkpanic(" pushstring "return {__close = function () Y = 'ho'; end}"
337+ newtable
338+ loadstring -2
339+ call 0 1
340+ setmetatable -2
341+ toclose -1
342+ pushstring "hi"
343+ error
344+ "," getglobal Y
345+ concat 2 # concat original error with global Y
346+ ") == "hiho")
347+if not _soft then
348+print("testing stack overflow")
349+collectgarbage("stop")
350+checkerr("XXXX",T.testC,"checkstack 1000023 XXXX")
351+checkerr("^stack overflow$",T.testC,"checkstack 1000023 ''")
352+local s = string.rep("pushnil;checkstack 1 XX;",1e6)
353+checkerr("overflow",T.testC,s)
354+collectgarbage("restart")
355+print("+")
356+end
357+local lim = _soft and 500 or 1.2e4
358+local prog = {"checkstack " .. (lim * 2 + 100) .. "msg","newtable"}
359+for i = 1, lim
360+do
361+prog[# prog + 1]="pushnum " .. i
362+prog[# prog + 1]="pushnum " .. i * 10
363+end
364+prog[# prog + 1]="rawgeti R 2"
365+prog[# prog + 1]="insert " .. - (2 * lim + 2)
366+for i = 1, lim
367+do
368+prog[# prog + 1]="settable " .. - (2 * (lim - i + 1) + 1)
369+end
370+prog[# prog + 1]="return 2"
371+prog=table.concat(prog,";")
372+local g,t = T.testC(prog)
373+assert(g == _G)
374+for i = 1, lim
375+do
376+assert(t[i] == i * 10)
377+;
378+t[i]=undef
379+end
380+assert(next(t) == nil)
381+prog,g,t=nil
382+a=T.testC(" loadstring 2; pcall 0 1 0;
383+ pushvalue 3; insert -2; pcall 1 1 0;
384+ pcall 0 0 0;
385+ return 1
386+","XX=150",(a)
387+assert(a == nil)
388+;
389+return 3
390+end)
391+assert(type(a) == "string" and XX == 150)
392+_G.XX=nil
393+local function check3
394+(p, ...)
395+local arg = {...}
396+assert(# arg == 3)
397+assert(string.find(arg[3],p))
398+end
399+check3(":1:",T.testC("loadstring 2; return *","x="))
400+check3("%.",T.testC("loadfile 2; return *","."))
401+check3("xxxx",T.testC("loadfile 2; return *","xxxx"))
402+local function checkerrnopro
403+(code,msg)
404+local th = coroutine.create(()
405+
406+end)
407+local stt,err = pcall(T.testC,th,code)
408+assert(not stt and string.find(err,msg))
409+end
410+if not _soft then
411+collectgarbage("stop")
412+checkerrnopro("pushnum 3; call 0 0","attempt to call")
413+print("testing stack overflow in unprotected thread")
414+function F()
415+F()
416+end
417+checkerrnopro("getglobal 'F'; call 0 0;","stack overflow")
418+F=nil
419+collectgarbage("restart")
420+end
421+print("+")
422+local a = {}
423+local a1 = T.testC("rawsetp 2 1; return 1",a,20)
424+assert(a == a1)
425+assert(a[T.pushuserdata(1)] == 20)
426+local a1,res = T.testC("rawgetp -1 1; return 2",a)
427+assert(a == a1 and res == 20)
428+local a = {}
429+a[a]=10
430+local prog = "gettable -1; return *"
431+local res = {T.testC(prog,a)}
432+assert(# res == 2 and res[1] == prog and res[2] == 10)
433+local prog = "settable -2; return *"
434+local res = {T.testC(prog,a,20)}
435+assert(a[a] == 20)
436+assert(# res == 1 and res[1] == prog)
437+a[a]=10
438+local prog = "rawget -1; return *"
439+local res = {T.testC(prog,a)}
440+assert(# res == 2 and res[1] == prog and res[2] == 10)
441+local prog = "rawset -2; return *"
442+local res = {T.testC(prog,a,20)}
443+assert(a[a] == 20)
444+assert(# res == 1 and res[1] == prog)
445+local prog = "rawset -1; return *"
446+local res = {T.testC(prog,30,a)}
447+assert(a[30] == a)
448+assert(# res == 1 and res[1] == prog)
449+local prog = "settable -1; return *"
450+local res = {T.testC(prog,40,a)}
451+assert(a[40] == a)
452+assert(# res == 1 and res[1] == prog)
453+local prog = "rawseti -1 100; return *"
454+local res = {T.testC(prog,a)}
455+assert(a[100] == a)
456+assert(# res == 1 and res[1] == prog)
457+local prog = "seti -1 200; return *"
458+local res = {T.testC(prog,a)}
459+assert(a[200] == a)
460+assert(# res == 1 and res[1] == prog)
461+a={["x"] = 0,["y"] = 12}
462+x,y=T.testC("gettable 2; pushvalue 4; gettable 2; return 2",a,3,"y",4,"x")
463+assert(x == 0 and y == 12)
464+T.testC("settable -5",a,3,4,"x",15)
465+assert(a.x == 15)
466+a[a]=print
467+x=T.testC("gettable 2; return 1",a)
468+assert(x == print)
469+T.testC("settable 2",a,"x")
470+assert(a[a] == "x")
471+b=setmetatable({["p"] = a},{})
472+getmetatable(b).__index=(t,i)
473+return t.p[i]
474+end
475+local k,x = T.testC("gettable 3, return 2",4,b,20,35,"x")
476+assert(x == 15 and k == 35)
477+k=T.testC("getfield 2 y, return 1",b)
478+assert(k == 12)
479+getmetatable(b).__index=(t,i)
480+return a[i]
481+end
482+getmetatable(b).__newindex=(t,i,v)
483+a[i]=v
484+end
485+y=T.testC("insert 2; gettable -5; return 1",2,3,4,"y",b)
486+assert(y == 12)
487+k=T.testC("settable -5, return 1",b,3,4,"x",16)
488+assert(a.x == 16 and k == 4)
489+a[b]="xuxu"
490+y=T.testC("gettable 2, return 1",b)
491+assert(y == "xuxu")
492+T.testC("settable 2",b,19)
493+assert(a[b] == 19)
494+local t = {["_012345678901234567890123456789012345678901234567890123456789"] = 32}
495+local a = T.testC(" getfield 2 _012345678901234567890123456789012345678901234567890123456789
496+ return 1
497+ ",t)
498+assert(a == 32)
499+local a = T.testC(" pushnum 33
500+ setglobal _012345678901234567890123456789012345678901234567890123456789
501+ ")
502+assert(_012345678901234567890123456789012345678901234567890123456789 == 33)
503+_012345678901234567890123456789012345678901234567890123456789=nil
504+a={}
505+t=pack(T.testC("next; return *",a,nil))
506+tcheck(t,{["n"] = 1,a})
507+a={["a"] = 3}
508+t=pack(T.testC("next; return *",a,nil))
509+tcheck(t,{["n"] = 3,a,"a",3})
510+t=pack(T.testC("next; pop 1; next; return *",a,nil))
511+tcheck(t,{["n"] = 1,a})
512+local A = T.testC(" pushnum 10; pushnum 20; pushcclosure 2; return 1")
513+t,b,c=A("pushvalue U0; pushvalue U1; pushvalue U2; return 3")
514+assert(b == 10 and c == 20 and type(t) == "table")
515+a,b=A("tostring U3; tonumber U4; return 2")
516+assert(a == nil and b == 0)
517+A("pushnum 100; pushnum 200; replace U2; replace U1")
518+b,c=A("pushvalue U1; pushvalue U2; return 2")
519+assert(b == 100 and c == 200)
520+A("replace U2; replace U1",{["x"] = 1},{["x"] = 2})
521+b,c=A("pushvalue U1; pushvalue U2; return 2")
522+assert(b.x == 1 and c.x == 2)
523+T.checkmemory()
524+assert(T.testC("isnull U1; return 1") == true)
525+assert(T.testC("isnull U100; return 1") == true)
526+assert(T.testC("pushvalue U1; return 1") == nil)
527+local f = T.testC(" pushnum 10; pushnum 20; pushcclosure 2; return 1")
528+assert(T.upvalue(f,1) == 10 and T.upvalue(f,2) == 20 and T.upvalue(f,3) == nil)
529+T.upvalue(f,2,"xuxu")
530+assert(T.upvalue(f,2) == "xuxu")
531+local A = "checkstack 300 msg;" .. string.rep("pushnum 10;",255) .. "pushcclosure 255; return 1"
532+A=T.testC(A)
533+for i = 1, 255
534+do
535+assert(A(("pushvalue U%d; return 1"):format(i)) == 10)
536+end
537+assert(A("isnull U256; return 1"))
538+assert(not A("isnil U256; return 1"))
539+checkerr("got number",debug.setuservalue,3,{})
540+checkerr("got nil",debug.setuservalue,nil,{})
541+checkerr("got light userdata",debug.setuservalue,T.pushuserdata(1),{})
542+local b = T.newuserdata(0,10)
543+for i = 1, 10
544+do
545+local v,p = debug.getuservalue(b,i)
546+assert(v == nil and p)
547+end
548+local v,p = debug.getuservalue(b,- 2)
549+assert(v == nil and not p)
550+local v,p = debug.getuservalue(b,11)
551+assert(v == nil and not p)
552+local t = {true,false,4.56,print,{},b,"XYZ"}
553+for k,v in ipairs(t)
554+do
555+debug.setuservalue(b,v,k)
556+end
557+for k,v in ipairs(t)
558+do
559+local v1,p = debug.getuservalue(b,k)
560+assert(v1 == v and p)
561+end
562+assert(not debug.getuservalue(4))
563+debug.setuservalue(b,()
564+return 10
565+end,10)
566+collectgarbage()
567+assert(debug.getuservalue(b,10)() == 10)
568+debug.setuservalue(b,134)
569+collectgarbage()
570+assert(debug.getuservalue(b) == 134)
571+local oldmode = collectgarbage("incremental")
572+T.gcstate("atomic")
573+assert(T.gccolor(b) == "black")
574+debug.setuservalue(b,{["x"] = 100})
575+T.gcstate("pause")
576+assert(debug.getuservalue(b).x == 100)
577+collectgarbage(oldmode)
578+for i = 1, 1e3
579+do
580+local bb = T.newuserdata(0,1)
581+debug.setuservalue(bb,b)
582+b=bb
583+end
584+collectgarbage()
585+for i = 1, 1e3
586+do
587+b=debug.getuservalue(b)
588+end
589+assert(debug.getuservalue(b).x == 100)
590+b=nil
591+local i = T.ref({})
592+T.unref(i)
593+assert(T.ref({}) == i)
594+local Arr = {}
595+local Lim = 100
596+for i = 1, Lim
597+do
598+Arr[i]=T.ref({})
599+end
600+assert(T.ref(nil) == - 1 and T.getref(- 1) == nil)
601+T.unref(- 1)
602+;
603+T.unref(- 1)
604+for i = 1, Lim
605+do
606+T.unref(Arr[i])
607+end
608+local function printlocks
609+()
610+local f = T.makeCfunc("gettable R; return 1")
611+local n = f("n")
612+print("n",n)
613+for i = 0, n
614+do
615+print(i,f(i))
616+end
617+end
618+for i = 1, Lim
619+do
620+Arr[i]=T.ref({})
621+end
622+for i = 1, Lim, 2
623+do
624+T.unref(Arr[i])
625+end
626+assert(type(T.getref(Arr[2])) == "table")
627+assert(T.getref(- 1) == nil)
628+a=T.ref({})
629+collectgarbage()
630+assert(type(T.getref(a)) == "table")
631+local tt = {}
632+local cl = {["n"] = 0}
633+A=nil
634+;
635+B=nil
636+local F =
637+F=(x)
638+local udval = T.udataval(x)
639+table.insert(cl,udval)
640+local d = T.newuserdata(100)
641+d=nil
642+assert(debug.getmetatable(x).__gc == F)
643+assert(load("table.insert({}, {})"))()
644+assert(not collectgarbage())
645+local dummy = {}
646+if A ~= nil then
647+assert(type(A) == "userdata")
648+assert(T.udataval(A) == B)
649+debug.getmetatable(A)
650+end
651+A=x
652+B=udval
653+return 1,2,3
654+end
655+tt.__gc=F
656+collectgarbage()
657+;
658+collectgarbage()
659+;
660+local x = collectgarbage("count")
661+;
662+local a = T.newuserdata(5001)
663+assert(T.testC("objsize 2; return 1",a) == 5001)
664+assert(collectgarbage("count") >= x + 4)
665+a=nil
666+collectgarbage()
667+;
668+assert(collectgarbage("count") <= x + 1)
669+x=collectgarbage("count")
670+collectgarbage("stop")
671+for i = 1, 1e3
672+do
673+T.newuserdata(0)
674+end
675+assert(collectgarbage("count") > x + 10)
676+collectgarbage()
677+assert(collectgarbage("count") <= x + 1)
678+collectgarbage()
679+x=collectgarbage("count")
680+collectgarbage("stop")
681+a={["__gc"] = ()
682+
683+end}
684+for i = 1, 1e3
685+do
686+debug.setmetatable(T.newuserdata(0),a)
687+end
688+assert(collectgarbage("count") >= x + 10)
689+collectgarbage()
690+assert(collectgarbage("count") >= x + 10)
691+collectgarbage()
692+assert(collectgarbage("count") <= x + 1)
693+collectgarbage("restart")
694+collectgarbage("stop")
695+a=T.newuserdata(0)
696+;
697+debug.setmetatable(a,tt)
698+;
699+local na = T.udataval(a)
700+b=T.newuserdata(0)
701+;
702+debug.setmetatable(b,tt)
703+;
704+local nb = T.udataval(b)
705+c=T.newuserdata(0)
706+;
707+debug.setmetatable(c,tt)
708+;
709+local nc = T.udataval(c)
710+x=T.newuserdata(4)
711+y=T.newuserdata(0)
712+checkerr("FILE%* expected, got userdata",io.input,a)
713+checkerr("FILE%* expected, got userdata",io.input,x)
714+assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
715+local d = T.ref(a)
716+;
717+local e = T.ref(b)
718+;
719+local f = T.ref(c)
720+;
721+t={T.getref(d),T.getref(e),T.getref(f)}
722+assert(t[1] == a and t[2] == b and t[3] == c)
723+t=nil
724+;
725+a=nil
726+;
727+c=nil
728+;
729+T.unref(e)
730+;
731+T.unref(f)
732+collectgarbage()
733+assert(# cl == 1 and cl[1] == nc)
734+x=T.getref(d)
735+assert(type(x) == "userdata" and debug.getmetatable(x) == tt)
736+x=nil
737+tt.b=b
738+tt=nil
739+A=nil
740+b=nil
741+T.unref(d)
742+;
743+local n5 = T.newuserdata(0)
744+debug.setmetatable(n5,{["__gc"] = F})
745+n5=T.udataval(n5)
746+collectgarbage()
747+assert(# cl == 4)
748+assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
749+collectgarbage("restart")
750+a,na={},{}
751+for i = 30, 1, - 1
752+do
753+a[i]=T.newuserdata(0)
754+debug.setmetatable(a[i],{["__gc"] = F})
755+na[i]=T.udataval(a[i])
756+end
757+cl={}
758+a=nil
759+;
760+collectgarbage()
761+assert(# cl == 30)
762+for i = 1, 30
763+do
764+assert(cl[i] == na[i])
765+end
766+na=nil
767+for i = 2, Lim, 2
768+do
769+T.unref(Arr[i])
770+end
771+x=T.newuserdata(41)
772+;
773+debug.setmetatable(x,{["__gc"] = F})
774+assert(T.testC("objsize 2; return 1",x) == 41)
775+cl={}
776+a={[x] = 1}
777+x=T.udataval(x)
778+collectgarbage()
779+assert(# cl == 0)
780+for n in pairs(a)
781+do
782+a[n]=undef
783+end
784+collectgarbage()
785+assert(# cl == 1 and cl[1] == x)
786+assert(T.testC("compare EQ 2 4; return 1",print,1,print,20))
787+assert(T.testC("compare EQ 3 2; return 1","alo","alo"))
788+assert(T.testC("compare EQ 2 3; return 1",nil,nil))
789+assert(not T.testC("compare EQ 2 3; return 1",{},{}))
790+assert(not T.testC("compare EQ 2 3; return 1"))
791+assert(not T.testC("compare EQ 2 3; return 1",3))
792+local map = {}
793+local t = {["__eq"] = (a,b)
794+return map[a] == map[b]
795+end}
796+local function f
797+(x)
798+local u = T.newuserdata(0)
799+debug.setmetatable(u,t)
800+map[u]=x
801+return u
802+end
803+assert(f(10) == f(10))
804+assert(f(10) ~= f(11))
805+assert(T.testC("compare EQ 2 3; return 1",f(10),f(10)))
806+assert(not T.testC("compare EQ 2 3; return 1",f(10),f(20)))
807+t.__eq=nil
808+assert(f(10) ~= f(10))
809+print("+")
810+_G.TT={}
811+T.sethook(" # set a line hook after 3 count hooks
812+ sethook 4 0 '
813+ getglobal TT;
814+ pushvalue -3; append -2
815+ pushvalue -2; append -2
816+ '","c",3)
817+local a = 1
818+a=1
819+a=1
820+a=1
821+a=1
822+debug.sethook()
823+local t = _G.TT
824+assert(t[1] == "line")
825+local line = t[2]
826+assert(t[3] == "line" and t[4] == line + 1)
827+assert(t[5] == "line" and t[6] == line + 2)
828+assert(t[7] == nil)
829+_G.TT=nil
830+warn("@off")
831+collectgarbage("stop")
832+local a = {}
833+for i = 1, 20
834+do
835+a[i]=T.newuserdata(i)
836+end
837+for i = 1, 20, 2
838+do
839+debug.setmetatable(a[i],{["__gc"] = (x)
840+error("@expected error in gc")
841+end})
842+end
843+for i = 2, 20, 2
844+do
845+debug.setmetatable(a[i],{["__gc"] = (x)
846+load("A=A+1")()
847+end})
848+end
849+a=nil
850+_G.A=0
851+collectgarbage()
852+assert(A == 10)
853+collectgarbage("restart")
854+warn("@on")
855+_G.A=nil
856+local a = {}
857+;
858+local lim = 30
859+for i = 0, lim
860+do
861+a[i]=T.pushuserdata(i)
862+end
863+for i = 0, lim
864+do
865+assert(T.udataval(a[i]) == i)
866+end
867+for i = 0, lim
868+do
869+assert(T.pushuserdata(i) == a[i])
870+end
871+for i = 0, lim
872+do
873+a[a[i]]=i
874+end
875+for i = 0, lim
876+do
877+a[T.pushuserdata(i)]=i
878+end
879+assert(type(tostring(a[1])) == "string")
880+T.closestate(T.newstate())
881+;
882+L1=T.newstate()
883+assert(L1)
884+assert(T.doremote(L1,"X='a'; return 'a'") == "a")
885+assert(# pack(T.doremote(L1,"function f () return 'alo', 3 end; f()")) == 0)
886+a,b=T.doremote(L1,"return f()")
887+assert(a == "alo" and b == "3")
888+T.doremote(L1,"_ERRORMESSAGE = nil")
889+a,b,c=T.doremote(L1,"return sin(1)")
890+assert(a == nil and c == 2)
891+a,b,c=T.doremote(L1,"return a+")
892+assert(a == nil and c == 3 and type(b) == "string")
893+T.loadlib(L1)
894+a,b,c=T.doremote(L1," string = require'string'
895+ a = require'_G'; assert(a == _G and require("_G") == a)
896+ io = require'io'; assert(type(io.read) == "function")
897+ assert(require("io") == io)
898+ a = require'table'; assert(type(a.insert) == "function")
899+ a = require'debug'; assert(type(a.getlocal) == "function")
900+ a = require'math'; assert(type(a.sin) == "function")
901+ return string.sub('okinama', 1, 2)
902+")
903+assert(a == "ok")
904+T.closestate(L1)
905+;
906+L1=T.newstate()
907+T.loadlib(L1)
908+T.doremote(L1,"a = {}")
909+T.testC(L1,"getglobal "a"; pushstring "x"; pushint 1;
910+ settable -3")
911+assert(T.doremote(L1,"return a.x") == "1")
912+T.closestate(L1)
913+L1=nil
914+print("+")
915+print("testing to-be-closed variables")
916+local openresource = {}
917+local function newresource
918+()
919+local x = setmetatable({10},{["__close"] = (y)
920+assert(openresource[# openresource] == y)
921+openresource[# openresource]=nil
922+y[1]=y[1] + 1
923+end})
924+openresource[# openresource + 1]=x
925+return x
926+end
927+local a,b = T.testC(" call 0 1 # create resource
928+ pushnil
929+ toclose -2 # mark call result to be closed
930+ toclose -1 # mark nil to be closed (will be ignored)
931+ return 2
932+ ",newresource)
933+assert(a[1] == 11 and b == nil)
934+assert(# openresource == 0)
935+local a = {T.testC(" call 0 1 # create resource
936+ toclose 2 # mark it to be closed
937+ return 2
938+ ",newresource)}
939+assert(type(a[1]) == "string" and a[2][1] == 11)
940+assert(# openresource == 0)
941+local a,b = pcall(T.makeCfunc(" call 0 1 # create resource
942+ toclose -1 # mark it to be closed
943+ error # resource is the error object
944+ "),newresource)
945+assert(a == false and b[1] == 11)
946+assert(# openresource == 0)
947+local a,b = pcall(T.makeCfunc(" newtable # create non-closable object
948+ toclose -1 # mark it to be closed (should raise an error)
949+ abort # will not be executed
950+ "))
951+assert(a == false and string.find(b,"non%-closable value"))
952+local function check
953+(n)
954+assert(# openresource == n)
955+end
956+_ENV.xxx=true
957+local a = T.testC(" pushvalue 2 # stack: S, NR, CH, NR
958+ call 0 1 # create resource; stack: S, NR, CH, R
959+ toclose -1 # mark it to be closed
960+ pushvalue 2 # stack: S, NR, CH, R, NR
961+ call 0 1 # create another resource; stack: S, NR, CH, R, R
962+ toclose -1 # mark it to be closed
963+ pushvalue 3 # stack: S, NR, CH, R, R, CH
964+ pushint 2 # there should be two open resources
965+ call 1 0 # stack: S, NR, CH, R, R
966+ closeslot -1 # close second resource
967+ pushvalue 3 # stack: S, NR, CH, R, R, CH
968+ pushint 1 # there should be one open resource
969+ call 1 0 # stack: S, NR, CH, R, R
970+ closeslot 4
971+ setglobal "xxx" # previous op. erased the slot
972+ pop 1 # pop other resource from the stack
973+ pushint *
974+ return 1 # return stack size
975+ ",newresource,check)
976+assert(a == 3 and _ENV.xxx == nil)
977+local a = T.testC(" pushvalue 2 # stack: S, NR, CH, NR
978+ call 0 1 # create resource; stack: S, NR, CH, R
979+ toclose -1 # mark it to be closed
980+ pushvalue 2 # stack: S, NR, CH, R, NR
981+ call 0 1 # create another resource; stack: S, NR, CH, R, R
982+ toclose -1 # mark it to be closed
983+ pushvalue 3 # stack: S, NR, CH, R, R, CH
984+ pushint 2 # there should be two open resources
985+ call 1 0 # stack: S, NR, CH, R, R
986+ pop 1 # pop second resource
987+ pushvalue 3 # stack: S, NR, CH, R, CH
988+ pushint 1 # there should be one open resource
989+ call 1 0 # stack: S, NR, CH, R
990+ pop 1 # pop other resource from the stack
991+ pushvalue 3 # stack: S, NR, CH, CH
992+ pushint 0 # there should be no open resources
993+ call 1 0 # stack: S, NR, CH
994+ pushint *
995+ return 1 # return stack size
996+ ",newresource,check)
997+assert(a == 3)
998+local a,b = pcall(T.makeCfunc(" pushint 32
999+ toclose -1
1000+ "))
1001+assert(not a and string.find(b,"(C temporary)"))
1002+print("memory-allocation errors")
1003+checkerr("block too big",T.newuserdata,math.maxinteger)
1004+collectgarbage()
1005+local f = load("local a={}; for i=1,100000 do a[i]=i end")
1006+T.alloccount(10)
1007+checkerr(MEMERRMSG,f)
1008+T.alloccount()
1009+local function testbytes
1010+(s,f)
1011+collectgarbage()
1012+local M = T.totalmem()
1013+local oldM = M
1014+local a,b = nil
1015+while true do
1016+collectgarbage()
1017+;
1018+collectgarbage()
1019+T.totalmem(M)
1020+a,b=T.testC("pcall 0 1 0; pushstatus; return 2",f)
1021+T.totalmem(0)
1022+if a and b == "OK" then
1023+break
1024+end
1025+if b ~= "OK" and b ~= MEMERRMSG then
1026+error(a,0)
1027+end
1028+M=M + 7
1029+print(string.format("minimum memory for %s: %d bytes",s,M - oldM))
1030+return a
1031+end
1032+local function testalloc
1033+(s,f)
1034+collectgarbage()
1035+local M = 0
1036+local a,b = nil
1037+while true do
1038+collectgarbage()
1039+;
1040+collectgarbage()
1041+T.alloccount(M)
1042+a,b=T.testC("pcall 0 1 0; pushstatus; return 2",f)
1043+T.alloccount()
1044+if a and b == "OK" then
1045+break
1046+end
1047+if b ~= "OK" and b ~= MEMERRMSG then
1048+error(a,0)
1049+end
1050+M=M + 1
1051+print(string.format("minimum allocations for %s: %d allocations",s,M))
1052+return a
1053+end
1054+local function testamem
1055+(s,f)
1056+testalloc(s,f)
1057+return testbytes(s,f)
1058+end
1059+b=testamem("doing nothing",()
1060+return 10
1061+end)
1062+assert(b == 10)
1063+testamem("state creation",()
1064+local st = T.newstate()
1065+if st then
1066+T.closestate(st)
1067+end
1068+return st
1069+end)
1070+testamem("empty-table creation",()
1071+return {}
1072+end)
1073+testamem("string creation",()
1074+return "XXX" .. "YYY"
1075+end)
1076+testamem("coroutine creation",()
1077+return coroutine.create(print)
1078+end)
1079+testamem("to-be-closed variables",()
1080+local flag =
1081+local x <close> = setmetatable({},{["__close"] = ()
1082+flag=true
1083+end})
1084+flag=false
1085+local x = {}
1086+return flag
1087+end)
1088+local mt = T.testC("rawgeti R 1; return 1")
1089+assert(type(mt) == "thread" and coroutine.running() == mt)
1090+local function expand
1091+(n,s)
1092+if n == 0 then
1093+return ""
1094+end
1095+local e = string.rep("=",n)
1096+return string.format("T.doonnewstack([%s[ %s;
1097+ collectgarbage(); %s]%s])
1098+",e,s,expand(n - 1,s),e)
1099+end
1100+G=0
1101+;
1102+collectgarbage()
1103+;
1104+a=collectgarbage("count")
1105+load(expand(20,"G=G+1"))()
1106+assert(G == 20)
1107+;
1108+collectgarbage()
1109+;
1110+G=nil
1111+testamem("running code on new thread",()
1112+return T.doonnewstack("local x=1") == 0
1113+end)
1114+testamem("loadstring",()
1115+return load("x=1")
1116+end)
1117+local testprog = "local function foo () return end
1118+local t = {"x"}
1119+AA = "aaa"
1120+for i = 1, #t do AA = AA .. t[i] end
1121+return true
1122+"
1123+_G.AA=nil
1124+local t = os.tmpname()
1125+local f = assert(io.open(t,"w"))
1126+f:write(testprog)
1127+f:close()
1128+testamem("dofile",()
1129+local a = loadfile(t)
1130+return a and a()
1131+end)
1132+assert(os.remove(t))
1133+assert(_G.AA == "aaax")
1134+testamem("gsub",()
1135+local a,b = string.gsub("alo alo","(a)",(x)
1136+return x .. "b"
1137+end)
1138+return (a == "ablo ablo")
1139+end)
1140+testamem("dump/undump",()
1141+local a = load(testprog)
1142+local b = a and string.dump(a)
1143+a=b and load(b)
1144+return a and a()
1145+end)
1146+_G.AA=nil
1147+local t = os.tmpname()
1148+testamem("file creation",()
1149+local f = assert(io.open(t,"w"))
1150+assert(not io.open("nomenaoexistente"))
1151+io.close(f)
1152+;
1153+return not loadfile("nomenaoexistente")
1154+end)
1155+assert(os.remove(t))
1156+testamem("table creation",()
1157+local a,lim = {},10
1158+for i = 1, lim
1159+do
1160+a[i]=i
1161+;
1162+a[i .. "a"]={}
1163+end
1164+return (type(a[lim .. "a"]) == "table" and a[lim] == lim)
1165+end)
1166+testamem("constructors",()
1167+local a = {10,20,30,40,50,["a"] = 1,["b"] = 2,["c"] = 3,["d"] = 4,["e"] = 5}
1168+return (type(a) == "table" and a.e == 5)
1169+end)
1170+local a = 1
1171+local close = nil
1172+testamem("closure creation",()
1173+function close(b)
1174+return (x)
1175+return b + x
1176+end
1177+end
1178+return (close(2)(4) == 6)
1179+end)
1180+testamem("using coroutines",()
1181+local a = coroutine.wrap(()
1182+coroutine.yield(string.rep("a",10))
1183+return {}
1184+end)
1185+assert(string.len(a()) == 10)
1186+return a()
1187+end)
1188+local lim = 100
1189+local a = {}
1190+;
1191+for i = 1, lim
1192+do
1193+a[i]="01234567890123456789"
1194+end
1195+testamem("auxiliary buffer",()
1196+return (# table.concat(a,",") == 20 * lim + lim - 1)
1197+end)
1198+testamem("growing stack",()
1199+local function foo
1200+(n)
1201+if n == 0 then
1202+return 1
1203+else
1204+return 1 + foo(n - 1)
1205+end
1206+end
1207+return foo(100)
1208+end)
1209+local res = T.testC("rawcheckstack 500000; return 1")
1210+assert(res == false)
1211+local L = T.newstate()
1212+T.alloccount(0)
1213+res=T.testC(L,"rawcheckstack 5000; return 1")
1214+T.alloccount()
1215+T.closestate(L)
1216+assert(res == false)
1217+local L = T.newstate()
1218+T.alloccount(0)
1219+T.closestate(L)
1220+T.alloccount()
1221+local L = T.newstate()
1222+T.loadlib(L)
1223+local res = (T.doremote(L," _ENV = require"_G"
1224+ local T = require"T"
1225+ local a = {}
1226+ for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table
1227+ local stsize, stuse = T.querystr()
1228+ assert(stuse > 1000)
1229+ local function foo (n)
1230+ if n > 0 then foo(n - 1) end
1231+ end
1232+ foo(180) -- grow stack
1233+ local _, stksize = T.stacklevel()
1234+ assert(stksize > 180)
1235+ a = nil
1236+ T.alloccount(0)
1237+ collectgarbage()
1238+ T.alloccount()
1239+ -- stack and string table could not be reallocated,
1240+ -- so they kept their sizes (without errors)
1241+ assert(select(2, T.stacklevel()) == stksize)
1242+ assert(T.querystr() == stsize)
1243+ return 'ok'
1244+ "))
1245+assert(res == "ok")
1246+T.closestate(L)
1247+print("+")
1248+local function gsub
1249+(a,b,c)
1250+a,b=T.testC("gsub 2 3 4; gettop; return 2",a,b,c)
1251+assert(b == 5)
1252+return a
1253+end
1254+assert(gsub("alo.alo.uhuh.",".","//") == "alo//alo//uhuh//")
1255+assert(gsub("alo.alo.uhuh.","alo","//") == "//.//.uhuh.")
1256+assert(gsub("","alo","//") == "")
1257+assert(gsub("...",".","/.") == "/././.")
1258+assert(gsub("...","...","") == "")
1259+local mt_xuxu,res,top = T.testC("newmetatable xuxu; gettop; return 3")
1260+assert(type(mt_xuxu) == "table" and res and top == 3)
1261+local d,res,top = T.testC("newmetatable xuxu; gettop; return 3")
1262+assert(mt_xuxu == d and not res and top == 3)
1263+d,res,top=T.testC("newmetatable xuxu1; gettop; return 3")
1264+assert(mt_xuxu ~= d and res and top == 3)
1265+x=T.newuserdata(0)
1266+;
1267+y=T.newuserdata(0)
1268+;
1269+T.testC("pushstring xuxu; gettable R; setmetatable 2",x)
1270+assert(getmetatable(x) == mt_xuxu)
1271+local res1,res2,top = T.testC("testudata -1 xuxu
1272+ testudata 2 xuxu
1273+ gettop
1274+ return 3",x)
1275+assert(res1 and res2 and top == 4)
1276+res1,res2,top=T.testC("testudata -1 xuxu1
1277+ testudata 2 xuxu1
1278+ gettop
1279+ return 3",x)
1280+assert(not res1 and not res2 and top == 4)
1281+res1,res2,top=T.testC("testudata -1 xuxu2
1282+ testudata 2 xuxu2
1283+ gettop
1284+ return 3",x)
1285+assert(not res1 and not res2 and top == 4)
1286+res1,res2,top=T.testC("testudata -1 xuxu
1287+ testudata 2 xuxu
1288+ gettop
1289+ return 3",y)
1290+assert(not res1 and not res2 and top == 4)
1291+local r = debug.getregistry()
1292+assert(r.xuxu == mt_xuxu and r.xuxu1 == d)
1293+r.xuxu=nil
1294+;
1295+r.xuxu1=nil
1296+print("OK")