Add argument type checks for basic library functions.
This commit is contained in:
@@ -1,15 +1,22 @@
|
|||||||
-- utilities to check that args of various types pass or fail
|
-- utilities to check that args of various types pass or fail
|
||||||
-- argument type checking
|
-- argument type checking
|
||||||
|
|
||||||
anylua = { nil, 'abc', 1.23, true, {aa=11,bb==22}, print }
|
astring = 'abc'
|
||||||
|
anumber = 1.23
|
||||||
|
aboolean = true
|
||||||
|
atable = {aa=11,bb=22}
|
||||||
|
afunction = function() end
|
||||||
|
anil = nil
|
||||||
|
|
||||||
somestring = { 'abc' }
|
anylua = { anil, astring, anumber, aboolean, atable, afunction }
|
||||||
somenumber = { 1.23 }
|
|
||||||
somestrnum = { 'abc', 1.23 }
|
somestring = { astring }
|
||||||
someboolean = { true }
|
somenumber = { anumber }
|
||||||
sometable = { {aa=11,bb=22} }
|
somestrnum = { astring, anumber }
|
||||||
somefunction = { print }
|
someboolean = { aboolean }
|
||||||
somenil = { nil }
|
sometable = { atable }
|
||||||
|
somefunction = { afunction }
|
||||||
|
somenil = { anil }
|
||||||
|
|
||||||
local function contains(set,val)
|
local function contains(set,val)
|
||||||
local m = #set
|
local m = #set
|
||||||
@@ -18,7 +25,7 @@ local function contains(set,val)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return false
|
return val == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local function except(some)
|
local function except(some)
|
||||||
@@ -56,6 +63,23 @@ local function signature(name,arglist)
|
|||||||
return name..'('..table.concat(t,',')..')'
|
return name..'('..table.concat(t,',')..')'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function dup(t)
|
||||||
|
local s = {}
|
||||||
|
for i=1,#t do
|
||||||
|
s[i] = t[i]
|
||||||
|
end
|
||||||
|
return s
|
||||||
|
end
|
||||||
|
|
||||||
|
local function split(t)
|
||||||
|
local s = {}
|
||||||
|
local n = #t
|
||||||
|
for i=1,n-1 do
|
||||||
|
s[i] = t[i]
|
||||||
|
end
|
||||||
|
return s,t[n]
|
||||||
|
end
|
||||||
|
|
||||||
local function expand(argsets, typesets, ...)
|
local function expand(argsets, typesets, ...)
|
||||||
local n = typesets and #typesets or 0
|
local n = typesets and #typesets or 0
|
||||||
if n <= 0 then
|
if n <= 0 then
|
||||||
@@ -63,11 +87,9 @@ local function expand(argsets, typesets, ...)
|
|||||||
return argsets
|
return argsets
|
||||||
end
|
end
|
||||||
|
|
||||||
local t = typesets[1]
|
local s,v = split(typesets)
|
||||||
local s = {select(2,unpack(typesets))}
|
for i=1,#v do
|
||||||
local m = #t
|
expand(argsets, s, v[i], ...)
|
||||||
for i=1,m do
|
|
||||||
expand(argsets, s, t[i], ...)
|
|
||||||
end
|
end
|
||||||
return argsets
|
return argsets
|
||||||
end
|
end
|
||||||
@@ -77,6 +99,34 @@ local function arglists(typesets)
|
|||||||
return ipairs(argsets)
|
return ipairs(argsets)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local function expand(arglists,fixed,varying,...)
|
||||||
|
for i=1,#varying do
|
||||||
|
local f = dup(fixed)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function arglists(typesets)
|
||||||
|
local argsets = {}
|
||||||
|
local args={}
|
||||||
|
local n = typesets and #typesets or 0
|
||||||
|
if n == 0 then
|
||||||
|
table.insert( argsets, args )
|
||||||
|
end
|
||||||
|
for i=1,n do
|
||||||
|
local t = typesets[i]
|
||||||
|
for j=1,#t do
|
||||||
|
args[i] = t[j]
|
||||||
|
if i == n then
|
||||||
|
table.insert( argsets, duptable(args) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ipairs(argsets)
|
||||||
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
local function lookup( name )
|
local function lookup( name )
|
||||||
return loadstring('return '..name)()
|
return loadstring('return '..name)()
|
||||||
end
|
end
|
||||||
@@ -87,15 +137,30 @@ local function invoke( name, arglist )
|
|||||||
return pcall(c, unpack(arglist))
|
return pcall(c, unpack(arglist))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- messages, banners
|
||||||
|
function banner(name)
|
||||||
|
print( '====== '..tostring(name)..' ======' )
|
||||||
|
end
|
||||||
|
|
||||||
|
local function subbanner(name)
|
||||||
|
print( '--- '..tostring(name) )
|
||||||
|
end
|
||||||
|
|
||||||
|
local ok = 'ok '
|
||||||
|
local fail = 'fail '
|
||||||
|
local needcheck = 'needcheck '
|
||||||
|
local badmsg = 'badmsg '
|
||||||
|
|
||||||
-- check that all combinations of arguments pass
|
-- check that all combinations of arguments pass
|
||||||
function checkallpass( name, typesets )
|
function checkallpass( name, typesets )
|
||||||
|
subbanner('checkallpass')
|
||||||
for i,v in arglists(typesets) do
|
for i,v in arglists(typesets) do
|
||||||
local sig = signature(name,v)
|
local sig = signature(name,v)
|
||||||
local s,e = invoke( name, v )
|
local s,e = invoke( name, v )
|
||||||
if s then
|
if s then
|
||||||
print( 'pass', sig )
|
print( ok, sig )
|
||||||
else
|
else
|
||||||
print( 'fail', sig, e )
|
print( fail, sig, e )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -103,31 +168,46 @@ end
|
|||||||
-- check that all combinations of arguments fail in some way,
|
-- check that all combinations of arguments fail in some way,
|
||||||
-- ignore error messages
|
-- ignore error messages
|
||||||
function checkallfail( name, typesets )
|
function checkallfail( name, typesets )
|
||||||
|
subbanner('checkallfail')
|
||||||
for i,v in arglists(typesets) do
|
for i,v in arglists(typesets) do
|
||||||
local sig = signature(name,v)
|
local sig = signature(name,v)
|
||||||
local s,e,f,g = invoke( name, v )
|
local s,e = invoke( name, v )
|
||||||
if not s then
|
if not s then
|
||||||
print( 'ok', sig )
|
print( ok, sig )
|
||||||
else
|
else
|
||||||
print( 'needcheck', sig, e, f, g )
|
print( needcheck, sig, e )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function checkfail( name, ... )
|
||||||
|
subbanner('checkfail')
|
||||||
|
local v = {...}
|
||||||
|
local sig = signature(name,v)
|
||||||
|
local s,e = invoke( name, v )
|
||||||
|
if not s then
|
||||||
|
print( ok, sig )
|
||||||
|
else
|
||||||
|
print( needcheck, sig, e )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- check that all combinations of arguments fail in some way,
|
-- check that all combinations of arguments fail in some way,
|
||||||
-- ignore error messages
|
-- ignore error messages
|
||||||
function checkallerrors( name, typesets, template )
|
function checkallerrors( name, typesets, template )
|
||||||
|
subbanner('checkallerrors')
|
||||||
|
template = tostring(template)
|
||||||
for i,v in arglists(typesets) do
|
for i,v in arglists(typesets) do
|
||||||
local sig = signature(name,v)
|
local sig = signature(name,v)
|
||||||
local s,e,f,g = invoke( name, v )
|
local s,e = invoke( name, v )
|
||||||
if not s then
|
if not s then
|
||||||
if string.match(e, template) then
|
if string.match(e, template) then
|
||||||
print( 'ok', sig, 'template='..template )
|
print( ok, sig, '...'..template..'...' )
|
||||||
else
|
else
|
||||||
print( 'badmsg', sig, "template='"..template.."' actual='"..e.."'" )
|
print( badmsg, sig, "template='"..template.."' actual='"..e.."'" )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print( 'needcheck', sig, e, f, g )
|
print( needcheck, sig, e )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,7 +3,71 @@ require 'args'
|
|||||||
|
|
||||||
|
|
||||||
-- arg types for basic library functions
|
-- arg types for basic library functions
|
||||||
local notastrnumnil={true,{},print}
|
local somestrnumnil={anil,astring,anumber}
|
||||||
|
local notastrnumnil={aboolean,atable,afunction}
|
||||||
|
|
||||||
|
-- assert
|
||||||
|
banner('assert')
|
||||||
|
checkallpass('assert',{{true,123},anylua})
|
||||||
|
checkallfail('assert',{{nil,false},{nil,'message'}})
|
||||||
|
checkallerrors('assert',{{nil,false},{nil}},'assertion failed')
|
||||||
|
checkallerrors('assert',{{nil,false},{'message'}},'message')
|
||||||
|
|
||||||
|
-- collectgarbage
|
||||||
|
banner('collectgarbage')
|
||||||
|
checkallpass('collectgarbage',{{'collect','count'}})
|
||||||
|
checkallerrors('collectgarbage',{notanil},'bad argument')
|
||||||
|
|
||||||
|
-- dofila
|
||||||
|
banner('dofile')
|
||||||
checkallpass('dofile', {{nil,'src/test/errors/args.lua','args.lua'}})
|
checkallpass('dofile', {{nil,'src/test/errors/args.lua','args.lua'}})
|
||||||
checkallfail('dofile', {notastrnumnil})
|
checkallerrors('dofile', {notastrnumnil}, 'bad argument')
|
||||||
checkallerrors('dofile', {notastrnumnil}, 'bad argument')
|
|
||||||
|
-- error
|
||||||
|
banner('error')
|
||||||
|
checkallfail('error', {anylua,{nil,0,1,2}})
|
||||||
|
checkallerrors('dofile', {{'message'},{nil,0,1,2}}, 'message')
|
||||||
|
checkallerrors('dofile', {{123},{nil,1,2}}, 123)
|
||||||
|
|
||||||
|
-- getfenv
|
||||||
|
banner('getfenv')
|
||||||
|
checkallpass('getfenv', {{nil,print,function()end,0,1,2}})
|
||||||
|
checkallerrors('getfenv', {{true,{},'abc'}}, 'bad argument')
|
||||||
|
|
||||||
|
-- getmetatable
|
||||||
|
banner('getmetatable')
|
||||||
|
checkallpass('getmetatable', {notanil})
|
||||||
|
checkfail('getmetatable',nil)
|
||||||
|
|
||||||
|
-- ipairs
|
||||||
|
banner('ipairs')
|
||||||
|
checkallpass('ipairs', {sometable})
|
||||||
|
checkallerrors('ipairs', {notatable}, 'bad argument')
|
||||||
|
|
||||||
|
-- load
|
||||||
|
banner('load')
|
||||||
|
checkallpass('load', {somefunction,{anil,astring}})
|
||||||
|
checkallerrors('load', {notafunction,{anil,astring,anumber}}, 'bad argument')
|
||||||
|
checkallerrors('load', {somefunction,{afunction,atable}}, 'bad argument')
|
||||||
|
|
||||||
|
-- loadfile
|
||||||
|
banner('loadfile')
|
||||||
|
checkallerrors('loadfile', {notastring}, 'bad argument')
|
||||||
|
|
||||||
|
-- loadstring
|
||||||
|
banner('loadstring')
|
||||||
|
checkallpass('loadstring', {{'return'},{anil,astring}})
|
||||||
|
checkallerrors('loadstring', {notastring,{anil,astring,anumber}}, 'bad argument')
|
||||||
|
checkallerrors('loadstring', {{'return'},{afunction,atable}}, 'bad argument')
|
||||||
|
|
||||||
|
-- next
|
||||||
|
banner('next')
|
||||||
|
checkallpass('next', {{{aa=11}},{nil,'aa'}})
|
||||||
|
checkallerrors('next', {notatable,{nil,1}}, 'bad argument')
|
||||||
|
checkallerrors('next', {sometable,{astring,afunction,atable}}, 'invalid key')
|
||||||
|
|
||||||
|
-- pairs
|
||||||
|
banner('pairs')
|
||||||
|
checkallpass('pairs', {sometable})
|
||||||
|
checkallerrors('pairs', {notatable}, 'bad argument')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user