Avoid excessive name pollution in test files

Test files are more polite regarding the use of globals when locals
would do, and when globals are necessary deleting them after use.
This commit is contained in:
Roberto Ierusalimschy 2022-12-28 18:34:11 -03:00
parent 0825cf237d
commit 314745ed84
26 changed files with 333 additions and 259 deletions

View File

@ -163,6 +163,7 @@ f()
dofile('db.lua') dofile('db.lua')
assert(dofile('calls.lua') == deep and deep) assert(dofile('calls.lua') == deep and deep)
_G.deep = nil
olddofile('strings.lua') olddofile('strings.lua')
olddofile('literals.lua') olddofile('literals.lua')
dofile('tpack.lua') dofile('tpack.lua')

View File

@ -14,7 +14,7 @@ local pack = table.pack
-- standard error message for memory errors -- standard error message for memory errors
local MEMERRMSG = "not enough memory" local MEMERRMSG = "not enough memory"
function tcheck (t1, t2) local function tcheck (t1, t2)
assert(t1.n == (t2.n or #t2) + 1) assert(t1.n == (t2.n or #t2) + 1)
for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end
end end
@ -28,7 +28,7 @@ end
print('testing C API') print('testing C API')
a = T.testC("pushvalue R; return 1") local a = T.testC("pushvalue R; return 1")
assert(a == debug.getregistry()) assert(a == debug.getregistry())
@ -43,10 +43,10 @@ a = T.d2s(12458954321123.0)
assert(a == string.pack("d", 12458954321123.0)) assert(a == string.pack("d", 12458954321123.0))
assert(T.s2d(a) == 12458954321123.0) assert(T.s2d(a) == 12458954321123.0)
a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2") local a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
assert(a == 2 and b == 3 and not c) assert(a == 2 and b == 3 and not c)
f = T.makeCfunc("pushnum 1; pushnum 2; pushnum 3; return 2") local f = T.makeCfunc("pushnum 1; pushnum 2; pushnum 3; return 2")
a,b,c = f() a,b,c = f()
assert(a == 2 and b == 3 and not c) assert(a == 2 and b == 3 and not c)
@ -61,7 +61,7 @@ assert(a==false and b==true and c==false)
a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40) a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
assert(a == 40 and b == 5 and not c) assert(a == 40 and b == 5 and not c)
t = pack(T.testC("settop 5; return *", 2, 3)) local t = pack(T.testC("settop 5; return *", 2, 3))
tcheck(t, {n=4,2,3}) tcheck(t, {n=4,2,3})
t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23)) t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
@ -166,16 +166,17 @@ end
-- testing globals -- testing globals
_G.a = 14; _G.b = "a31" _G.AA = 14; _G.BB = "a31"
local a = {T.testC[[ local a = {T.testC[[
getglobal a; getglobal AA;
getglobal b; getglobal BB;
getglobal b; getglobal BB;
setglobal a; setglobal AA;
return * return *
]]} ]]}
assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.a == "a31") assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.AA == "a31")
_G.AA, _G.BB = nil
-- testing arith -- testing arith
assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5) assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5)
@ -199,13 +200,14 @@ a,b,c = T.testC([[pushnum 1;
pushstring 10; arith _; pushstring 10; arith _;
pushstring 5; return 3]]) pushstring 5; return 3]])
assert(a == 1 and b == -10 and c == "5") assert(a == 1 and b == -10 and c == "5")
mt = {__add = function (a,b) return setmetatable({a[1] + b[1]}, mt) end, local mt = {
__add = function (a,b) return setmetatable({a[1] + b[1]}, mt) end,
__mod = function (a,b) return setmetatable({a[1] % b[1]}, mt) end, __mod = function (a,b) return setmetatable({a[1] % b[1]}, mt) end,
__unm = function (a) return setmetatable({a[1]* 2}, mt) end} __unm = function (a) return setmetatable({a[1]* 2}, mt) end}
a,b,c = setmetatable({4}, mt), a,b,c = setmetatable({4}, mt),
setmetatable({8}, mt), setmetatable({8}, mt),
setmetatable({-3}, mt) setmetatable({-3}, mt)
x,y,z = T.testC("arith +; return 2", 10, a, b) local x,y,z = T.testC("arith +; return 2", 10, a, b)
assert(x == 10 and y[1] == 12 and z == nil) assert(x == 10 and y[1] == 12 and z == nil)
assert(T.testC("arith %; return 1", a, c)[1] == 4%-3) assert(T.testC("arith %; return 1", a, c)[1] == 4%-3)
assert(T.testC("arith _; arith +; arith %; return 1", b, a, c)[1] == assert(T.testC("arith _; arith +; arith %; return 1", b, a, c)[1] ==
@ -312,9 +314,9 @@ assert(T.testC("concat 1; return 1", "xuxu") == "xuxu")
-- testing lua_is -- testing lua_is
function B(x) return x and 1 or 0 end local function B (x) return x and 1 or 0 end
function count (x, n) local function count (x, n)
n = n or 2 n = n or 2
local prog = [[ local prog = [[
isnumber %d; isnumber %d;
@ -345,7 +347,7 @@ assert(count(nil, 15) == 100)
-- testing lua_to... -- testing lua_to...
function to (s, x, n) local function to (s, x, n)
n = n or 2 n = n or 2
return T.testC(string.format("%s %d; return 1", s, n), x) return T.testC(string.format("%s %d; return 1", s, n), x)
end end
@ -486,11 +488,12 @@ a = T.testC([[
pushvalue 3; insert -2; pcall 1 1 0; pushvalue 3; insert -2; pcall 1 1 0;
pcall 0 0 0; pcall 0 0 0;
return 1 return 1
]], "x=150", function (a) assert(a==nil); return 3 end) ]], "XX=150", function (a) assert(a==nil); return 3 end)
assert(type(a) == 'string' and x == 150) assert(type(a) == 'string' and XX == 150)
_G.XX = nil
function check3(p, ...) local function check3(p, ...)
local arg = {...} local arg = {...}
assert(#arg == 3) assert(#arg == 3)
assert(string.find(arg[3], p)) assert(string.find(arg[3], p))
@ -500,7 +503,7 @@ check3("%.", T.testC("loadfile 2; return *", "."))
check3("xxxx", T.testC("loadfile 2; return *", "xxxx")) check3("xxxx", T.testC("loadfile 2; return *", "xxxx"))
-- test errors in non protected threads -- test errors in non protected threads
function checkerrnopro (code, msg) local function checkerrnopro (code, msg)
local th = coroutine.create(function () end) -- create new thread local th = coroutine.create(function () end) -- create new thread
local stt, err = pcall(T.testC, th, code) -- run code there local stt, err = pcall(T.testC, th, code) -- run code there
assert(not stt and string.find(err, msg)) assert(not stt and string.find(err, msg))
@ -510,8 +513,9 @@ if not _soft then
collectgarbage("stop") -- avoid __gc with full stack collectgarbage("stop") -- avoid __gc with full stack
checkerrnopro("pushnum 3; call 0 0", "attempt to call") checkerrnopro("pushnum 3; call 0 0", "attempt to call")
print"testing stack overflow in unprotected thread" print"testing stack overflow in unprotected thread"
function f () f() end function F () F() end
checkerrnopro("getglobal 'f'; call 0 0;", "stack overflow") checkerrnopro("getglobal 'F'; call 0 0;", "stack overflow")
F = nil
collectgarbage("restart") collectgarbage("restart")
end end
print"+" print"+"
@ -588,7 +592,7 @@ assert(a[a] == "x")
b = setmetatable({p = a}, {}) b = setmetatable({p = a}, {})
getmetatable(b).__index = function (t, i) return t.p[i] end getmetatable(b).__index = function (t, i) return t.p[i] end
k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x") local k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
assert(x == 15 and k == 35) assert(x == 15 and k == 35)
k = T.testC("getfield 2 y, return 1", b) k = T.testC("getfield 2 y, return 1", b)
assert(k == 12) assert(k == 12)
@ -748,8 +752,8 @@ local i = T.ref{}
T.unref(i) T.unref(i)
assert(T.ref{} == i) assert(T.ref{} == i)
Arr = {} local Arr = {}
Lim = 100 local Lim = 100
for i=1,Lim do -- lock many objects for i=1,Lim do -- lock many objects
Arr[i] = T.ref({}) Arr[i] = T.ref({})
end end
@ -761,7 +765,7 @@ for i=1,Lim do -- unlock all them
T.unref(Arr[i]) T.unref(Arr[i])
end end
function printlocks () local function printlocks ()
local f = T.makeCfunc("gettable R; return 1") local f = T.makeCfunc("gettable R; return 1")
local n = f("n") local n = f("n")
print("n", n) print("n", n)
@ -793,8 +797,8 @@ assert(type(T.getref(a)) == 'table')
-- colect in cl the `val' of all collected userdata -- colect in cl the `val' of all collected userdata
tt = {} local tt = {}
cl = {n=0} local cl = {n=0}
A = nil; B = nil A = nil; B = nil
local F local F
F = function (x) F = function (x)
@ -817,6 +821,7 @@ F = function (x)
end end
tt.__gc = F tt.__gc = F
-- test whether udate collection frees memory in the right time -- test whether udate collection frees memory in the right time
do do
collectgarbage(); collectgarbage();
@ -853,9 +858,9 @@ end
collectgarbage("stop") collectgarbage("stop")
-- create 3 userdatas with tag `tt' -- create 3 userdatas with tag `tt'
a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a) a = T.newuserdata(0); debug.setmetatable(a, tt); local na = T.udataval(a)
b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b) b = T.newuserdata(0); debug.setmetatable(b, tt); local nb = T.udataval(b)
c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c) c = T.newuserdata(0); debug.setmetatable(c, tt); local nc = T.udataval(c)
-- create userdata without meta table -- create userdata without meta table
x = T.newuserdata(4) x = T.newuserdata(4)
@ -866,9 +871,9 @@ checkerr("FILE%* expected, got userdata", io.input, x)
assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil) assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
d=T.ref(a); local d = T.ref(a);
e=T.ref(b); local e = T.ref(b);
f=T.ref(c); local f = T.ref(c);
t = {T.getref(d), T.getref(e), T.getref(f)} t = {T.getref(d), T.getref(e), T.getref(f)}
assert(t[1] == a and t[2] == b and t[3] == c) assert(t[1] == a and t[2] == b and t[3] == c)
@ -888,7 +893,7 @@ tt=nil -- frees tt for GC
A = nil A = nil
b = nil b = nil
T.unref(d); T.unref(d);
n5 = T.newuserdata(0) local n5 = T.newuserdata(0)
debug.setmetatable(n5, {__gc=F}) debug.setmetatable(n5, {__gc=F})
n5 = T.udataval(n5) n5 = T.udataval(n5)
collectgarbage() collectgarbage()
@ -959,11 +964,11 @@ print'+'
-- testing changing hooks during hooks -- testing changing hooks during hooks
_G.t = {} _G.TT = {}
T.sethook([[ T.sethook([[
# set a line hook after 3 count hooks # set a line hook after 3 count hooks
sethook 4 0 ' sethook 4 0 '
getglobal t; getglobal TT;
pushvalue -3; append -2 pushvalue -3; append -2
pushvalue -2; append -2 pushvalue -2; append -2
']], "c", 3) ']], "c", 3)
@ -973,12 +978,13 @@ a = 1 -- count hook (set line hook)
a = 1 -- line hook a = 1 -- line hook
a = 1 -- line hook a = 1 -- line hook
debug.sethook() debug.sethook()
t = _G.t local t = _G.TT
assert(t[1] == "line") assert(t[1] == "line")
line = t[2] local line = t[2]
assert(t[3] == "line" and t[4] == line + 1) assert(t[3] == "line" and t[4] == line + 1)
assert(t[5] == "line" and t[6] == line + 2) assert(t[5] == "line" and t[6] == line + 2)
assert(t[7] == nil) assert(t[7] == nil)
_G.TT = nil
------------------------------------------------------------------------- -------------------------------------------------------------------------
@ -1003,6 +1009,7 @@ do -- testing errors during GC
collectgarbage("restart") collectgarbage("restart")
warn("@on") warn("@on")
end end
_G.A = nil
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- test for userdata vals -- test for userdata vals
do do
@ -1032,8 +1039,8 @@ assert(a == 'alo' and b == '3')
T.doremote(L1, "_ERRORMESSAGE = nil") T.doremote(L1, "_ERRORMESSAGE = nil")
-- error: `sin' is not defined -- error: `sin' is not defined
a, _, b = T.doremote(L1, "return sin(1)") a, b, c = T.doremote(L1, "return sin(1)")
assert(a == nil and b == 2) -- 2 == run-time error assert(a == nil and c == 2) -- 2 == run-time error
-- error: syntax error -- error: syntax error
a, b, c = T.doremote(L1, "return a+") a, b, c = T.doremote(L1, "return a+")
@ -1204,7 +1211,7 @@ T.alloccount() -- remove limit
-- o that we get memory errors in all allocations of a given -- o that we get memory errors in all allocations of a given
-- task, until there is enough memory to complete the task without -- task, until there is enough memory to complete the task without
-- errors. -- errors.
function testbytes (s, f) local function testbytes (s, f)
collectgarbage() collectgarbage()
local M = T.totalmem() local M = T.totalmem()
local oldM = M local oldM = M
@ -1229,7 +1236,7 @@ end
-- task, until there is enough allocations to complete the task without -- task, until there is enough allocations to complete the task without
-- errors. -- errors.
function testalloc (s, f) local function testalloc (s, f)
collectgarbage() collectgarbage()
local M = 0 local M = 0
local a,b = nil local a,b = nil
@ -1296,12 +1303,12 @@ end)
-- testing threads -- testing threads
-- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1) -- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1)
mt = T.testC("rawgeti R 1; return 1") local mt = T.testC("rawgeti R 1; return 1")
assert(type(mt) == "thread" and coroutine.running() == mt) assert(type(mt) == "thread" and coroutine.running() == mt)
function expand (n,s) local function expand (n,s)
if n==0 then return "" end if n==0 then return "" end
local e = string.rep("=", n) local e = string.rep("=", n)
return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n", return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
@ -1311,9 +1318,10 @@ end
G=0; collectgarbage(); a =collectgarbage("count") G=0; collectgarbage(); a =collectgarbage("count")
load(expand(20,"G=G+1"))() load(expand(20,"G=G+1"))()
assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1) assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
G = nil
testamem("running code on new thread", function () testamem("running code on new thread", function ()
return T.doonnewstack("x=1") == 0 -- try to create thread return T.doonnewstack("local x=1") == 0 -- try to create thread
end) end)
@ -1327,13 +1335,13 @@ end)
local testprog = [[ local testprog = [[
local function foo () return end local function foo () return end
local t = {"x"} local t = {"x"}
a = "aaa" AA = "aaa"
for i = 1, #t do a=a..t[i] end for i = 1, #t do AA = AA .. t[i] end
return true return true
]] ]]
-- testing memory x dofile -- testing memory x dofile
_G.a = nil _G.AA = nil
local t =os.tmpname() local t =os.tmpname()
local f = assert(io.open(t, "w")) local f = assert(io.open(t, "w"))
f:write(testprog) f:write(testprog)
@ -1343,7 +1351,7 @@ testamem("dofile", function ()
return a and a() return a and a()
end) end)
assert(os.remove(t)) assert(os.remove(t))
assert(_G.a == "aaax") assert(_G.AA == "aaax")
-- other generic tests -- other generic tests
@ -1360,6 +1368,8 @@ testamem("dump/undump", function ()
return a and a() return a and a()
end) end)
_G.AA = nil
local t = os.tmpname() local t = os.tmpname()
testamem("file creation", function () testamem("file creation", function ()
local f = assert(io.open(t, 'w')) local f = assert(io.open(t, 'w'))
@ -1381,7 +1391,7 @@ testamem("constructors", function ()
end) end)
local a = 1 local a = 1
close = nil local close = nil
testamem("closure creation", function () testamem("closure creation", function ()
function close (b) function close (b)
return function (x) return b + x end return function (x) return b + x end

View File

@ -85,7 +85,7 @@ local DIR = "libs" .. dirsep
-- prepend DIR to a name and correct directory separators -- prepend DIR to a name and correct directory separators
local function D (x) local function D (x)
x = string.gsub(x, "/", dirsep) local x = string.gsub(x, "/", dirsep)
return DIR .. x return DIR .. x
end end
@ -106,7 +106,7 @@ local function createfiles (files, preextras, posextras)
end end
end end
function removefiles (files) local function removefiles (files)
for n in pairs(files) do for n in pairs(files) do
os.remove(D(n)) os.remove(D(n))
end end
@ -154,10 +154,9 @@ local try = function (p, n, r, ext)
assert(ext == x) assert(ext == x)
end end
a = require"names" local a = require"names"
assert(a[1] == "names" and a[2] == D"names.lua") assert(a[1] == "names" and a[2] == D"names.lua")
_G.a = nil
local st, msg = pcall(require, "err") local st, msg = pcall(require, "err")
assert(not st and string.find(msg, "arithmetic") and B == 15) assert(not st and string.find(msg, "arithmetic") and B == 15)
st, msg = pcall(require, "synerr") st, msg = pcall(require, "synerr")
@ -191,6 +190,7 @@ try("X", "XXxX", AA, "libs/XXxX")
removefiles(files) removefiles(files)
NAME, REQUIRED, AA, B = nil
-- testing require of sub-packages -- testing require of sub-packages
@ -223,7 +223,7 @@ assert(require"P1" == m and m.AA == 10)
removefiles(files) removefiles(files)
AA = nil
package.path = "" package.path = ""
assert(not pcall(require, "file_does_not_exist")) assert(not pcall(require, "file_does_not_exist"))
@ -305,6 +305,7 @@ else
assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1") assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1")
assert(string.find(ext, "libs/lib1", 1, true)) assert(string.find(ext, "libs/lib1", 1, true))
assert(fs.id(45) == 45) assert(fs.id(45) == 45)
_ENV.x, _ENV.y = nil
end end
_ENV = _G _ENV = _G
@ -338,10 +339,10 @@ print("testing assignments, logical operators, and constructors")
local res, res2 = 27 local res, res2 = 27
a, b = 1, 2+3 local a, b = 1, 2+3
assert(a==1 and b==5) assert(a==1 and b==5)
a={} a={}
function f() return 10, 11, 12 end local function f() return 10, 11, 12 end
a.x, b, a[1] = 1, 2, f() a.x, b, a[1] = 1, 2, f()
assert(a.x==1 and b==2 and a[1]==10) assert(a.x==1 and b==2 and a[1]==10)
a[f()], b, a[f()+3] = f(), a, 'x' a[f()], b, a[f()+3] = f(), a, 'x'
@ -353,15 +354,15 @@ do
local a,b,c local a,b,c
a,b = 0, f(1) a,b = 0, f(1)
assert(a == 0 and b == 1) assert(a == 0 and b == 1)
A,b = 0, f(1) a,b = 0, f(1)
assert(A == 0 and b == 1) assert(a == 0 and b == 1)
a,b,c = 0,5,f(4) a,b,c = 0,5,f(4)
assert(a==0 and b==5 and c==1) assert(a==0 and b==5 and c==1)
a,b,c = 0,5,f(0) a,b,c = 0,5,f(0)
assert(a==0 and b==5 and c==nil) assert(a==0 and b==5 and c==nil)
end end
a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6 local a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
assert(not a and b and c and d==6) assert(not a and b and c and d==6)
d = 20 d = 20
@ -419,6 +420,7 @@ assert(not pcall(function () local a = {[nil] = 10} end))
assert(a[nil] == undef) assert(a[nil] == undef)
a = nil a = nil
local a, b, c
a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'} a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
a, a.x, a.y = a, a[-3] a, a.x, a.y = a, a[-3]
assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y) assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
@ -455,7 +457,7 @@ while maxint ~= (maxint + 0.0) or (maxint - 1) ~= (maxint - 1.0) do
maxint = maxint // 2 maxint = maxint // 2
end end
maxintF = maxint + 0.0 -- float version local maxintF = maxint + 0.0 -- float version
assert(maxintF == maxint and math.type(maxintF) == "float" and assert(maxintF == maxint and math.type(maxintF) == "float" and
maxintF >= 2.0^14) maxintF >= 2.0^14)

View File

@ -32,7 +32,7 @@ setmetatable(env, {
}) })
X = nil X = nil
co = coroutine.wrap(f) local co = coroutine.wrap(f)
assert(co() == 's') assert(co() == 's')
assert(co() == 'g') assert(co() == 'g')
assert(co() == 'g') assert(co() == 'g')

