From 33eca973514addaa92665af28f1f41b4bd92a344 Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Tue, 15 Jul 2008 18:35:38 +0000 Subject: [PATCH] Add argument type checks for basic library functions. --- src/test/errors/args.lua | 126 ++++++++++++++++++++++++++------ src/test/errors/baselibargs.lua | 70 +++++++++++++++++- 2 files changed, 170 insertions(+), 26 deletions(-) diff --git a/src/test/errors/args.lua b/src/test/errors/args.lua index d35942da..3e6245e8 100644 --- a/src/test/errors/args.lua +++ b/src/test/errors/args.lua @@ -1,15 +1,22 @@ -- utilities to check that args of various types pass or fail -- 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' } -somenumber = { 1.23 } -somestrnum = { 'abc', 1.23 } -someboolean = { true } -sometable = { {aa=11,bb=22} } -somefunction = { print } -somenil = { nil } +anylua = { anil, astring, anumber, aboolean, atable, afunction } + +somestring = { astring } +somenumber = { anumber } +somestrnum = { astring, anumber } +someboolean = { aboolean } +sometable = { atable } +somefunction = { afunction } +somenil = { anil } local function contains(set,val) local m = #set @@ -18,7 +25,7 @@ local function contains(set,val) return true end end - return false + return val == nil end local function except(some) @@ -56,6 +63,23 @@ local function signature(name,arglist) return name..'('..table.concat(t,',')..')' 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 n = typesets and #typesets or 0 if n <= 0 then @@ -63,11 +87,9 @@ local function expand(argsets, typesets, ...) return argsets end - local t = typesets[1] - local s = {select(2,unpack(typesets))} - local m = #t - for i=1,m do - expand(argsets, s, t[i], ...) + local s,v = split(typesets) + for i=1,#v do + expand(argsets, s, v[i], ...) end return argsets end @@ -77,6 +99,34 @@ local function arglists(typesets) return ipairs(argsets) 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 ) return loadstring('return '..name)() end @@ -87,15 +137,30 @@ local function invoke( name, arglist ) return pcall(c, unpack(arglist)) 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 function checkallpass( name, typesets ) + subbanner('checkallpass') for i,v in arglists(typesets) do local sig = signature(name,v) local s,e = invoke( name, v ) if s then - print( 'pass', sig ) + print( ok, sig ) else - print( 'fail', sig, e ) + print( fail, sig, e ) end end end @@ -103,31 +168,46 @@ end -- check that all combinations of arguments fail in some way, -- ignore error messages function checkallfail( name, typesets ) + subbanner('checkallfail') for i,v in arglists(typesets) do local sig = signature(name,v) - local s,e,f,g = invoke( name, v ) + local s,e = invoke( name, v ) if not s then - print( 'ok', sig ) + print( ok, sig ) else - print( 'needcheck', sig, e, f, g ) + print( needcheck, sig, e ) 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, -- ignore error messages function checkallerrors( name, typesets, template ) + subbanner('checkallerrors') + template = tostring(template) for i,v in arglists(typesets) do local sig = signature(name,v) - local s,e,f,g = invoke( name, v ) + local s,e = invoke( name, v ) if not s then if string.match(e, template) then - print( 'ok', sig, 'template='..template ) + print( ok, sig, '...'..template..'...' ) else - print( 'badmsg', sig, "template='"..template.."' actual='"..e.."'" ) + print( badmsg, sig, "template='"..template.."' actual='"..e.."'" ) end else - print( 'needcheck', sig, e, f, g ) + print( needcheck, sig, e ) end end end diff --git a/src/test/errors/baselibargs.lua b/src/test/errors/baselibargs.lua index d48ad2ad..4a6f9006 100644 --- a/src/test/errors/baselibargs.lua +++ b/src/test/errors/baselibargs.lua @@ -3,7 +3,71 @@ require 'args' -- 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'}}) -checkallfail('dofile', {notastrnumnil}) -checkallerrors('dofile', {notastrnumnil}, 'bad argument') \ No newline at end of file +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') +