mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
Increase code coverage for Lua libraries
Add test coverage for lua libraries Remove dead code in Lua implementation Signed-off-by: Don Brady <don.brady@delphix.com>
This commit is contained in:
committed by
Brian Behlendorf
parent
ee00bfb2e6
commit
fc5d4b6737
@@ -17,6 +17,11 @@ dist_pkgdata_SCRIPTS = \
|
||||
tst.large_prog.ksh \
|
||||
tst.large_prog.out \
|
||||
tst.large_prog.zcp \
|
||||
tst.lib_base.lua \
|
||||
tst.lib_coroutine.lua \
|
||||
tst.lib_strings.lua \
|
||||
tst.lib_table.lua \
|
||||
tst.libraries.ksh \
|
||||
tst.memory_limit.ksh \
|
||||
tst.nested_neg.ksh \
|
||||
tst.nested_neg.zcp \
|
||||
|
||||
@@ -0,0 +1,469 @@
|
||||
--[[
|
||||
--*****************************************************************************
|
||||
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
|
||||
--*
|
||||
--* Permission is hereby granted, free of charge, to any person obtaining
|
||||
--* a copy of this software and associated documentation files (the
|
||||
--* "Software"), to deal in the Software without restriction, including
|
||||
--* without limitation the rights to use, copy, modify, merge, publish,
|
||||
--* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
--* permit persons to whom the Software is furnished to do so, subject to
|
||||
--* the following conditions:
|
||||
--*
|
||||
--* The above copyright notice and this permission notice shall be
|
||||
--* included in all copies or substantial portions of the Software.
|
||||
--*
|
||||
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
--*****************************************************************************
|
||||
--]]
|
||||
|
||||
-- testing metatables
|
||||
|
||||
X = 20; B = 30
|
||||
|
||||
_ENV = setmetatable({}, {__index=_G})
|
||||
|
||||
collectgarbage()
|
||||
|
||||
X = X+10
|
||||
assert(X == 30 and _G.X == 20)
|
||||
B = false
|
||||
assert(B == false)
|
||||
B = nil
|
||||
assert(B == 30)
|
||||
|
||||
assert(getmetatable{} == nil)
|
||||
assert(getmetatable(4) == nil)
|
||||
assert(getmetatable(nil) == nil)
|
||||
a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
|
||||
__tostring=function(x) return x.name end})
|
||||
assert(getmetatable(a) == "xuxu")
|
||||
assert(tostring(a) == "NAME")
|
||||
|
||||
local a, t = {10,20,30; x="10", y="20"}, {}
|
||||
assert(setmetatable(a,t) == a)
|
||||
assert(getmetatable(a) == t)
|
||||
assert(setmetatable(a,nil) == a)
|
||||
assert(getmetatable(a) == nil)
|
||||
assert(setmetatable(a,t) == a)
|
||||
|
||||
|
||||
function f (t, i, e)
|
||||
assert(not e)
|
||||
local p = rawget(t, "parent")
|
||||
return (p and p[i]+3), "dummy return"
|
||||
end
|
||||
|
||||
t.__index = f
|
||||
|
||||
a.parent = {z=25, x=12, [4] = 24}
|
||||
assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
|
||||
|
||||
collectgarbage()
|
||||
|
||||
a = setmetatable({}, t)
|
||||
function f(t, i, v) rawset(t, i, v-3) end
|
||||
setmetatable(t, t) -- causes a bug in 5.1 !
|
||||
t.__newindex = f
|
||||
a[1] = 30; a.x = "101"; a[5] = 200
|
||||
assert(a[1] == 27 and a.x == 98 and a[5] == 197)
|
||||
|
||||
|
||||
local c = {}
|
||||
a = setmetatable({}, t)
|
||||
t.__newindex = c
|
||||
a[1] = 10; a[2] = 20; a[3] = 90
|
||||
assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
|
||||
|
||||
|
||||
do
|
||||
local a;
|
||||
a = setmetatable({}, {__index = setmetatable({},
|
||||
{__index = setmetatable({},
|
||||
{__index = function (_,n) return a[n-3]+4, "lixo" end})})})
|
||||
a[0] = 20
|
||||
for i=0,10 do
|
||||
assert(a[i*3] == 20 + i*4)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
do -- newindex
|
||||
local foi
|
||||
local a = {}
|
||||
for i=1,10 do a[i] = 0; a['a'..i] = 0; end
|
||||
setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
|
||||
foi = false; a[1]=0; assert(not foi)
|
||||
foi = false; a['a1']=0; assert(not foi)
|
||||
foi = false; a['a11']=0; assert(foi)
|
||||
foi = false; a[11]=0; assert(foi)
|
||||
foi = false; a[1]=nil; assert(not foi)
|
||||
foi = false; a[1]=nil; assert(foi)
|
||||
end
|
||||
|
||||
|
||||
setmetatable(t, nil)
|
||||
function f (t, ...) return t, {...} end
|
||||
t.__call = f
|
||||
|
||||
do
|
||||
local x,y = a(table.unpack{'a', 1})
|
||||
assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
|
||||
x,y = a()
|
||||
assert(x==a and y[1]==nil)
|
||||
end
|
||||
|
||||
|
||||
local b = setmetatable({}, t)
|
||||
setmetatable(b,t)
|
||||
|
||||
function f(op)
|
||||
return function (...) cap = {[0] = op, ...} ; return (...) end
|
||||
end
|
||||
t.__add = f("add")
|
||||
t.__sub = f("sub")
|
||||
t.__mul = f("mul")
|
||||
t.__div = f("div")
|
||||
t.__mod = f("mod")
|
||||
t.__unm = f("unm")
|
||||
t.__pow = f("pow")
|
||||
t.__len = f("len")
|
||||
|
||||
assert(b+5 == b)
|
||||
assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
|
||||
assert(b+'5' == b)
|
||||
assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
|
||||
assert(5+b == 5)
|
||||
assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
|
||||
assert('5'+b == '5')
|
||||
assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
|
||||
b=b-3; assert(getmetatable(b) == t)
|
||||
assert(5-a == 5)
|
||||
assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
|
||||
assert('5'-a == '5')
|
||||
assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
|
||||
assert(a*a == a)
|
||||
assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
|
||||
assert(a/0 == a)
|
||||
assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
|
||||
assert(a%2 == a)
|
||||
assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
|
||||
assert(-a == a)
|
||||
assert(cap[0] == "unm" and cap[1] == a)
|
||||
assert(a^4 == a)
|
||||
assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
|
||||
assert(a^'4' == a)
|
||||
assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
|
||||
assert(4^a == 4)
|
||||
assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
|
||||
assert('4'^a == '4')
|
||||
assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
|
||||
assert(#a == a)
|
||||
assert(cap[0] == "len" and cap[1] == a)
|
||||
|
||||
|
||||
-- test for rawlen
|
||||
t = setmetatable({1,2,3}, {__len = function () return 10 end})
|
||||
assert(#t == 10 and rawlen(t) == 3)
|
||||
assert(rawlen"abc" == 3)
|
||||
assert(rawlen(string.rep('a', 1000)) == 1000)
|
||||
|
||||
t = {}
|
||||
t.__lt = function (a,b,c)
|
||||
collectgarbage()
|
||||
assert(c == nil)
|
||||
if type(a) == 'table' then a = a.x end
|
||||
if type(b) == 'table' then b = b.x end
|
||||
return a<b, "dummy"
|
||||
end
|
||||
|
||||
function Op(x) return setmetatable({x=x}, t) end
|
||||
|
||||
local function test ()
|
||||
assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
|
||||
assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
|
||||
assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
|
||||
assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
|
||||
assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
|
||||
assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
|
||||
assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
|
||||
assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
|
||||
assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
|
||||
assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
|
||||
assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
|
||||
assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
|
||||
end
|
||||
|
||||
test()
|
||||
|
||||
t.__le = function (a,b,c)
|
||||
assert(c == nil)
|
||||
if type(a) == 'table' then a = a.x end
|
||||
if type(b) == 'table' then b = b.x end
|
||||
return a<=b, "dummy"
|
||||
end
|
||||
|
||||
test() -- retest comparisons, now using both `lt' and `le'
|
||||
|
||||
|
||||
-- test `partial order'
|
||||
|
||||
local function Set(x)
|
||||
local y = {}
|
||||
for _,k in pairs(x) do y[k] = 1 end
|
||||
return setmetatable(y, t)
|
||||
end
|
||||
|
||||
t.__lt = function (a,b)
|
||||
for k in pairs(a) do
|
||||
if not b[k] then return false end
|
||||
b[k] = nil
|
||||
end
|
||||
return next(b) ~= nil
|
||||
end
|
||||
|
||||
t.__le = nil
|
||||
|
||||
assert(Set{1,2,3} < Set{1,2,3,4})
|
||||
assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
|
||||
assert((Set{1,2,3,4} <= Set{1,2,3,4}))
|
||||
assert((Set{1,2,3,4} >= Set{1,2,3,4}))
|
||||
assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
|
||||
|
||||
t.__le = function (a,b)
|
||||
for k in pairs(a) do
|
||||
if not b[k] then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
|
||||
assert(not(Set{1,3} <= Set{3,5}))
|
||||
assert(not(Set{1,3} >= Set{3,5}))
|
||||
|
||||
t.__eq = function (a,b)
|
||||
for k in pairs(a) do
|
||||
if not b[k] then return false end
|
||||
b[k] = nil
|
||||
end
|
||||
return next(b) == nil
|
||||
end
|
||||
|
||||
local s = Set{1,3,5}
|
||||
assert(s == Set{3,5,1})
|
||||
assert(not rawequal(s, Set{3,5,1}))
|
||||
assert(rawequal(s, s))
|
||||
assert(Set{1,3,5,1} == Set{3,5,1})
|
||||
assert(Set{1,3,5} ~= Set{3,5,1,6})
|
||||
t[Set{1,3,5}] = 1
|
||||
assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
|
||||
|
||||
|
||||
t.__concat = function (a,b,c)
|
||||
assert(c == nil)
|
||||
if type(a) == 'table' then a = a.val end
|
||||
if type(b) == 'table' then b = b.val end
|
||||
if A then return a..b
|
||||
else
|
||||
return setmetatable({val=a..b}, t)
|
||||
end
|
||||
end
|
||||
|
||||
c = {val="c"}; setmetatable(c, t)
|
||||
d = {val="d"}; setmetatable(d, t)
|
||||
|
||||
A = true
|
||||
assert(c..d == 'cd')
|
||||
assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
|
||||
|
||||
A = false
|
||||
assert((c..d..c..d).val == 'cdcd')
|
||||
x = c..d
|
||||
assert(getmetatable(x) == t and x.val == 'cd')
|
||||
x = 0 .."a".."b"..c..d.."e".."f".."g"
|
||||
assert(x.val == "0abcdefg")
|
||||
|
||||
|
||||
-- concat metamethod x numbers (bug in 5.1.1)
|
||||
c = {}
|
||||
local x
|
||||
setmetatable(c, {__concat = function (a,b)
|
||||
assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
|
||||
return c
|
||||
end})
|
||||
assert(c..5 == c and 5 .. c == c)
|
||||
assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
|
||||
|
||||
|
||||
-- test comparison compatibilities
|
||||
local t1, t2, c, d
|
||||
t1 = {}; c = {}; setmetatable(c, t1)
|
||||
d = {}
|
||||
t1.__eq = function () return true end
|
||||
t1.__lt = function () return true end
|
||||
setmetatable(d, t1)
|
||||
assert(c == d and c < d and not(d <= c))
|
||||
t2 = {}
|
||||
t2.__eq = t1.__eq
|
||||
t2.__lt = t1.__lt
|
||||
setmetatable(d, t2)
|
||||
assert(c == d and c < d and not(d <= c))
|
||||
|
||||
|
||||
|
||||
-- test for several levels of calls
|
||||
local i
|
||||
local tt = {
|
||||
__call = function (t, ...)
|
||||
i = i+1
|
||||
if t.f then return t.f(...)
|
||||
else return {...}
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local a = setmetatable({}, tt)
|
||||
local b = setmetatable({f=a}, tt)
|
||||
local c = setmetatable({f=b}, tt)
|
||||
|
||||
i = 0
|
||||
x = c(3,4,5)
|
||||
assert(i == 3 and x[1] == 3 and x[3] == 5)
|
||||
|
||||
|
||||
assert(_G.X == 20)
|
||||
|
||||
|
||||
local _g = _G
|
||||
_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
|
||||
|
||||
|
||||
a = {}
|
||||
rawset(a, "x", 1, 2, 3)
|
||||
assert(a.x == 1 and rawget(a, "x", 3) == 1)
|
||||
|
||||
|
||||
-- bug in 5.1
|
||||
T, K, V = nil
|
||||
grandparent = {}
|
||||
grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
|
||||
|
||||
parent = {}
|
||||
parent.__newindex = parent
|
||||
setmetatable(parent, grandparent)
|
||||
|
||||
child = setmetatable({}, parent)
|
||||
child.foo = 10 --> CRASH (on some machines)
|
||||
assert(T == parent and K == "foo" and V == 10)
|
||||
|
||||
|
||||
-- testing 'tonumber'
|
||||
assert(tonumber{} == nil)
|
||||
assert(tonumber('-012') == -010-2)
|
||||
assert(tonumber("0xffffffffffff") == 2^(4*12) - 1)
|
||||
assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1)
|
||||
|
||||
-- testing 'tonumber' with base
|
||||
assert(tonumber(' 001010 ', 2) == 10)
|
||||
assert(tonumber(' 001010 ', 10) == 1010)
|
||||
assert(tonumber(' -1010 ', 2) == -10)
|
||||
assert(tonumber('10', 36) == 36)
|
||||
assert(tonumber(' -10 ', 36) == -36)
|
||||
assert(tonumber(' +1Z ', 36) == 36 + 35)
|
||||
assert(tonumber(' -1z ', 36) == -36 + -35)
|
||||
assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
|
||||
assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
|
||||
assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34)
|
||||
assert(tonumber('ffffFFFF', 16)+1 == 2^32)
|
||||
assert(tonumber('0ffffFFFF', 16)+1 == 2^32)
|
||||
assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40)
|
||||
for i = 2,36 do
|
||||
assert(tonumber('\t10000000000\t', i) == i^10)
|
||||
end
|
||||
|
||||
-- testing 'tonumber' for invalid formats
|
||||
function f(...)
|
||||
if select('#', ...) == 1 then
|
||||
return (...)
|
||||
else
|
||||
return "***"
|
||||
end
|
||||
end
|
||||
|
||||
assert(f(tonumber('fFfa', 15)) == nil)
|
||||
assert(f(tonumber('099', 8)) == nil)
|
||||
assert(f(tonumber('1\0', 2)) == nil)
|
||||
assert(f(tonumber('', 8)) == nil)
|
||||
assert(f(tonumber(' ', 9)) == nil)
|
||||
assert(f(tonumber('0xf', 10)) == nil)
|
||||
|
||||
assert(f(tonumber('inf')) == nil)
|
||||
assert(f(tonumber(' INF ')) == nil)
|
||||
assert(f(tonumber('Nan')) == nil)
|
||||
assert(f(tonumber('nan')) == nil)
|
||||
|
||||
assert(f(tonumber('')) == nil)
|
||||
assert(f(tonumber('1 a')) == nil)
|
||||
assert(f(tonumber('1\0')) == nil)
|
||||
assert(f(tonumber('1 \0')) == nil)
|
||||
assert(f(tonumber('1\0 ')) == nil)
|
||||
assert(f(tonumber('e1')) == nil)
|
||||
assert(f(tonumber('e 1')) == nil)
|
||||
|
||||
|
||||
-- testing 'tonumber' for invalid hexadecimal formats
|
||||
assert(tonumber('0x') == nil)
|
||||
assert(tonumber('x') == nil)
|
||||
assert(tonumber('x3') == nil)
|
||||
assert(tonumber('00x2') == nil)
|
||||
assert(tonumber('0x 2') == nil)
|
||||
assert(tonumber('0 x2') == nil)
|
||||
assert(tonumber('23x') == nil)
|
||||
assert(tonumber('- 0xaa') == nil)
|
||||
|
||||
|
||||
-- testing hexadecimal numerals
|
||||
assert(tonumber('+0x2') == 2)
|
||||
assert(tonumber('-0xaA') == -170)
|
||||
assert(tonumber('-0xffFFFfff') == -2^32 + 1)
|
||||
|
||||
|
||||
-- testing 'tostring'
|
||||
assert(tostring("alo") == "alo")
|
||||
assert(tostring(12) == "12")
|
||||
assert(tostring(1234567890123) == '1234567890123')
|
||||
assert(type(tostring("hello")) == "string")
|
||||
assert(tostring(true) == "true")
|
||||
assert(tostring(false) == "false")
|
||||
assert(string.find(tostring{}, 'table:'))
|
||||
assert(string.find(tostring(select), 'function:'))
|
||||
assert(#tostring('\0') == 1)
|
||||
|
||||
|
||||
-- testing ipairs
|
||||
local x = 0
|
||||
for k,v in ipairs{10,20,30;x=12} do
|
||||
x = x + 1
|
||||
assert(k == x and v == x * 10)
|
||||
end
|
||||
|
||||
for _ in ipairs{x=12, y=24} do assert(nil) end
|
||||
|
||||
-- test for 'false' x ipair
|
||||
x = false
|
||||
local i = 0
|
||||
for k,v in ipairs{true,false,true,false} do
|
||||
i = i + 1
|
||||
x = not x
|
||||
assert(x == v)
|
||||
end
|
||||
assert(i == 4)
|
||||
|
||||
|
||||
return "OK"
|
||||
@@ -0,0 +1,362 @@
|
||||
--[[
|
||||
--*****************************************************************************
|
||||
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
|
||||
--*
|
||||
--* Permission is hereby granted, free of charge, to any person obtaining
|
||||
--* a copy of this software and associated documentation files (the
|
||||
--* "Software"), to deal in the Software without restriction, including
|
||||
--* without limitation the rights to use, copy, modify, merge, publish,
|
||||
--* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
--* permit persons to whom the Software is furnished to do so, subject to
|
||||
--* the following conditions:
|
||||
--*
|
||||
--* The above copyright notice and this permission notice shall be
|
||||
--* included in all copies or substantial portions of the Software.
|
||||
--*
|
||||
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
--*****************************************************************************
|
||||
--]]
|
||||
|
||||
local f
|
||||
|
||||
local main, ismain = coroutine.running()
|
||||
assert(type(main) == "thread" and ismain)
|
||||
assert(not coroutine.resume(main))
|
||||
|
||||
|
||||
-- tests for multiple yield/resume arguments
|
||||
|
||||
local function eqtab (t1, t2)
|
||||
assert(#t1 == #t2)
|
||||
for i = 1, #t1 do
|
||||
local v = t1[i]
|
||||
assert(t2[i] == v)
|
||||
end
|
||||
end
|
||||
|
||||
_G.x = nil -- declare x
|
||||
function foo (a, ...)
|
||||
local x, y = coroutine.running()
|
||||
assert(x == f and y == false)
|
||||
-- next call should not corrupt coroutine (but must fail,
|
||||
-- as it attempts to resume the running coroutine)
|
||||
assert(coroutine.resume(f) == false)
|
||||
assert(coroutine.status(f) == "running")
|
||||
local arg = {...}
|
||||
for i=1,#arg do
|
||||
_G.x = {coroutine.yield(table.unpack(arg[i]))}
|
||||
end
|
||||
return table.unpack(a)
|
||||
end
|
||||
|
||||
f = coroutine.create(foo)
|
||||
assert(type(f) == "thread" and coroutine.status(f) == "suspended")
|
||||
assert(string.find(tostring(f), "thread"))
|
||||
local s,a,b,c,d
|
||||
s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
|
||||
assert(s and a == nil and coroutine.status(f) == "suspended")
|
||||
s,a,b,c,d = coroutine.resume(f)
|
||||
eqtab(_G.x, {})
|
||||
assert(s and a == 1 and b == nil)
|
||||
s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
|
||||
eqtab(_G.x, {1, 2, 3})
|
||||
assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
|
||||
s,a,b,c,d = coroutine.resume(f, "xuxu")
|
||||
eqtab(_G.x, {"xuxu"})
|
||||
assert(s and a == 1 and b == 2 and c == 3 and d == nil)
|
||||
assert(coroutine.status(f) == "dead")
|
||||
s, a = coroutine.resume(f, "xuxu")
|
||||
assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
|
||||
|
||||
|
||||
-- yields in tail calls
|
||||
local function foo (i) return coroutine.yield(i) end
|
||||
f = coroutine.wrap(function ()
|
||||
for i=1,10 do
|
||||
assert(foo(i) == _G.x)
|
||||
end
|
||||
return 'a'
|
||||
end)
|
||||
for i=1,10 do _G.x = i; assert(f(i) == i) end
|
||||
_G.x = 'xuxu'; assert(f('xuxu') == 'a')
|
||||
|
||||
-- recursive
|
||||
function pf (n, i)
|
||||
coroutine.yield(n)
|
||||
pf(n*i, i+1)
|
||||
end
|
||||
|
||||
f = coroutine.wrap(pf)
|
||||
local s=1
|
||||
for i=1,10 do
|
||||
assert(f(1, 1) == s)
|
||||
s = s*i
|
||||
end
|
||||
|
||||
-- sieve implemented with co-routines
|
||||
|
||||
-- generate all the numbers from 2 to n
|
||||
function gen (n)
|
||||
return coroutine.wrap(function ()
|
||||
for i=2,n do coroutine.yield(i) end
|
||||
end)
|
||||
end
|
||||
|
||||
-- filter the numbers generated by 'g', removing multiples of 'p'
|
||||
function filter (p, g)
|
||||
return coroutine.wrap(function ()
|
||||
for n in g do
|
||||
if n%p ~= 0 then coroutine.yield(n) end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- generate primes up to 20
|
||||
local x = gen(20)
|
||||
local a = {}
|
||||
while 1 do
|
||||
local n = x()
|
||||
if n == nil then break end
|
||||
table.insert(a, n)
|
||||
x = filter(n, x)
|
||||
end
|
||||
|
||||
-- expect 8 primes and last one is 19
|
||||
assert(#a == 8 and a[#a] == 19)
|
||||
x, a = nil
|
||||
|
||||
|
||||
-- yielding across C boundaries
|
||||
|
||||
co = coroutine.wrap(function()
|
||||
coroutine.yield(20)
|
||||
return 30
|
||||
end)
|
||||
|
||||
assert(co() == 20)
|
||||
assert(co() == 30)
|
||||
|
||||
|
||||
local f = function (s, i) return coroutine.yield(i) end
|
||||
function f (a, b) a = coroutine.yield(a); error{a + b} end
|
||||
function g(x) return x[1]*2 end
|
||||
|
||||
|
||||
-- unyieldable C call
|
||||
do
|
||||
local function f (c)
|
||||
return c .. c
|
||||
end
|
||||
|
||||
local co = coroutine.wrap(function (c)
|
||||
local s = string.gsub("a", ".", f)
|
||||
return s
|
||||
end)
|
||||
assert(co() == "aa")
|
||||
end
|
||||
|
||||
|
||||
-- errors in coroutines
|
||||
function foo ()
|
||||
coroutine.yield(3)
|
||||
error(foo)
|
||||
end
|
||||
|
||||
function goo() foo() end
|
||||
x = coroutine.wrap(goo)
|
||||
assert(x() == 3)
|
||||
x = coroutine.create(goo)
|
||||
a,b = coroutine.resume(x)
|
||||
assert(a and b == 3)
|
||||
a,b = coroutine.resume(x)
|
||||
assert(not a and b == foo and coroutine.status(x) == "dead")
|
||||
a,b = coroutine.resume(x)
|
||||
assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
|
||||
|
||||
|
||||
-- co-routines x for loop
|
||||
function all (a, n, k)
|
||||
if k == 0 then coroutine.yield(a)
|
||||
else
|
||||
for i=1,n do
|
||||
a[k] = i
|
||||
all(a, n, k-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local a = 0
|
||||
for t in coroutine.wrap(function () all({}, 5, 4) end) do
|
||||
a = a+1
|
||||
end
|
||||
assert(a == 5^4)
|
||||
|
||||
|
||||
-- access to locals of collected corroutines
|
||||
local C = {}; setmetatable(C, {__mode = "kv"})
|
||||
local x = coroutine.wrap (function ()
|
||||
local a = 10
|
||||
local function f () a = a+10; return a end
|
||||
while true do
|
||||
a = a+1
|
||||
coroutine.yield(f)
|
||||
end
|
||||
end)
|
||||
|
||||
C[1] = x;
|
||||
|
||||
local f = x()
|
||||
assert(f() == 21 and x()() == 32 and x() == f)
|
||||
x = nil
|
||||
collectgarbage()
|
||||
assert(C[1] == nil)
|
||||
assert(f() == 43 and f() == 53)
|
||||
|
||||
|
||||
-- old bug: attempt to resume itself
|
||||
|
||||
function co_func (current_co)
|
||||
assert(coroutine.running() == current_co)
|
||||
assert(coroutine.resume(current_co) == false)
|
||||
coroutine.yield(10, 20)
|
||||
assert(coroutine.resume(current_co) == false)
|
||||
coroutine.yield(23)
|
||||
return 10
|
||||
end
|
||||
|
||||
local co = coroutine.create(co_func)
|
||||
local a,b,c = coroutine.resume(co, co)
|
||||
assert(a == true and b == 10 and c == 20)
|
||||
a,b = coroutine.resume(co, co)
|
||||
assert(a == true and b == 23)
|
||||
a,b = coroutine.resume(co, co)
|
||||
assert(a == true and b == 10)
|
||||
assert(coroutine.resume(co, co) == false)
|
||||
assert(coroutine.resume(co, co) == false)
|
||||
|
||||
|
||||
-- attempt to resume 'normal' coroutine
|
||||
local co1, co2
|
||||
co1 = coroutine.create(function () return co2() end)
|
||||
co2 = coroutine.wrap(function ()
|
||||
assert(coroutine.status(co1) == 'normal')
|
||||
assert(not coroutine.resume(co1))
|
||||
coroutine.yield(3)
|
||||
end)
|
||||
|
||||
a,b = coroutine.resume(co1)
|
||||
assert(a and b == 3)
|
||||
assert(coroutine.status(co1) == 'dead')
|
||||
|
||||
|
||||
-- access to locals of erroneous coroutines
|
||||
local x = coroutine.create (function ()
|
||||
local a = 10
|
||||
_G.f = function () a=a+1; return a end
|
||||
error('x')
|
||||
end)
|
||||
|
||||
assert(not coroutine.resume(x))
|
||||
-- overwrite previous position of local `a'
|
||||
assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
|
||||
assert(_G.f() == 11)
|
||||
assert(_G.f() == 12)
|
||||
|
||||
|
||||
-- leaving a pending coroutine open
|
||||
_X = coroutine.wrap(function ()
|
||||
local a = 10
|
||||
local x = function () a = a+1 end
|
||||
coroutine.yield()
|
||||
end)
|
||||
|
||||
_X()
|
||||
|
||||
assert(coroutine.running() == main)
|
||||
|
||||
|
||||
|
||||
-- testing yields inside metamethods
|
||||
|
||||
local mt = {
|
||||
__eq = function(a,b) coroutine.yield(nil, "eq"); return a.x == b.x end,
|
||||
__lt = function(a,b) coroutine.yield(nil, "lt"); return a.x < b.x end,
|
||||
__le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
|
||||
__add = function(a,b) coroutine.yield(nil, "add"); return a.x + b.x end,
|
||||
__sub = function(a,b) coroutine.yield(nil, "sub"); return a.x - b.x end,
|
||||
__mod = function(a,b) coroutine.yield(nil, "mod"); return a.x % b.x end,
|
||||
__unm = function(a,b) coroutine.yield(nil, "unm"); return -a.x end,
|
||||
|
||||
__concat = function(a,b)
|
||||
coroutine.yield(nil, "concat");
|
||||
a = type(a) == "table" and a.x or a
|
||||
b = type(b) == "table" and b.x or b
|
||||
return a .. b
|
||||
end,
|
||||
__index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
|
||||
__newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
|
||||
}
|
||||
|
||||
|
||||
local function new (x)
|
||||
return setmetatable({x = x, k = {}}, mt)
|
||||
end
|
||||
|
||||
|
||||
local a = new(10)
|
||||
local b = new(12)
|
||||
local c = new"hello"
|
||||
|
||||
local function run (f, t)
|
||||
local i = 1
|
||||
local c = coroutine.wrap(f)
|
||||
while true do
|
||||
local res, stat = c()
|
||||
if res then assert(t[i] == nil); return res, t end
|
||||
assert(stat == t[i])
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assert(run(function () if (a>=b) then return '>=' else return '<' end end,
|
||||
{"le", "sub"}) == "<")
|
||||
-- '<=' using '<'
|
||||
mt.__le = nil
|
||||
assert(run(function () if (a<=b) then return '<=' else return '>' end end,
|
||||
{"lt"}) == "<=")
|
||||
assert(run(function () if (a==b) then return '==' else return '~=' end end,
|
||||
{"eq"}) == "~=")
|
||||
|
||||
assert(run(function () return a % b end, {"mod"}) == 10)
|
||||
|
||||
assert(run(function () return a..b end, {"concat"}) == "1012")
|
||||
|
||||
assert(run(function() return a .. b .. c .. a end,
|
||||
{"concat", "concat", "concat"}) == "1012hello10")
|
||||
|
||||
assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
|
||||
{"concat", "concat", "concat"}) == "ab10chello12x")
|
||||
|
||||
|
||||
-- testing yields inside 'for' iterators
|
||||
|
||||
local f = function (s, i)
|
||||
if i%2 == 0 then coroutine.yield(nil, "for") end
|
||||
if i < s then return i + 1 end
|
||||
end
|
||||
|
||||
assert(run(function ()
|
||||
local s = 0
|
||||
for i in f, 4, 0 do s = s + i end
|
||||
return s
|
||||
end, {"for", "for", "for"}) == 10)
|
||||
|
||||
|
||||
return "OK"
|
||||
@@ -0,0 +1,241 @@
|
||||
--[[
|
||||
--*****************************************************************************
|
||||
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
|
||||
--*
|
||||
--* Permission is hereby granted, free of charge, to any person obtaining
|
||||
--* a copy of this software and associated documentation files (the
|
||||
--* "Software"), to deal in the Software without restriction, including
|
||||
--* without limitation the rights to use, copy, modify, merge, publish,
|
||||
--* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
--* permit persons to whom the Software is furnished to do so, subject to
|
||||
--* the following conditions:
|
||||
--*
|
||||
--* The above copyright notice and this permission notice shall be
|
||||
--* included in all copies or substantial portions of the Software.
|
||||
--*
|
||||
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
--*****************************************************************************
|
||||
--]]
|
||||
|
||||
-- testing string library
|
||||
|
||||
local maxi, mini = 0x7fffffffffffffff, 0x8000000000000000
|
||||
|
||||
-- testing string.sub
|
||||
assert(string.sub("123456789",2,4) == "234")
|
||||
assert(string.sub("123456789",7) == "789")
|
||||
assert(string.sub("123456789",7,6) == "")
|
||||
assert(string.sub("123456789",7,7) == "7")
|
||||
assert(string.sub("123456789",0,0) == "")
|
||||
assert(string.sub("123456789",-10,10) == "123456789")
|
||||
assert(string.sub("123456789",1,9) == "123456789")
|
||||
assert(string.sub("123456789",-10,-20) == "")
|
||||
assert(string.sub("123456789",-1) == "9")
|
||||
assert(string.sub("123456789",-4) == "6789")
|
||||
assert(string.sub("123456789",-6, -4) == "456")
|
||||
assert(string.sub("123456789", mini, -4) == "123456")
|
||||
assert(string.sub("123456789", mini, maxi) == "123456789")
|
||||
assert(string.sub("123456789", mini, mini) == "")
|
||||
assert(string.sub("\000123456789",3,5) == "234")
|
||||
assert(("\000123456789"):sub(8) == "789")
|
||||
|
||||
-- testing string.find
|
||||
assert(string.find("123456789", "345") == 3)
|
||||
a,b = string.find("123456789", "345")
|
||||
assert(string.sub("123456789", a, b) == "345")
|
||||
assert(string.find("1234567890123456789", "345", 3) == 3)
|
||||
assert(string.find("1234567890123456789", "345", 4) == 13)
|
||||
assert(string.find("1234567890123456789", "346", 4) == nil)
|
||||
assert(string.find("1234567890123456789", ".45", -9) == 13)
|
||||
assert(string.find("abcdefg", "\0", 5, 1) == nil)
|
||||
assert(string.find("", "") == 1)
|
||||
assert(string.find("", "", 1) == 1)
|
||||
assert(not string.find("", "", 2))
|
||||
assert(string.find('', 'aaa', 1) == nil)
|
||||
assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
|
||||
|
||||
assert(string.len("") == 0)
|
||||
assert(string.len("\0\0\0") == 3)
|
||||
assert(string.len("1234567890") == 10)
|
||||
|
||||
assert(#"" == 0)
|
||||
assert(#"\0\0\0" == 3)
|
||||
assert(#"1234567890" == 10)
|
||||
|
||||
-- testing string.byte/string.char
|
||||
assert(string.byte("a") == 97)
|
||||
assert(string.byte("\xe4") > 127)
|
||||
assert(string.byte(string.char(255)) == 255)
|
||||
assert(string.byte(string.char(0)) == 0)
|
||||
assert(string.byte("\0") == 0)
|
||||
assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
|
||||
assert(string.byte("ba", 2) == 97)
|
||||
assert(string.byte("\n\n", 2, -1) == 10)
|
||||
assert(string.byte("\n\n", 2, 2) == 10)
|
||||
assert(string.byte("") == nil)
|
||||
assert(string.byte("hi", -3) == nil)
|
||||
assert(string.byte("hi", 3) == nil)
|
||||
assert(string.byte("hi", 9, 10) == nil)
|
||||
assert(string.byte("hi", 2, 1) == nil)
|
||||
assert(string.char() == "")
|
||||
assert(string.char(0, 255, 0) == "\0\255\0")
|
||||
assert(string.char(0, string.byte("\xe4"), 0) == "\0\xe4\0")
|
||||
assert(string.char(string.byte("\xe4l\0\195\179u", 1, -1)) == "\xe4l\0\195\179u")
|
||||
assert(string.char(string.byte("\xe4l\0\195\179u", 1, 0)) == "")
|
||||
assert(string.char(string.byte("\xe4l\0\195\179u", -10, 100)) == "\xe4l\0\195\179u")
|
||||
|
||||
assert(string.upper("ab\0c") == "AB\0C")
|
||||
assert(string.lower("\0ABCc%$") == "\0abcc%$")
|
||||
assert(string.rep('teste', 0) == '')
|
||||
assert(string.rep('t\195\169s\00t\195\170', 2) == 't\195\169s\0t\195\170t\195\169s\000t\195\170')
|
||||
assert(string.rep('', 10) == '')
|
||||
|
||||
-- repetitions with separator
|
||||
assert(string.rep('teste', 0, 'xuxu') == '')
|
||||
assert(string.rep('teste', 1, 'xuxu') == 'teste')
|
||||
assert(string.rep('\1\0\1', 2, '\0\0') == '\1\0\1\0\0\1\0\1')
|
||||
assert(string.rep('', 10, '.') == string.rep('.', 9))
|
||||
|
||||
assert(string.reverse"" == "")
|
||||
assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
|
||||
assert(string.reverse"\0001234" == "4321\0")
|
||||
|
||||
for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
|
||||
|
||||
|
||||
x = '"\195\174lo"\n\\'
|
||||
assert(string.format('%q%s', x, x) == '"\\"\195\174lo\\"\\\n\\\\""\195\174lo"\n\\')
|
||||
assert(string.format('%q', "\0") == [["\0"]])
|
||||
x = "\0\1\0023\5\0009"
|
||||
assert(string.format("\0%c\0%c%x\0", string.byte("\xe4"), string.byte("b"), 140) ==
|
||||
"\0\xe4\0b8c\0")
|
||||
assert(string.format('') == "")
|
||||
assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
|
||||
string.format("%c%c%c%c", 34, 48, 90, 100))
|
||||
assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
|
||||
assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
|
||||
x = string.format('"%-50s"', 'a')
|
||||
assert(#x == 52)
|
||||
assert(string.sub(x, 1, 4) == '"a ')
|
||||
|
||||
assert(string.format("-%.20s.20s", string.rep("%", 2000)) ==
|
||||
"-"..string.rep("%", 20)..".20s")
|
||||
assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
|
||||
string.format("%q", "-"..string.rep("%", 2000)..".20s"))
|
||||
|
||||
-- format x tostring
|
||||
assert(string.format("%s %s", nil, true) == "nil true")
|
||||
assert(string.format("%s %.4s", false, true) == "false true")
|
||||
assert(string.format("%.3s %.3s", false, true) == "fal tru")
|
||||
|
||||
|
||||
-- testing large numbers for format
|
||||
do
|
||||
local max, min = 0x7fffffff, -0x80000000 -- "large" for 32 bits
|
||||
assert(string.sub(string.format("%8x", -1), -8) == "ffffffff")
|
||||
assert(string.format("%x", max) == "7fffffff")
|
||||
assert(string.sub(string.format("%x", min), -8) == "80000000")
|
||||
assert(string.format("%d", max) == "2147483647")
|
||||
assert(string.format("%d", min) == "-2147483648")
|
||||
assert(string.format("%u", 0xffffffff) == "4294967295")
|
||||
assert(string.format("%o", 0xABCD) == "125715")
|
||||
|
||||
max, min = 0x7fffffffffffffff, -0x8000000000000000
|
||||
assert(string.format("0x%8X", 0x8f000003) == "0x8F000003")
|
||||
assert(string.format("%d", 2^53) == "9007199254740992")
|
||||
assert(string.format("%x", max) == "7fffffffffffffff")
|
||||
assert(string.format("%x", min) == "8000000000000000")
|
||||
assert(string.format("%d", max) == "9223372036854775807")
|
||||
assert(string.format("%d", min) == "-9223372036854775808")
|
||||
end
|
||||
|
||||
|
||||
assert(table.concat{} == "")
|
||||
assert(table.concat({}, 'x') == "")
|
||||
assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
|
||||
local a = {}; for i=1,300 do a[i] = "xuxu" end
|
||||
assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300))
|
||||
assert(table.concat(a, "b", 20, 20) == "xuxu")
|
||||
assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
|
||||
assert(table.concat(a, "x", 22, 21) == "")
|
||||
assert(table.concat(a, "3", 299) == "xuxu3xuxu")
|
||||
assert(table.concat({}, "x", 2^31-1, 2^31-2) == "")
|
||||
assert(table.concat({}, "x", -2^31+1, -2^31) == "")
|
||||
assert(table.concat({}, "x", 2^31-1, -2^31) == "")
|
||||
assert(table.concat({[2^31-1] = "alo"}, "x", 2^31-1, 2^31-1) == "alo")
|
||||
|
||||
a = {"a","b","c"}
|
||||
assert(table.concat(a, ",", 1, 0) == "")
|
||||
assert(table.concat(a, ",", 1, 1) == "a")
|
||||
assert(table.concat(a, ",", 1, 2) == "a,b")
|
||||
assert(table.concat(a, ",", 2) == "b,c")
|
||||
assert(table.concat(a, ",", 3) == "c")
|
||||
assert(table.concat(a, ",", 4) == "")
|
||||
|
||||
|
||||
-- tests for gmatch
|
||||
local a = 0
|
||||
for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
|
||||
assert(a==6)
|
||||
|
||||
t = {n=0}
|
||||
for w in string.gmatch("first second word", "%w+") do
|
||||
t.n=t.n+1; t[t.n] = w
|
||||
end
|
||||
assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
|
||||
|
||||
t = {3, 6, 9}
|
||||
for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
|
||||
assert(i == table.remove(t, 1))
|
||||
end
|
||||
assert(#t == 0)
|
||||
|
||||
t = {}
|
||||
for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
|
||||
t[i] = j
|
||||
end
|
||||
a = 0
|
||||
for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
|
||||
assert(a == 3)
|
||||
|
||||
|
||||
-- tests for gsub
|
||||
function f1(s, p)
|
||||
p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
|
||||
p = string.gsub(p, "^(^?)", "%1()", 1)
|
||||
p = string.gsub(p, "($?)$", "()%1", 1)
|
||||
local t = {string.match(s, p)}
|
||||
return string.sub(s, t[1], t[#t] - 1)
|
||||
end
|
||||
|
||||
assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
|
||||
assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
|
||||
assert(f1('=======', '^(=*)=%1$') == '=======')
|
||||
|
||||
-- gsub with tables
|
||||
assert(string.gsub("alo alo", ".", {}) == "alo alo")
|
||||
assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
|
||||
assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
|
||||
assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
|
||||
|
||||
assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo")
|
||||
|
||||
t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
|
||||
assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
|
||||
|
||||
|
||||
-- tests for match
|
||||
assert(string.match('==========', '^([=]*)=%1$') == nil)
|
||||
assert(string.match("alo xyzK", "(%w+)K") == "xyz")
|
||||
assert(string.match("254 K", "(%d*)K") == "")
|
||||
assert(string.match("alo ", "(%w*)$") == "")
|
||||
assert(string.match("alo ", "(%w+)$") == nil)
|
||||
assert(string.match("ab\0\1\2c", "[\0-\2]+") == "\0\1\2")
|
||||
|
||||
return "OK"
|
||||
@@ -0,0 +1,252 @@
|
||||
--[[
|
||||
--*****************************************************************************
|
||||
--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
|
||||
--*
|
||||
--* Permission is hereby granted, free of charge, to any person obtaining
|
||||
--* a copy of this software and associated documentation files (the
|
||||
--* "Software"), to deal in the Software without restriction, including
|
||||
--* without limitation the rights to use, copy, modify, merge, publish,
|
||||
--* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
--* permit persons to whom the Software is furnished to do so, subject to
|
||||
--* the following conditions:
|
||||
--*
|
||||
--* The above copyright notice and this permission notice shall be
|
||||
--* included in all copies or substantial portions of the Software.
|
||||
--*
|
||||
--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
--*****************************************************************************
|
||||
--]]
|
||||
|
||||
-- testing table library
|
||||
|
||||
-- workaround missing pcall in zfs lua implementation
|
||||
local function tuple(...)
|
||||
return {n=select('#', ...), ...}
|
||||
end
|
||||
|
||||
function pcall(f, ...)
|
||||
local co = coroutine.create(f)
|
||||
local res = tuple(coroutine.resume(co, ...))
|
||||
if res[1] and coroutine.status(co) == "suspended" then
|
||||
res[1] = false
|
||||
end
|
||||
return table.unpack(res, 1, res.n)
|
||||
end
|
||||
|
||||
|
||||
-- workaround missing math lib in zfs lua implementation
|
||||
local A1, A2 = 727595, 798405 -- 5^17=D20*A1+A2
|
||||
local D20, D40 = 1048576, 1099511627776 -- 2^20, 2^40
|
||||
local X1, X2 = 0, 1
|
||||
function rand()
|
||||
local U = X2*A2
|
||||
local V = (X1*A2 + X2*A1) % D20
|
||||
V = (V*D20 + U) % D40
|
||||
X1 = V/D20
|
||||
X2 = V - X1*D20
|
||||
return V*100/D40
|
||||
end
|
||||
|
||||
|
||||
-- testing unpack
|
||||
|
||||
local unpack = table.unpack
|
||||
|
||||
local x,y,z,a,n
|
||||
a = {}; lim = 2000
|
||||
for i=1, lim do a[i]=i end
|
||||
assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
|
||||
x = unpack(a)
|
||||
assert(x == 1)
|
||||
x = {unpack(a)}
|
||||
assert(#x == lim and x[1] == 1 and x[lim] == lim)
|
||||
x = {unpack(a, lim-2)}
|
||||
assert(#x == 3 and x[1] == lim-2 and x[3] == lim)
|
||||
x = {unpack(a, 10, 6)}
|
||||
assert(next(x) == nil) -- no elements
|
||||
x = {unpack(a, 11, 10)}
|
||||
assert(next(x) == nil) -- no elements
|
||||
x,y = unpack(a, 10, 10)
|
||||
assert(x == 10 and y == nil)
|
||||
x,y,z = unpack(a, 10, 11)
|
||||
assert(x == 10 and y == 11 and z == nil)
|
||||
a,x = unpack{1}
|
||||
assert(a==1 and x==nil)
|
||||
a,x = unpack({1,2}, 1, 1)
|
||||
assert(a==1 and x==nil)
|
||||
|
||||
if not _no32 then
|
||||
assert(not pcall(unpack, {}, 0, 2^31-1))
|
||||
assert(not pcall(unpack, {}, 1, 2^31-1))
|
||||
assert(not pcall(unpack, {}, -(2^31), 2^31-1))
|
||||
assert(not pcall(unpack, {}, -(2^31 - 1), 2^31-1))
|
||||
assert(pcall(unpack, {}, 2^31-1, 0))
|
||||
assert(pcall(unpack, {}, 2^31-1, 1))
|
||||
pcall(unpack, {}, 1, 2^31)
|
||||
a, b = unpack({[2^31-1] = 20}, 2^31-1, 2^31-1)
|
||||
assert(a == 20 and b == nil)
|
||||
a, b = unpack({[2^31-1] = 20}, 2^31-2, 2^31-1)
|
||||
assert(a == nil and b == 20)
|
||||
end
|
||||
|
||||
-- testing pack
|
||||
|
||||
a = table.pack()
|
||||
assert(a[1] == nil and a.n == 0)
|
||||
|
||||
a = table.pack(table)
|
||||
assert(a[1] == table and a.n == 1)
|
||||
|
||||
a = table.pack(nil, nil, nil, nil)
|
||||
assert(a[1] == nil and a.n == 4)
|
||||
|
||||
|
||||
-- testing sort
|
||||
|
||||
|
||||
-- test checks for invalid order functions
|
||||
local function check (t)
|
||||
local function f(a, b) assert(a and b); return true end
|
||||
local s, e = pcall(table.sort, t, f)
|
||||
assert(not s and e:find("invalid order function"))
|
||||
end
|
||||
|
||||
check{1,2,3,4}
|
||||
check{1,2,3,4,5}
|
||||
check{1,2,3,4,5,6}
|
||||
|
||||
|
||||
function check (a, f)
|
||||
f = f or function (x,y) return x<y end;
|
||||
for n = #a, 2, -1 do
|
||||
assert(not f(a[n], a[n-1]))
|
||||
end
|
||||
end
|
||||
|
||||
a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||
"Oct", "Nov", "Dec"}
|
||||
|
||||
table.sort(a)
|
||||
check(a)
|
||||
|
||||
function perm (s, n)
|
||||
n = n or #s
|
||||
if n == 1 then
|
||||
local t = {unpack(s)}
|
||||
table.sort(t)
|
||||
check(t)
|
||||
else
|
||||
for i = 1, n do
|
||||
s[i], s[n] = s[n], s[i]
|
||||
perm(s, n - 1)
|
||||
s[i], s[n] = s[n], s[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
perm{}
|
||||
perm{1}
|
||||
perm{1,2}
|
||||
perm{1,2,3}
|
||||
perm{1,2,3,4}
|
||||
perm{2,2,3,4}
|
||||
perm{1,2,3,4,5}
|
||||
perm{1,2,3,3,5}
|
||||
perm{1,2,3,4,5,6}
|
||||
perm{2,2,3,3,5,6}
|
||||
|
||||
limit = 5000
|
||||
|
||||
a = {}
|
||||
for i=1,limit do
|
||||
a[i] = rand()
|
||||
end
|
||||
|
||||
table.sort(a)
|
||||
check(a)
|
||||
|
||||
table.sort(a)
|
||||
check(a)
|
||||
|
||||
a = {}
|
||||
for i=1,limit do
|
||||
a[i] = rand()
|
||||
end
|
||||
|
||||
i=0
|
||||
table.sort(a, function(x,y) i=i+1; return y<x end)
|
||||
check(a, function(x,y) return y<x end)
|
||||
|
||||
|
||||
table.sort{} -- empty array
|
||||
|
||||
for i=1,limit do a[i] = false end
|
||||
table.sort(a, function(x,y) return nil end)
|
||||
check(a, function(x,y) return nil end)
|
||||
for i,v in pairs(a) do assert(not v or i=='n' and v==limit) end
|
||||
|
||||
A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
|
||||
table.sort(A)
|
||||
check(A)
|
||||
|
||||
tt = {__lt = function (a,b) return a.val < b.val end}
|
||||
a = {}
|
||||
for i=1,10 do a[i] = {val=rand(100)}; setmetatable(a[i], tt); end
|
||||
table.sort(a)
|
||||
check(a, tt.__lt)
|
||||
check(a)
|
||||
|
||||
|
||||
-- test remove
|
||||
local function test (a)
|
||||
table.insert(a, 10); table.insert(a, 2, 20);
|
||||
table.insert(a, 1, -1); table.insert(a, 40);
|
||||
table.insert(a, #a+1, 50)
|
||||
table.insert(a, 2, -2)
|
||||
assert(table.remove(a,1) == -1)
|
||||
assert(table.remove(a,1) == -2)
|
||||
assert(table.remove(a,1) == 10)
|
||||
assert(table.remove(a,1) == 20)
|
||||
assert(table.remove(a,1) == 40)
|
||||
assert(table.remove(a,1) == 50)
|
||||
assert(table.remove(a,1) == nil)
|
||||
end
|
||||
|
||||
a = {n=0, [-7] = "ban"}
|
||||
test(a)
|
||||
assert(a.n == 0 and a[-7] == "ban")
|
||||
|
||||
a = {[-7] = "ban"};
|
||||
test(a)
|
||||
assert(a.n == nil and #a == 0 and a[-7] == "ban")
|
||||
|
||||
|
||||
table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
|
||||
assert(table.remove(a) == 10)
|
||||
assert(table.remove(a) == 20)
|
||||
assert(table.remove(a) == -1)
|
||||
|
||||
a = {'c', 'd'}
|
||||
table.insert(a, 3, 'a')
|
||||
table.insert(a, 'b')
|
||||
assert(table.remove(a, 1) == 'c')
|
||||
assert(table.remove(a, 1) == 'd')
|
||||
assert(table.remove(a, 1) == 'a')
|
||||
assert(table.remove(a, 1) == 'b')
|
||||
assert(#a == 0 and a.n == nil)
|
||||
|
||||
a = {10,20,30,40}
|
||||
assert(a[#a] == 40)
|
||||
assert(table.remove(a, #a) == 40)
|
||||
assert(a[#a] == 30)
|
||||
assert(table.remove(a, 2) == 20)
|
||||
assert(a[#a] == 30 and #a == 2)
|
||||
|
||||
|
||||
return "OK"
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2017 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
|
||||
|
||||
verify_runnable "global"
|
||||
arch=$(uname -m)
|
||||
|
||||
if [[ "$arch" == "sparc64" ]]; then
|
||||
log_note "Skipping lib_base and lib_coroutine on sparc64 to avoid stack overflow"
|
||||
else
|
||||
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_base.lua
|
||||
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_coroutine.lua
|
||||
fi
|
||||
log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_strings.lua
|
||||
log_must_program -m 40000000 $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_table.lua
|
||||
|
||||
log_pass "lua libraries work correctly."
|
||||
Reference in New Issue
Block a user