View File

@ -16,7 +16,7 @@ assert(type(nil) == 'nil'
and type(type) == 'function') and type(type) == 'function')
assert(type(assert) == type(print)) assert(type(assert) == type(print))
function f (x) return a:x (x) end local function f (x) return a:x (x) end
assert(type(f) == 'function') assert(type(f) == 'function')
assert(not pcall(type)) assert(not pcall(type))
@ -33,10 +33,11 @@ do
assert(fact(5) == 120) assert(fact(5) == 120)
end end
assert(fact == false) assert(fact == false)
fact = nil
-- testing declarations -- testing declarations
a = {i = 10} local a = {i = 10}
self = 20 local self = 20
function a:x (x) return x+self.i end function a:x (x) return x+self.i end
function a.y (x) return x+self end function a.y (x) return x+self end
@ -72,6 +73,8 @@ f(1,2, -- this one too
3,4) 3,4)
assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a') assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
t = nil -- delete 't'
function fat(x) function fat(x)
if x <= 1 then return 1 if x <= 1 then return 1
else return x*load("return fat(" .. x-1 .. ")", "")() else return x*load("return fat(" .. x-1 .. ")", "")()
@ -80,26 +83,29 @@ end
assert(load "load 'assert(fat(6)==720)' () ")() assert(load "load 'assert(fat(6)==720)' () ")()
a = load('return fat(5), 3') a = load('return fat(5), 3')
a,b = a() local a,b = a()
assert(a == 120 and b == 3) assert(a == 120 and b == 3)
fat = nil
print('+') print('+')
function err_on_n (n) local function err_on_n (n)
if n==0 then error(); exit(1); if n==0 then error(); exit(1);
else err_on_n (n-1); exit(1); else err_on_n (n-1); exit(1);
end end
end end
do do
function dummy (n) local function dummy (n)
if n > 0 then if n > 0 then
assert(not pcall(err_on_n, n)) assert(not pcall(err_on_n, n))
dummy(n-1) dummy(n-1)
end end
end end
dummy(10)
end end
dummy(10) _G.deep = nil -- "declaration" (used by 'all.lua')
function deep (n) function deep (n)
if n>0 then deep(n-1) end if n>0 then deep(n-1) end
@ -209,7 +215,7 @@ assert(a == 23 and (function (x) return x*2 end)(20) == 40)
-- testing closures -- testing closures
-- fixed-point operator -- fixed-point operator
Z = function (le) local Z = function (le)
local function a (f) local function a (f)
return le(function (x) return f(f)(x) end) return le(function (x) return f(f)(x) end)
end end
@ -219,14 +225,14 @@ Z = function (le)
-- non-recursive factorial -- non-recursive factorial
F = function (f) local F = function (f)
return function (n) return function (n)
if n == 0 then return 1 if n == 0 then return 1
else return n*f(n-1) end else return n*f(n-1) end
end end
end end
fat = Z(F) local fat = Z(F)
assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4)) assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4))
@ -237,22 +243,21 @@ local function g (z)
return f(z,z+1,z+2,z+3) return f(z,z+1,z+2,z+3)
end end
f = g(10) local f = g(10)
assert(f(9, 16) == 10+11+12+13+10+9+16+10) assert(f(9, 16) == 10+11+12+13+10+9+16+10)
Z, F, f = nil
print('+') print('+')
-- testing multiple returns -- testing multiple returns
function unlpack (t, i) local function unlpack (t, i)
i = i or 1 i = i or 1
if (i <= #t) then if (i <= #t) then
return t[i], unlpack(t, i+1) return t[i], unlpack(t, i+1)
end end
end end
function equaltab (t1, t2) local function equaltab (t1, t2)
assert(#t1 == #t2) assert(#t1 == #t2)
for i = 1, #t1 do for i = 1, #t1 do
assert(t1[i] == t2[i]) assert(t1[i] == t2[i])
@ -261,8 +266,8 @@ end
local pack = function (...) return (table.pack(...)) end local pack = function (...) return (table.pack(...)) end
function f() return 1,2,30,4 end local function f() return 1,2,30,4 end
function ret2 (a,b) return a,b end local function ret2 (a,b) return a,b end
local a,b,c,d = unlpack{1,2,3} local a,b,c,d = unlpack{1,2,3}
assert(a==1 and b==2 and c==3 and d==nil) assert(a==1 and b==2 and c==3 and d==nil)
@ -291,7 +296,7 @@ table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
local x = "-- a comment\0\0\0\n x = 10 + \n23; \ local x = "-- a comment\0\0\0\n x = 10 + \n23; \
local a = function () x = 'hi' end; \ local a = function () x = 'hi' end; \
return '\0'" return '\0'"
function read1 (x) local function read1 (x)
local i = 0 local i = 0
return function () return function ()
collectgarbage() collectgarbage()
@ -300,7 +305,7 @@ function read1 (x)
end end
end end
function cannotload (msg, a,b) local function cannotload (msg, a,b)
assert(not a and string.find(b, msg)) assert(not a and string.find(b, msg))
end end
@ -342,6 +347,7 @@ a = assert(load(read1(x), nil, "b"))
assert(a() == 1 and _G.x == 1) assert(a() == 1 and _G.x == 1)
cannotload("attempt to load a binary chunk", load(read1(x), nil, "t")) cannotload("attempt to load a binary chunk", load(read1(x), nil, "t"))
cannotload("attempt to load a binary chunk", load(x, nil, "t")) cannotload("attempt to load a binary chunk", load(x, nil, "t"))
_G.x = nil
assert(not pcall(string.dump, print)) -- no dump of C functions assert(not pcall(string.dump, print)) -- no dump of C functions
@ -366,7 +372,7 @@ debug.setupvalue(x, 2, _G)
assert(x() == 123) assert(x() == 123)
assert(assert(load("return XX + ...", nil, nil, {XX = 13}))(4) == 17) assert(assert(load("return XX + ...", nil, nil, {XX = 13}))(4) == 17)
XX = nil
-- test generic load with nested functions -- test generic load with nested functions
x = [[ x = [[

View File

@ -4,7 +4,7 @@
print "testing closures" print "testing closures"
local A,B = 0,{g=10} local A,B = 0,{g=10}
function f(x) local function f(x)
local a = {} local a = {}
for i=1,1000 do for i=1,1000 do
local y = 0 local y = 0
@ -89,6 +89,7 @@ assert(r == "a" and s == "b")
-- testing closures with 'for' control variable x break -- testing closures with 'for' control variable x break
local f
for i=1,3 do for i=1,3 do
f = function () return i end f = function () return i end
break break
@ -139,7 +140,7 @@ assert(b('get') == 'xuxu')
b('set', 10); assert(b('get') == 14) b('set', 10); assert(b('get') == 14)
local w local y, w
-- testing multi-level closure -- testing multi-level closure
function f(x) function f(x)
return function (y) return function (y)
@ -230,6 +231,7 @@ t()
-- test for debug manipulation of upvalues -- test for debug manipulation of upvalues
local debug = require'debug' local debug = require'debug'
local foo1, foo2, foo3
do do
local a , b, c = 3, 5, 7 local a , b, c = 3, 5, 7
foo1 = function () return a+b end; foo1 = function () return a+b end;

View File

@ -86,7 +86,7 @@ checkKlist(foo, {1, 1.0, 2, 2.0, 0, 0.0})
-- testing opcodes -- testing opcodes
-- check that 'f' opcodes match '...' -- check that 'f' opcodes match '...'
function check (f, ...) local function check (f, ...)
local arg = {...} local arg = {...}
local c = T.listcode(f) local c = T.listcode(f)
for i=1, #arg do for i=1, #arg do
@ -99,7 +99,7 @@ end
-- check that 'f' opcodes match '...' and that 'f(p) == r'. -- check that 'f' opcodes match '...' and that 'f(p) == r'.
function checkR (f, p, r, ...) local function checkR (f, p, r, ...)
local r1 = f(p) local r1 = f(p)
assert(r == r1 and math.type(r) == math.type(r1)) assert(r == r1 and math.type(r) == math.type(r1))
check(f, ...) check(f, ...)
@ -107,7 +107,7 @@ end
-- check that 'a' and 'b' has the same opcodes -- check that 'a' and 'b' has the same opcodes
function checkequal (a, b) local function checkequal (a, b)
a = T.listcode(a) a = T.listcode(a)
b = T.listcode(b) b = T.listcode(b)
assert(#a == #b) assert(#a == #b)

View File

@ -11,6 +11,7 @@ local function checkload (s, msg)
end end
-- testing semicollons -- testing semicollons
local a
do ;;; end do ;;; end
; do ; a = 3; assert(a == 3) end; ; do ; a = 3; assert(a == 3) end;
; ;
@ -49,10 +50,10 @@ assert((((nil and true) or false) and true) == false)
local a,b = 1,nil; local a,b = 1,nil;
assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75); assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x); local x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x); x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
x,y=1,2; local x, y = 1, 2;
assert((x>y) and x or y == 2); assert((x>y) and x or y == 2);
x,y=2,1; x,y=2,1;
assert((x>y) and x or y == 2); assert((x>y) and x or y == 2);
@ -77,13 +78,13 @@ do -- testing operators with diffent kinds of constants
local gab = f(o1, o2) local gab = f(o1, o2)
_ENV.XX = o1 _ENV.XX = o1
code = string.format("return XX %s %s", op, o2) local code = string.format("return XX %s %s", op, o2)
res = assert(load(code))() local res = assert(load(code))()
assert(res == gab) assert(res == gab)
_ENV.XX = o2 _ENV.XX = o2
local code = string.format("return (%s) %s XX", o1, op) code = string.format("return (%s) %s XX", o1, op)
local res = assert(load(code))() res = assert(load(code))()
assert(res == gab) assert(res == gab)
code = string.format("return (%s) %s %s", o1, op, o2) code = string.format("return (%s) %s %s", o1, op, o2)
@ -92,6 +93,7 @@ do -- testing operators with diffent kinds of constants
end end
end end
end end
_ENV.XX = nil
end end
@ -100,7 +102,7 @@ repeat until 1; repeat until true;
while false do end; while nil do end; while false do end; while nil do end;
do -- test old bug (first name could not be an `upvalue') do -- test old bug (first name could not be an `upvalue')
local a; function f(x) x={a=1}; x={x=1}; x={G=1} end local a; local function f(x) x={a=1}; x={x=1}; x={G=1} end
end end
@ -128,7 +130,7 @@ do -- bug since 5.4.0
end end
function f (i) local function f (i)
if type(i) ~= 'number' then return i,'jojo'; end; if type(i) ~= 'number' then return i,'jojo'; end;
if i > 0 then return i, f(i-1); end; if i > 0 then return i, f(i-1); end;
end end
@ -154,10 +156,10 @@ end
assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil) assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
for i=1,1000 do break; end; for i=1,1000 do break; end;
n=100; local n=100;
i=3; local i=3;
t = {}; local t = {};
a=nil local a=nil
while not a do while not a do
a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end; a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
end end
@ -200,14 +202,14 @@ a={y=1}
x = {a.y} x = {a.y}
assert(x[1] == 1) assert(x[1] == 1)
function f(i) local function f (i)
while 1 do while 1 do
if i>0 then i=i-1; if i>0 then i=i-1;
else return; end; else return; end;
end; end;
end; end;
function g(i) local function g(i)
while 1 do while 1 do
if i>0 then i=i-1 if i>0 then i=i-1
else return end else return end
@ -272,7 +274,7 @@ function g (a,b,c,d,e)
if not (a>=b or c or d and e or nil) then return 0; else return 1; end; if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
end end
function h (a,b,c,d,e) local function h (a,b,c,d,e)
while (a>=b or c or (d and e) or nil) do return 1; end; while (a>=b or c or (d and e) or nil) do return 1; end;
return 0; return 0;
end; end;
@ -300,7 +302,7 @@ do
assert(a==2) assert(a==2)
end end
function F(a) local function F (a)
assert(debug.getinfo(1, "n").name == 'F') assert(debug.getinfo(1, "n").name == 'F')
return a,2,3 return a,2,3
end end
@ -393,6 +395,8 @@ for n = 1, level do
if i % 60000 == 0 then print('+') end if i % 60000 == 0 then print('+') end
end end
end end
IX = nil
_G.GLOB1 = nil
------------------------------------------------------------------ ------------------------------------------------------------------
-- testing some syntax errors (chosen through 'gcov') -- testing some syntax errors (chosen through 'gcov')

View File

@ -30,7 +30,8 @@ local function eqtab (t1, t2)
end end
_G.x = nil -- declare x _G.x = nil -- declare x
function foo (a, ...) _G.f = nil -- declare f
local function foo (a, ...)
local x, y = coroutine.running() local x, y = coroutine.running()
assert(x == f and y == false) assert(x == f and y == false)
-- next call should not corrupt coroutine (but must fail, -- next call should not corrupt coroutine (but must fail,
@ -67,10 +68,11 @@ assert(coroutine.status(f) == "dead")
s, a = coroutine.resume(f, "xuxu") s, a = coroutine.resume(f, "xuxu")
assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead") assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
_G.f = nil
-- yields in tail calls -- yields in tail calls
local function foo (i) return coroutine.yield(i) end local function foo (i) return coroutine.yield(i) end
f = coroutine.wrap(function () local f = coroutine.wrap(function ()
for i=1,10 do for i=1,10 do
assert(foo(i) == _G.x) assert(foo(i) == _G.x)
end end
@ -79,8 +81,10 @@ end)
for i=1,10 do _G.x = i; assert(f(i) == i) end for i=1,10 do _G.x = i; assert(f(i) == i) end
_G.x = 'xuxu'; assert(f('xuxu') == 'a') _G.x = 'xuxu'; assert(f('xuxu') == 'a')
_G.x = nil
-- recursive -- recursive
function pf (n, i) local function pf (n, i)
coroutine.yield(n) coroutine.yield(n)
pf(n*i, i+1) pf(n*i, i+1)
end end
@ -93,14 +97,14 @@ for i=1,10 do
end end
-- sieve -- sieve
function gen (n) local function gen (n)
return coroutine.wrap(function () return coroutine.wrap(function ()
for i=2,n do coroutine.yield(i) end for i=2,n do coroutine.yield(i) end
end) end)
end end
function filter (p, g) local function filter (p, g)
return coroutine.wrap(function () return coroutine.wrap(function ()
while 1 do while 1 do
local n = g() local n = g()
@ -221,14 +225,14 @@ do
-- <close> versus pcall in coroutines -- <close> versus pcall in coroutines
local X = false local X = false
local Y = false local Y = false
function foo () local function foo ()
local x <close> = func2close(function (self, err) local x <close> = func2close(function (self, err)
Y = debug.getinfo(2) Y = debug.getinfo(2)
X = err X = err
end) end)
error(43) error(43)
end end
co = coroutine.create(function () return pcall(foo) end) local co = coroutine.create(function () return pcall(foo) end)
local st1, st2, err = coroutine.resume(co) local st1, st2, err = coroutine.resume(co)
assert(st1 and not st2 and err == 43) assert(st1 and not st2 and err == 43)
assert(X == 43 and Y.what == "C") assert(X == 43 and Y.what == "C")
@ -275,7 +279,7 @@ end
-- yielding across C boundaries -- yielding across C boundaries
co = coroutine.wrap(function() local co = coroutine.wrap(function()
assert(not pcall(table.sort,{1,2,3}, coroutine.yield)) assert(not pcall(table.sort,{1,2,3}, coroutine.yield))
assert(coroutine.isyieldable()) assert(coroutine.isyieldable())
coroutine.yield(20) coroutine.yield(20)
@ -303,15 +307,15 @@ local r1, r2, v = f1(nil)
assert(r1 and not r2 and v[1] == (10 + 1)*10/2) assert(r1 and not r2 and v[1] == (10 + 1)*10/2)
function f (a, b) a = coroutine.yield(a); error{a + b} end local function f (a, b) a = coroutine.yield(a); error{a + b} end
function g(x) return x[1]*2 end local function g(x) return x[1]*2 end
co = coroutine.wrap(function () co = coroutine.wrap(function ()
coroutine.yield(xpcall(f, g, 10, 20)) coroutine.yield(xpcall(f, g, 10, 20))
end) end)
assert(co() == 10) assert(co() == 10)
r, msg = co(100) local r, msg = co(100)
assert(not r and msg == 240) assert(not r and msg == 240)
@ -373,9 +377,10 @@ assert(not a and b == foo and coroutine.status(x) == "dead")
a,b = coroutine.resume(x) a,b = coroutine.resume(x)
assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead") assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
goo = nil
-- co-routines x for loop -- co-routines x for loop
function all (a, n, k) local function all (a, n, k)
if k == 0 then coroutine.yield(a) if k == 0 then coroutine.yield(a)
else else
for i=1,n do for i=1,n do
@ -415,7 +420,7 @@ assert(f() == 43 and f() == 53)
-- old bug: attempt to resume itself -- old bug: attempt to resume itself
function co_func (current_co) local function co_func (current_co)
assert(coroutine.running() == current_co) assert(coroutine.running() == current_co)
assert(coroutine.resume(current_co) == false) assert(coroutine.resume(current_co) == false)
coroutine.yield(10, 20) coroutine.yield(10, 20)
@ -491,15 +496,16 @@ a = nil
-- access to locals of erroneous coroutines -- access to locals of erroneous coroutines
local x = coroutine.create (function () local x = coroutine.create (function ()
local a = 10 local a = 10
_G.f = function () a=a+1; return a end _G.F = function () a=a+1; return a end
error('x') error('x')
end) end)
assert(not coroutine.resume(x)) assert(not coroutine.resume(x))
-- overwrite previous position of local `a' -- overwrite previous position of local `a'
assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1)) assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
assert(_G.f() == 11) assert(_G.F() == 11)
assert(_G.f() == 12) assert(_G.F() == 12)
_G.F = nil
if not T then if not T then
@ -510,7 +516,7 @@ else
local turn local turn
function fact (t, x) local function fact (t, x)
assert(turn == t) assert(turn == t)
if x == 0 then return 1 if x == 0 then return 1
else return x*fact(t, x-1) else return x*fact(t, x-1)
@ -579,6 +585,7 @@ else
_G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil) _G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil)
_G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20) _G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20)
assert(co() == 10) assert(co() == 10)
_G.X = nil
-- testing yields in count hook -- testing yields in count hook
co = coroutine.wrap(function () co = coroutine.wrap(function ()
@ -656,6 +663,8 @@ else
assert(X == 'a a a' and Y == 'OK') assert(X == 'a a a' and Y == 'OK')
X, Y = nil
-- resuming running coroutine -- resuming running coroutine
C = coroutine.create(function () C = coroutine.create(function ()
@ -701,7 +710,7 @@ else
X = function (x) coroutine.yield(x, 'BB'); return 'CC' end; X = function (x) coroutine.yield(x, 'BB'); return 'CC' end;
return 'ok']])) return 'ok']]))
t = table.pack(T.testC(state, [[ local t = table.pack(T.testC(state, [[
rawgeti R 1 # get main thread rawgeti R 1 # get main thread
pushstring 'XX' pushstring 'XX'
getglobal X # get function for body getglobal X # get function for body
@ -730,13 +739,13 @@ end
-- leaving a pending coroutine open -- leaving a pending coroutine open
_X = coroutine.wrap(function () _G.TO_SURVIVE = coroutine.wrap(function ()
local a = 10 local a = 10
local x = function () a = a+1 end local x = function () a = a+1 end
coroutine.yield() coroutine.yield()
end) end)
_X() _G.TO_SURVIVE()
if not _soft then if not _soft then
@ -935,7 +944,7 @@ assert(run(function ()
do local _ENV = _ENV do local _ENV = _ENV
f = function () AAA = BBB + 1; return AAA end f = function () AAA = BBB + 1; return AAA end
end end
g = new(10); g.k.BBB = 10; local g = new(10); g.k.BBB = 10;
debug.setupvalue(f, 1, g) debug.setupvalue(f, 1, g)
assert(run(f, {"idx", "nidx", "idx"}) == 11) assert(run(f, {"idx", "nidx", "idx"}) == 11)
assert(g.k.AAA == 11) assert(g.k.AAA == 11)
@ -1075,6 +1084,8 @@ assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
-- testing yields with continuations -- testing yields with continuations
local y
co = coroutine.wrap(function (...) return co = coroutine.wrap(function (...) return
T.testC([[ # initial function T.testC([[ # initial function
yieldk 1 2 yieldk 1 2
@ -1127,6 +1138,9 @@ assert(x == "YIELD" and y == 4)
assert(not pcall(co)) -- coroutine should be dead assert(not pcall(co)) -- coroutine should be dead
_G.ctx = nil
_G.status = nil
-- bug in nCcalls -- bug in nCcalls
local co = coroutine.wrap(function () local co = coroutine.wrap(function ()

View File

@ -16,7 +16,7 @@ end
assert(not debug.gethook()) assert(not debug.gethook())
local testline = 19 -- line where 'test' is defined local testline = 19 -- line where 'test' is defined
function test (s, l, p) -- this must be line 19 local function test (s, l, p) -- this must be line 19
collectgarbage() -- avoid gc during trace collectgarbage() -- avoid gc during trace
local function f (event, line) local function f (event, line)
assert(event == 'line') assert(event == 'line')
@ -50,7 +50,7 @@ end
-- test file and string names truncation -- test file and string names truncation
a = "function f () end" local a = "function f () end"
local function dostring (s, x) return load(s, x)() end local function dostring (s, x) return load(s, x)() end
dostring(a) dostring(a)
assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a)) assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
@ -72,7 +72,8 @@ dostring(a, string.format("=%s", string.rep('x', 500)))
assert(string.find(debug.getinfo(f).short_src, "^x*$")) assert(string.find(debug.getinfo(f).short_src, "^x*$"))
dostring(a, "=") dostring(a, "=")
assert(debug.getinfo(f).short_src == "") assert(debug.getinfo(f).short_src == "")
a = nil; f = nil; _G.a = nil; _G.f = nil;
_G[string.rep("p", 400)] = nil
repeat repeat
@ -120,6 +121,7 @@ else
end end
]], {2,3,4,7}) ]], {2,3,4,7})
test([[ test([[
local function foo() local function foo()
end end
@ -128,6 +130,7 @@ A = 1
A = 2 A = 2
A = 3 A = 3
]], {2, 3, 2, 4, 5, 6}) ]], {2, 3, 2, 4, 5, 6})
_G.A = nil
test([[-- test([[--
@ -175,6 +178,8 @@ end
test([[for i=1,4 do a=1 end]], {1,1,1,1}) test([[for i=1,4 do a=1 end]], {1,1,1,1})
_G.a = nil
do -- testing line info/trace with large gaps in source do -- testing line info/trace with large gaps in source
@ -194,6 +199,7 @@ do -- testing line info/trace with large gaps in source
end end
end end
end end
_G.a = nil
do -- testing active lines do -- testing active lines
@ -287,7 +293,6 @@ foo(200, 3, 4)
local a = {} local a = {}
for i = 1, (_soft and 100 or 1000) do a[i] = i end for i = 1, (_soft and 100 or 1000) do a[i] = i end
foo(table.unpack(a)) foo(table.unpack(a))
a = nil
@ -307,13 +312,14 @@ do -- test hook presence in debug info
debug.sethook() debug.sethook()
assert(count == 4) assert(count == 4)
end end
_ENV.a = nil
-- hook table has weak keys -- hook table has weak keys
assert(getmetatable(debug.getregistry()._HOOKKEY).__mode == 'k') assert(getmetatable(debug.getregistry()._HOOKKEY).__mode == 'k')
a = {}; L = nil a = {}; local L = nil
local glob = 1 local glob = 1
local oldglob = glob local oldglob = glob
debug.sethook(function (e,l) debug.sethook(function (e,l)
@ -354,7 +360,7 @@ function foo()
end; foo() -- set L end; foo() -- set L
-- check line counting inside strings and empty lines -- check line counting inside strings and empty lines
_ = 'alo\ local _ = 'alo\
alo' .. [[ alo' .. [[
]] ]]
@ -403,6 +409,7 @@ function g(a,b) return (a+1) + f() end
assert(g(0,0) == 30) assert(g(0,0) == 30)
_G.f, _G.g = nil
debug.sethook(nil); debug.sethook(nil);
assert(not debug.gethook()) assert(not debug.gethook())
@ -446,7 +453,7 @@ local function collectlocals (level)
end end
X = nil local X = nil
a = {} a = {}
function a:f (a, b, ...) local arg = {...}; local c = 13 end function a:f (a, b, ...) local arg = {...}; local c = 13 end
debug.sethook(function (e) debug.sethook(function (e)
@ -469,6 +476,7 @@ a:f(1,2,3,4,5)
assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil) assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
assert(XX == 12) assert(XX == 12)
assert(not debug.gethook()) assert(not debug.gethook())
_G.XX = nil
-- testing access to local variables in return hook (bug in 5.2) -- testing access to local variables in return hook (bug in 5.2)
@ -593,6 +601,7 @@ end
debug.sethook() debug.sethook()
local g, g1
-- tests for tail calls -- tests for tail calls
local function f (x) local function f (x)
@ -638,7 +647,7 @@ h(false)
debug.sethook() debug.sethook()
assert(b == 2) -- two tail calls assert(b == 2) -- two tail calls
lim = _soft and 3000 or 30000 local lim = _soft and 3000 or 30000
local function foo (x) local function foo (x)
if x==0 then if x==0 then
assert(debug.getinfo(2).what == "main") assert(debug.getinfo(2).what == "main")
@ -940,7 +949,7 @@ end
print("testing debug functions on chunk without debug info") print("testing debug functions on chunk without debug info")
prog = [[-- program to be loaded without debug information (strip) local prog = [[-- program to be loaded without debug information (strip)
local debug = require'debug' local debug = require'debug'
local a = 12 -- a local variable local a = 12 -- a local variable

View File

@ -114,12 +114,14 @@ checkmessage("a = {} | 1", "bitwise operation")
checkmessage("a = {} < 1", "attempt to compare") checkmessage("a = {} < 1", "attempt to compare")
checkmessage("a = {} <= 1", "attempt to compare") checkmessage("a = {} <= 1", "attempt to compare")
checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'") checkmessage("aaa=1; bbbb=2; aaa=math.sin(3)+bbbb(3)", "global 'bbbb'")
checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'") checkmessage("aaa={}; do local aaa=1 end aaa:bbbb(3)", "method 'bbbb'")
checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'") checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'")) assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'"))
checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number") checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number")
checkmessage("a=(1)..{}", "a table value") checkmessage("aaa=(1)..{}", "a table value")
_G.aaa, _G.bbbb = nil
-- calls -- calls
checkmessage("local a; a(13)", "local 'a'") checkmessage("local a; a(13)", "local 'a'")
@ -134,12 +136,13 @@ checkmessage([[
-- tail calls -- tail calls
checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'") checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
checkmessage("a={}; do local a=1 end; return a:bbbb(3)", "method 'bbbb'") checkmessage("aaa={}; do local aaa=1 end; return aaa:bbbb(3)", "method 'bbbb'")
checkmessage("a = #print", "length of a function value") checkmessage("aaa = #print", "length of a function value")
checkmessage("a = #3", "length of a number value") checkmessage("aaa = #3", "length of a number value")
_G.aaa = nil
aaa = nil
checkmessage("aaa.bbb:ddd(9)", "global 'aaa'") checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'") checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'") checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
@ -152,15 +155,16 @@ checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'") checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
checkmessage("b=1; local aaa={}; x=aaa+b", "local 'aaa'") checkmessage("BB=1; local aaa={}; x=aaa+BB", "local 'aaa'")
checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'") checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
checkmessage("aaa=2; b=nil;x=aaa*b", "global 'b'") checkmessage("aaa=2; BB=nil;x=aaa*BB", "global 'BB'")
checkmessage("aaa={}; x=-aaa", "global 'aaa'") checkmessage("aaa={}; x=-aaa", "global 'aaa'")
-- short circuit -- short circuit
checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)", checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = math.sin(1) and bbbb(3)",
"local 'bbbb'") "local 'bbbb'")
checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'") checkmessage("aaa=1; local aaa,bbbb=2,3; aaa = bbbb(1) or aaa(3)",
"local 'bbbb'")
checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'") checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value") checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'")) assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
@ -187,8 +191,8 @@ checkmessage("return ~-3e40", "has no integer representation")
checkmessage("return ~-3.009", "has no integer representation") checkmessage("return ~-3.009", "has no integer representation")
checkmessage("return 3.009 & 1", "has no integer representation") checkmessage("return 3.009 & 1", "has no integer representation")
checkmessage("return 34 >> {}", "table value") checkmessage("return 34 >> {}", "table value")
checkmessage("a = 24 // 0", "divide by zero") checkmessage("aaa = 24 // 0", "divide by zero")
checkmessage("a = 1 % 0", "'n%0'") checkmessage("aaa = 1 % 0", "'n%0'")
-- type error for an object which is neither in an upvalue nor a register. -- type error for an object which is neither in an upvalue nor a register.
@ -269,13 +273,13 @@ end
-- tests for field accesses after RK limit -- tests for field accesses after RK limit
local t = {} local t = {}
for i = 1, 1000 do for i = 1, 1000 do
t[i] = "a = x" .. i t[i] = "aaa = x" .. i
end end
local s = table.concat(t, "; ") local s = table.concat(t, "; ")
t = nil t = nil
checkmessage(s.."; a = bbb + 1", "global 'bbb'") checkmessage(s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'") checkmessage("local _ENV=_ENV;"..s.."; aaa = bbb + 1", "global 'bbb'")
checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'") checkmessage(s.."; local t = {}; aaa = t.bbb + 1", "field 'bbb'")
checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'") checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
checkmessage([[aaa=9 checkmessage([[aaa=9
@ -324,14 +328,17 @@ main()
]], "global 'NoSuchName'") ]], "global 'NoSuchName'")
print'+' print'+'
a = {}; setmetatable(a, {__index = string}) aaa = {}; setmetatable(aaa, {__index = string})
checkmessage("a:sub()", "bad self") checkmessage("aaa:sub()", "bad self")
checkmessage("string.sub('a', {})", "#2") checkmessage("string.sub('a', {})", "#2")
checkmessage("('a'):sub{}", "#1") checkmessage("('a'):sub{}", "#1")
checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'") checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'") checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
_G.aaa = nil
-- tests for errors in coroutines -- tests for errors in coroutines
local function f (n) local function f (n)
@ -349,7 +356,7 @@ checkerr("yield across", f)
-- testing size of 'source' info; size of buffer for that info is -- testing size of 'source' info; size of buffer for that info is
-- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'. -- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
idsize = 60 - 1 local idsize = 60 - 1
local function checksize (source) local function checksize (source)
-- syntax error -- syntax error
local _, msg = load("x", source) local _, msg = load("x", source)
@ -411,13 +418,14 @@ x
local p = [[ local p = [[
function g() f() end function g() f() end
function f(x) error('a', X) end function f(x) error('a', XX) end
g() g()
]] ]]
X=3;lineerror((p), 3) XX=3;lineerror((p), 3)
X=0;lineerror((p), false) XX=0;lineerror((p), false)
X=1;lineerror((p), 2) XX=1;lineerror((p), 2)
X=2;lineerror((p), 1) XX=2;lineerror((p), 1)
_G.XX, _G.g, _G.f = nil
lineerror([[ lineerror([[
@ -449,11 +457,11 @@ if not _soft then
-- several tests that exaust the Lua stack -- several tests that exaust the Lua stack
collectgarbage() collectgarbage()
print"testing stack overflow" print"testing stack overflow"
C = 0 local C = 0
-- get line where stack overflow will happen -- get line where stack overflow will happen
local l = debug.getinfo(1, "l").currentline + 1 local l = debug.getinfo(1, "l").currentline + 1
local function auxy () C=C+1; auxy() end -- produce a stack overflow local function auxy () C=C+1; auxy() end -- produce a stack overflow
function y () function YY ()
collectgarbage("stop") -- avoid running finalizers without stack space collectgarbage("stop") -- avoid running finalizers without stack space
auxy() auxy()
collectgarbage("restart") collectgarbage("restart")
@ -465,9 +473,11 @@ if not _soft then
return (string.find(m, "stack overflow")) return (string.find(m, "stack overflow"))
end end
-- repeated stack overflows (to check stack recovery) -- repeated stack overflows (to check stack recovery)
assert(checkstackmessage(doit('y()'))) assert(checkstackmessage(doit('YY()')))
assert(checkstackmessage(doit('y()'))) assert(checkstackmessage(doit('YY()')))
assert(checkstackmessage(doit('y()'))) assert(checkstackmessage(doit('YY()')))
_G.YY = nil
-- error lines in stack overflow -- error lines in stack overflow
@ -561,7 +571,7 @@ do
end end
-- xpcall with arguments -- xpcall with arguments
a, b, c = xpcall(string.find, error, "alo", "al") local a, b, c = xpcall(string.find, error, "alo", "al")
assert(a and b == 1 and c == 2) assert(a and b == 1 and c == 2)
a, b, c = xpcall(string.find, function (x) return {} end, true, "al") a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
assert(not a and type(b) == "table" and c == nil) assert(not a and type(b) == "table" and c == nil)
@ -581,11 +591,12 @@ checksyntax("a\1a = 1", "", "<\\1>", 1)
-- test 255 as first char in a chunk -- test 255 as first char in a chunk
checksyntax("\255a = 1", "", "<\\255>", 1) checksyntax("\255a = 1", "", "<\\255>", 1)
doit('I = load("a=9+"); a=3') doit('I = load("a=9+"); aaa=3')
assert(a==3 and not I) assert(_G.aaa==3 and not _G.I)
_G.I,_G.aaa = nil
print('+') print('+')
lim = 1000 local lim = 1000
if _soft then lim = 100 end if _soft then lim = 100 end
for i=1,lim do for i=1,lim do
doit('a = ') doit('a = ')

View File

@ -420,6 +420,9 @@ assert(i == 3 and x[1] == 3 and x[3] == 5)
assert(_G.X == 20) assert(_G.X == 20)
_G.X, _G.B = nil
print'+' print'+'
local _g = _G local _g = _G

View File

@ -507,15 +507,17 @@ load((io.lines(file, 1)))()
assert(_G.X == 4) assert(_G.X == 4)
load((io.lines(file, 3)))() load((io.lines(file, 3)))()
assert(_G.X == 8) assert(_G.X == 8)
_G.X = nil
print('+') print('+')
local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'" local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
io.output(file) io.output(file)
assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1))) assert(io.write(string.format("X2 = %q\n-- comment without ending EOS", x1)))
io.close() io.close()
assert(loadfile(file))() assert(loadfile(file))()
assert(x1 == x2) assert(x1 == _G.X2)
_G.X2 = nil
print('+') print('+')
assert(os.remove(file)) assert(os.remove(file))
assert(not os.remove(file)) assert(not os.remove(file))

View File

@ -125,7 +125,7 @@ do
end end
a:test() a:test()
_G.temp = nil
end end
@ -134,7 +134,7 @@ do local f = function () end end
print("functions with errors") print("functions with errors")
prog = [[ local prog = [[
do do
a = 10; a = 10;
function foo(x,y) function foo(x,y)
@ -153,22 +153,25 @@ do
end end
end end
end end
rawset(_G, "a", nil)
_G.x = nil
foo = nil do
print('long strings') foo = nil
x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789" print('long strings')
assert(string.len(x)==80) local x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
s = '' assert(string.len(x)==80)
k = math.min(300, (math.maxinteger // 80) // 2) local s = ''
for n = 1, k do s = s..x; j=tostring(n) end local k = math.min(300, (math.maxinteger // 80) // 2)
assert(string.len(s) == k*80) for n = 1, k do s = s..x; local j=tostring(n) end
s = string.sub(s, 1, 10000) assert(string.len(s) == k*80)
s, i = string.gsub(s, '(%d%d%d%d)', '') s = string.sub(s, 1, 10000)
assert(i==10000 // 4) local s, i = string.gsub(s, '(%d%d%d%d)', '')
s = nil assert(i==10000 // 4)
x = nil
assert(_G["while"] == 234) assert(_G["while"] == 234)
_G["while"] = nil
end
-- --
@ -227,8 +230,8 @@ end
print("clearing tables") print("clearing tables")
lim = 15 local lim = 15
a = {} local a = {}
-- fill a with `collectable' indices -- fill a with `collectable' indices
for i=1,lim do a[{}] = i end for i=1,lim do a[{}] = i end
b = {} b = {}
@ -552,6 +555,7 @@ do
for i=1,1000 do _ENV.a = {} end -- no collection during the loop for i=1,1000 do _ENV.a = {} end -- no collection during the loop
until gcinfo() > 2 * x until gcinfo() > 2 * x
collectgarbage"restart" collectgarbage"restart"
_ENV.a = nil
end end

View File

@ -10,6 +10,7 @@ local function dostring (x) return assert(load(x), "")() end
dostring("x \v\f = \t\r 'a\0a' \v\f\f") dostring("x \v\f = \t\r 'a\0a' \v\f\f")
assert(x == 'a\0a' and string.len(x) == 3) assert(x == 'a\0a' and string.len(x) == 3)
_G.x = nil
-- escape sequences -- escape sequences
assert('\n\"\'\\' == [[ assert('\n\"\'\\' == [[
@ -129,16 +130,16 @@ end
-- long variable names -- long variable names
var1 = string.rep('a', 15000) .. '1' local var1 = string.rep('a', 15000) .. '1'
var2 = string.rep('a', 15000) .. '2' local var2 = string.rep('a', 15000) .. '2'
prog = string.format([[ local prog = string.format([[
%s = 5 %s = 5
%s = %s + 1 %s = %s + 1
return function () return %s - %s end return function () return %s - %s end
]], var1, var2, var1, var1, var2) ]], var1, var2, var1, var1, var2)
local f = dostring(prog) local f = dostring(prog)
assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1) assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1)
var1, var2, f = nil _G[var1], _G[var2] = nil
print('+') print('+')
-- escapes -- -- escapes --
@ -150,13 +151,13 @@ assert([[
$debug]] == "\n $debug") $debug]] == "\n $debug")
assert([[ [ ]] ~= [[ ] ]]) assert([[ [ ]] ~= [[ ] ]])
-- long strings -- -- long strings --
b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960) assert(string.len(b) == 960)
prog = [=[ prog = [=[
print('+') print('+')
a1 = [["this is a 'string' with several 'quotes'"]] local a1 = [["this is a 'string' with several 'quotes'"]]
a2 = "'quotes'" local a2 = "'quotes'"
assert(string.find(a1, a2) == 34) assert(string.find(a1, a2) == 34)
print('+') print('+')
@ -164,12 +165,13 @@ print('+')
a1 = [==[temp = [[an arbitrary value]]; ]==] a1 = [==[temp = [[an arbitrary value]]; ]==]
assert(load(a1))() assert(load(a1))()
assert(temp == 'an arbitrary value') assert(temp == 'an arbitrary value')
_G.temp = nil
-- long strings -- -- long strings --
b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789" local b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
assert(string.len(b) == 960) assert(string.len(b) == 960)
print('+') print('+')
a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789 local a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789 00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789 00123456789012345678901234567890123456789123456789012345678901234567890123456789
00123456789012345678901234567890123456789123456789012345678901234567890123456789 00123456789012345678901234567890123456789123456789012345678901234567890123456789
@ -199,13 +201,11 @@ x = 1
]=] ]=]
print('+') print('+')
x = nil _G.x = nil
dostring(prog) dostring(prog)
assert(x) assert(x)
_G.x = nil
prog = nil
a = nil
b = nil
do -- reuse of long strings do -- reuse of long strings
@ -234,8 +234,8 @@ end
-- testing line ends -- testing line ends
prog = [[ prog = [[
a = 1 -- a comment local a = 1 -- a comment
b = 2 local b = 2
x = [=[ x = [=[
@ -252,10 +252,11 @@ for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
assert(dostring(prog) == nn) assert(dostring(prog) == nn)
assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n") assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
end end
_G.x, _G.y = nil
-- testing comments and strings with long brackets -- testing comments and strings with long brackets
a = [==[]=]==] local a = [==[]=]==]
assert(a == "]=") assert(a == "]=")
a = [==[[===[[=[]]=][====[]]===]===]==] a = [==[[===[[=[]]=][====[]]===]===]==]

View File

@ -37,7 +37,7 @@ end
f = nil f = nil
local f local f
x = 1 local x = 1
a = nil a = nil
load('local a = {}')() load('local a = {}')()
@ -152,7 +152,7 @@ local dummy
local _ENV = (function (...) return ... end)(_G, dummy) -- { local _ENV = (function (...) return ... end)(_G, dummy) -- {
do local _ENV = {assert=assert}; assert(true) end do local _ENV = {assert=assert}; assert(true) end
mt = {_G = _G} local mt = {_G = _G}
local foo,x local foo,x
A = false -- "declare" A A = false -- "declare" A
do local _ENV = mt do local _ENV = mt
@ -174,6 +174,8 @@ do local _ENV = {assert=assert, A=10};
end end
assert(x==20) assert(x==20)
A = nil
do -- constants do -- constants
local a<const>, b, c<const> = 10, 20, 30 local a<const>, b, c<const> = 10, 20, 30
@ -711,7 +713,7 @@ if rawget(_G, "T") then
collectgarbage(); collectgarbage() collectgarbage(); collectgarbage()
m = T.totalmem() local m = T.totalmem()
collectgarbage("stop") collectgarbage("stop")
-- error in the first buffer allocation -- error in the first buffer allocation

View File

@ -339,7 +339,7 @@ prepfile("a = [[b\nc\nd\ne]]\n=a")
RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out) RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
checkprogout("b\nc\nd\ne\n\n") checkprogout("b\nc\nd\ne\n\n")
prompt = "alo" local prompt = "alo"
prepfile[[ -- prepfile[[ --
a = 2 a = 2
]] ]]
@ -390,7 +390,7 @@ NoRun("error object is a table value", [[lua %s]], prog)
-- chunk broken in many lines -- chunk broken in many lines
s = [=[ -- local s = [=[ --
function f ( x ) function f ( x )
local a = [[ local a = [[
xuxu xuxu

View File

@ -50,7 +50,7 @@ end
local msgf2i = "number.* has no integer representation" local msgf2i = "number.* has no integer representation"
-- float equality -- float equality
function eq (a,b,limit) local function eq (a,b,limit)
if not limit then if not limit then
if floatbits >= 50 then limit = 1E-11 if floatbits >= 50 then limit = 1E-11
else limit = 1E-5 else limit = 1E-5
@ -62,7 +62,7 @@ end
-- equality with types -- equality with types
function eqT (a,b) local function eqT (a,b)
return a == b and math.type(a) == math.type(b) return a == b and math.type(a) == math.type(b)
end end
@ -83,7 +83,7 @@ end
do do
local x = -1 local x = -1
local mz = 0/x -- minus zero local mz = 0/x -- minus zero
t = {[0] = 10, 20, 30, 40, 50} local t = {[0] = 10, 20, 30, 40, 50}
assert(t[mz] == t[0] and t[-0] == t[0]) assert(t[mz] == t[0] and t[-0] == t[0])
end end

View File

@ -189,7 +189,7 @@ end
-- size tests for vararg -- size tests for vararg
lim = 35 lim = 35
function foo (n, ...) local function foo (n, ...)
local arg = {...} local arg = {...}
check(arg, n, 0) check(arg, n, 0)
assert(select('#', ...) == n) assert(select('#', ...) == n)

View File

@ -9,12 +9,12 @@ local function checkerror (msg, f, ...)
end end
function f(s, p) local function f (s, p)
local i,e = string.find(s, p) local i,e = string.find(s, p)
if i then return string.sub(s, i, e) end if i then return string.sub(s, i, e) end
end end
a,b = string.find('', '') -- empty patterns are tricky local a,b = string.find('', '') -- empty patterns are tricky
assert(a == 1 and b == 0); assert(a == 1 and b == 0);
a,b = string.find('alo', '') a,b = string.find('alo', '')
assert(a == 1 and b == 0) assert(a == 1 and b == 0)
@ -88,7 +88,7 @@ assert(f("alo alo", "%C+") == "alo alo")
print('+') print('+')
function f1(s, p) local function f1 (s, p)
p = string.gsub(p, "%%([0-9])", function (s) p = string.gsub(p, "%%([0-9])", function (s)
return "%" .. (tonumber(s)+1) return "%" .. (tonumber(s)+1)
end) end)
@ -113,7 +113,7 @@ local abc = string.char(range(0, 127)) .. string.char(range(128, 255));
assert(string.len(abc) == 256) assert(string.len(abc) == 256)
function strset (p) local function strset (p)
local res = {s=''} local res = {s=''}
string.gsub(abc, p, function (c) res.s = res.s .. c end) string.gsub(abc, p, function (c) res.s = res.s .. c end)
return res.s return res.s
@ -147,7 +147,7 @@ assert(string.gsub('
assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim
assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim
assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ') assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ')
t = "abç d" local t = "abç d"
a, b = string.gsub(t, '(.)', '%1@') a, b = string.gsub(t, '(.)', '%1@')
assert('@'..a == string.gsub(t, '', '@') and b == 5) assert('@'..a == string.gsub(t, '', '@') and b == 5)
a, b = string.gsub('abçd', '(.)', '%0@', 2) a, b = string.gsub('abçd', '(.)', '%0@', 2)
@ -184,6 +184,7 @@ do
local function setglobal (n,v) rawset(_G, n, v) end local function setglobal (n,v) rawset(_G, n, v) end
string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal) string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal)
assert(_G.a=="roberto" and _G.roberto=="a") assert(_G.a=="roberto" and _G.roberto=="a")
_G.a = nil; _G.roberto = nil
end end
function f(a,b) return string.gsub(a,'.',b) end function f(a,b) return string.gsub(a,'.',b) end
@ -195,20 +196,21 @@ assert(string.gsub("alo $a='x'$ novamente $return a$",
"$([^$]*)%$", "$([^$]*)%$",
dostring) == "alo novamente x") dostring) == "alo novamente x")
x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$", local x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$",
"$([^$]*)%$", dostring) "$([^$]*)%$", dostring)
assert(x == ' assim vai para ALO') assert(x == ' assim vai para ALO')
_G.a, _G.x = nil
t = {} local t = {}
s = 'a alo jose joao' local s = 'a alo jose joao'
r = string.gsub(s, '()(%w+)()', function (a,w,b) local r = string.gsub(s, '()(%w+)()', function (a,w,b)
assert(string.len(w) == b-a); assert(string.len(w) == b-a);
t[a] = b-a; t[a] = b-a;
end) end)
assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4) assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
function isbalanced (s) local function isbalanced (s)
return not string.find(string.gsub(s, "%b()", ""), "[()]") return not string.find(string.gsub(s, "%b()", ""), "[()]")
end end
@ -251,7 +253,7 @@ if not _soft then
end end
-- recursive nest of gsubs -- recursive nest of gsubs
function rev (s) local function rev (s)
return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end) return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end)
end end

View File

@ -20,7 +20,7 @@ end
checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4)
local x,y,z,a,n local x,y,z,a,n
a = {}; lim = _soft and 200 or 2000 a = {}; local lim = _soft and 200 or 2000
for i=1, lim do a[i]=i end for i=1, lim do a[i]=i end
assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim) assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
x = unpack(a) x = unpack(a)
@ -222,7 +222,7 @@ a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
table.sort(a) table.sort(a)
check(a) check(a)
function perm (s, n) local function perm (s, n)
n = n or #s n = n or #s
if n == 1 then if n == 1 then
local t = {unpack(s)} local t = {unpack(s)}
@ -248,7 +248,7 @@ perm{1,2,3,3,5}
perm{1,2,3,4,5,6} perm{1,2,3,4,5,6}
perm{2,2,3,3,5,6} perm{2,2,3,3,5,6}
function timesort (a, n, func, msg, pre) local function timesort (a, n, func, msg, pre)
local x = os.clock() local x = os.clock()
table.sort(a, func) table.sort(a, func)
x = (os.clock() - x) * 1000 x = (os.clock() - x) * 1000
@ -257,7 +257,7 @@ function timesort (a, n, func, msg, pre)
check(a, func) check(a, func)
end end
limit = 50000 local limit = 50000
if _soft then limit = 5000 end if _soft then limit = 5000 end
a = {} a = {}
@ -274,7 +274,7 @@ for i=1,limit do
a[i] = math.random() a[i] = math.random()
end end
x = os.clock(); i=0 local x = os.clock(); local i = 0
table.sort(a, function(x,y) i=i+1; return y<x end) table.sort(a, function(x,y) i=i+1; return y<x end)
x = (os.clock() - x) * 1000 x = (os.clock() - x) * 1000
print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons", print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons",
@ -289,18 +289,19 @@ timesort(a, limit, function(x,y) return nil end, "equal")
for i,v in pairs(a) do assert(v == false) end for i,v in pairs(a) do assert(v == false) end
A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"} AA = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
table.sort(A) table.sort(AA)
check(A) check(AA)
table.sort(A, function (x, y) table.sort(AA, function (x, y)
load(string.format("A[%q] = ''", x), "")() load(string.format("AA[%q] = ''", x), "")()
collectgarbage() collectgarbage()
return x<y return x<y
end) end)
_G.AA = nil
tt = {__lt = function (a,b) return a.val < b.val end} local tt = {__lt = function (a,b) return a.val < b.val end}
a = {} a = {}
for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end
table.sort(a) table.sort(a)

View File

@ -52,7 +52,7 @@ assert(("\000123456789"):sub(8) == "789")
-- testing string.find -- testing string.find
assert(string.find("123456789", "345") == 3) assert(string.find("123456789", "345") == 3)
a,b = string.find("123456789", "345") local a,b = string.find("123456789", "345")
assert(string.sub("123456789", a, b) == "345") assert(string.sub("123456789", a, b) == "345")
assert(string.find("1234567890123456789", "345", 3) == 3) assert(string.find("1234567890123456789", "345", 3) == 3)
assert(string.find("1234567890123456789", "345", 4) == 13) assert(string.find("1234567890123456789", "345", 4) == 13)
@ -192,7 +192,7 @@ do -- tests for '%p' format
end end
end end
x = '"ílo"\n\\' local x = '"ílo"\n\\'
assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\') assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
assert(string.format('%q', "\0") == [["\0"]]) assert(string.format('%q', "\0") == [["\0"]])
assert(load(string.format('return %q', x))() == x) assert(load(string.format('return %q', x))() == x)
@ -452,7 +452,7 @@ end
do do
local f = string.gmatch("1 2 3 4 5", "%d+") local f = string.gmatch("1 2 3 4 5", "%d+")
assert(f() == "1") assert(f() == "1")
co = coroutine.wrap(f) local co = coroutine.wrap(f)
assert(co() == "2") assert(co() == "2")
end end

View File

@ -35,7 +35,7 @@ print("\talignment: " .. align)
-- check errors in arguments -- check errors in arguments
function checkerror (msg, f, ...) local function checkerror (msg, f, ...)
local status, err = pcall(f, ...) local status, err = pcall(f, ...)
-- print(status, err, msg) -- print(status, err, msg)
assert(not status and string.find(err, msg)) assert(not status and string.find(err, msg))

View File

@ -230,7 +230,7 @@ do
check(s, {0x10000, 0x1FFFFF}, true) check(s, {0x10000, 0x1FFFFF}, true)
end end
x = "日本語a-4\0éó" local x = "日本語a-4\0éó"
check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243}) check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243})

View File

@ -3,13 +3,13 @@
print('testing vararg') print('testing vararg')
function f(a, ...) local function f (a, ...)
local x = {n = select('#', ...), ...} local x = {n = select('#', ...), ...}
for i = 1, x.n do assert(a[i] == x[i]) end for i = 1, x.n do assert(a[i] == x[i]) end
return x.n return x.n
end end
function c12 (...) local function c12 (...)
assert(arg == _G.arg) -- no local 'arg' assert(arg == _G.arg) -- no local 'arg'
local x = {...}; x.n = #x local x = {...}; x.n = #x
local res = (x.n==2 and x[1] == 1 and x[2] == 2) local res = (x.n==2 and x[1] == 1 and x[2] == 2)
@ -17,7 +17,7 @@ function c12 (...)
return res, 2 return res, 2
end end
function vararg (...) return {n = select('#', ...), ...} end local function vararg (...) return {n = select('#', ...), ...} end
local call = function (f, args) return f(table.unpack(args, 1, args.n)) end local call = function (f, args) return f(table.unpack(args, 1, args.n)) end
@ -29,7 +29,7 @@ assert(vararg().n == 0)
assert(vararg(nil, nil).n == 2) assert(vararg(nil, nil).n == 2)
assert(c12(1,2)==55) assert(c12(1,2)==55)
a,b = assert(call(c12, {1,2})) local a,b = assert(call(c12, {1,2}))
assert(a == 55 and b == 2) assert(a == 55 and b == 2)
a = call(c12, {1,2;n=2}) a = call(c12, {1,2;n=2})
assert(a == 55 and b == 2) assert(a == 55 and b == 2)
@ -49,7 +49,7 @@ function t:f (...) local arg = {...}; return self[...]+#arg end
assert(t:f(1,4) == 3 and t:f(2) == 11) assert(t:f(1,4) == 3 and t:f(2) == 11)
print('+') print('+')
lim = 20 local lim = 20
local i, a = 1, {} local i, a = 1, {}
while i <= lim do a[i] = i+0.3; i=i+1 end while i <= lim do a[i] = i+0.3; i=i+1 end
@ -59,7 +59,7 @@ function f(a, b, c, d, ...)
more[lim-4] == lim+0.3 and not more[lim-3]) more[lim-4] == lim+0.3 and not more[lim-3])
end end
function g(a,b,c) local function g (a,b,c)
assert(a == 1.3 and b == 2.3 and c == 3.3) assert(a == 1.3 and b == 2.3 and c == 3.3)
end end
@ -76,7 +76,7 @@ print("+")
-- new-style varargs -- new-style varargs
function oneless (a, ...) return ... end local function oneless (a, ...) return ... end
function f (n, a, ...) function f (n, a, ...)
local b local b
@ -99,8 +99,8 @@ assert(a==nil and b==nil and c==nil and d==nil and e==nil)
-- varargs for main chunks -- varargs for main chunks
f = load[[ return {...} ]] local f = load[[ return {...} ]]
x = f(2,3) local x = f(2,3)
assert(x[1] == 2 and x[2] == 3 and x[3] == undef) assert(x[1] == 2 and x[2] == 3 and x[3] == undef)

View File

@ -52,7 +52,7 @@ if _soft then return 10 end
print "testing large programs (>64k)" print "testing large programs (>64k)"
-- template to create a very big test file -- template to create a very big test file
prog = [[$ local prog = [[$
local a,b local a,b
@ -85,7 +85,7 @@ function b:xxx (a,b) return a+b end
assert(b:xxx(10, 12) == 22) -- pushself with non-constant index assert(b:xxx(10, 12) == 22) -- pushself with non-constant index
b["xxx"] = undef b["xxx"] = undef
s = 0; n=0 local s = 0; local n=0
for a,b in pairs(b) do s=s+b; n=n+1 end for a,b in pairs(b) do s=s+b; n=n+1 end
-- with 32-bit floats, exact value of 's' depends on summation order -- with 32-bit floats, exact value of 's' depends on summation order
assert(81800000.0 < s and s < 81860000 and n == 70001) assert(81800000.0 < s and s < 81860000 and n == 70001)
@ -93,7 +93,7 @@ assert(81800000.0 < s and s < 81860000 and n == 70001)
a = nil; b = nil a = nil; b = nil
print'+' print'+'
function f(x) b=x end local function f(x) b=x end
a = f{$3$} or 10 a = f{$3$} or 10
@ -118,7 +118,7 @@ local function sig (x)
return (x % 2 == 0) and '' or '-' return (x % 2 == 0) and '' or '-'
end end
F = { local F = {
function () -- $1$ function () -- $1$
for i=10,50009 do for i=10,50009 do
io.write('a', i, ' = ', sig(i), 5+((i-10)/2), ',\n') io.write('a', i, ' = ', sig(i), 5+((i-10)/2), ',\n')
@ -138,14 +138,14 @@ function () -- $3$
end, end,
} }
file = os.tmpname() local file = os.tmpname()
io.output(file) io.output(file)
for s in string.gmatch(prog, "$([^$]+)") do for s in string.gmatch(prog, "$([^$]+)") do
local n = tonumber(s) local n = tonumber(s)
if not n then io.write(s) else F[n]() end if not n then io.write(s) else F[n]() end
end end
io.close() io.close()
result = dofile(file) local result = dofile(file)
assert(os.remove(file)) assert(os.remove(file))
print'OK' print'OK'
return result return result