You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.3 KiB
159 lines
4.3 KiB
Lua Easy Mock -- LeMock
|
|
Copyright (C) 2009 Tommy Pettersson <ptp@lysator.liu.se>
|
|
See terms in file COPYRIGHT, or at http://lemock.luaforge.net
|
|
@
|
|
|
|
Class Argv
|
|
##########
|
|
|
|
It is convenient to handle argument lists and return lists as an abstract
|
|
type.
|
|
|
|
<<Userguide Anyargs>>=
|
|
|
|
An //anyarg// is a special argument used when recording, that will match
|
|
any argument during replay. It can appear anywhere and any times in an
|
|
argument list, or as the argument in an assignment, to replace real
|
|
arguments. There is also //anyargs//, which will match any number
|
|
(including zero) of any arguments. Anyargs can only appear as the last
|
|
argument of an argument list. Anyarg and anyargs are handy when the actual
|
|
values of the arguments during replay are unimportant or unknown.
|
|
@
|
|
|
|
new
|
|
---
|
|
|
|
<<Unit test for class Argv method new>>=
|
|
function new_test ()
|
|
Argv:new( Argv.ANYARGS )
|
|
Argv:new( 1, Argv.ANYARGS )
|
|
Argv:new( 1, 2, Argv.ANYARGS )
|
|
end
|
|
function new_anyargs_with_extra_arguments_fails_test ()
|
|
local l = {}
|
|
l['ANYARGS,1'] = { Argv.ANYARGS, 1 }
|
|
l['ANYARGS,ANYARGS' ] = { Argv.ANYARGS, Argv.ANYARGS }
|
|
l['1,ANYARGS,1'] = { 1, Argv.ANYARGS, 1 }
|
|
l['1,ANYARGS,ANYARGS'] = { 1, Argv.ANYARGS, Argv.ANYARGS }
|
|
for msg, args in pairs( l ) do
|
|
local ok, err = pcall( function() Argv:new( unpack(args) ) end )
|
|
assert_false( ok, "Bad ANYARGS accepted for "..msg )
|
|
assert_match( "ANYARGS not at end", err )
|
|
end
|
|
end
|
|
|
|
<<Class Argv method new>>=
|
|
function Argv:new (...)
|
|
local av = object( self )
|
|
av.v = {...}
|
|
av.len = select('#',...)
|
|
for i = 1, av.len - 1 do
|
|
if av.v[i] == Argv.ANYARGS then
|
|
error( "ANYARGS not at end.", 0 )
|
|
end
|
|
end
|
|
return av
|
|
end
|
|
@
|
|
|
|
equal
|
|
-----
|
|
|
|
<<Unit test for class Argv method equal>>=
|
|
local l = {}
|
|
local function p (...) l[#l+1] = { n=select('#',...), ... } end
|
|
p() p(nil) p(nil,nil) p(false) p({}) p(false,nil,{},nil) p(nil,p)
|
|
p(true) p(0.1,'','a') p(1/0,nil,0/0) p(0/0) p(0/0, true) p(0/0, false)
|
|
function equal_test ()
|
|
local a1, a2, f, op
|
|
for i = 1, #l do
|
|
ai = Argv:new( unpack( l[i], 1, l[i].n ))
|
|
for j = 1, #l do
|
|
aj = Argv:new( unpack( l[j], 1, l[j].n ))
|
|
if i == j then
|
|
f, op = assert_true, ') ~= ('
|
|
else
|
|
f, op = assert_false, ') == ('
|
|
end
|
|
f( ai:equal(aj), '('..ai:tostring()..op..aj:tostring()..')' )
|
|
end
|
|
end
|
|
end
|
|
function equal_anyargs_test ()
|
|
local a, b = {}, {}
|
|
a[1] = Argv:new( Argv.ANYARGS )
|
|
a[2] = Argv:new( 6, Argv.ANYARGS )
|
|
a[3] = Argv:new( 6, 5, Argv.ANYARGS )
|
|
for i = 1, #l do
|
|
b[1] = Argv:new( unpack( l[i], 1, l[i].n ))
|
|
b[2] = Argv:new( 6, unpack( l[i], 1, l[i].n ))
|
|
b[3] = Argv:new( 6, 5, unpack( l[i], 1, l[i].n ))
|
|
for j = 1, 3 do
|
|
local astr = '('..a[j]:tostring()..')'
|
|
local bstr = '('..b[j]:tostring()..')'
|
|
assert_true( a[j]:equal(b[j]), astr..' ~= '..bstr )
|
|
assert_true( b[j]:equal(a[j]), bstr..' ~= '..astr )
|
|
end
|
|
end
|
|
end
|
|
function equal_anyarg_test ()
|
|
local l = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
|
|
local a1 = Argv:new( unpack(l) )
|
|
for i = 1, 9 do
|
|
l[i] = Argv.ANYARG
|
|
local a2 = Argv:new( unpack(l) )
|
|
assert_true( a1:equal(a2) )
|
|
assert_true( a2:equal(a1) )
|
|
l[i] = i
|
|
end
|
|
end
|
|
@
|
|
The comparison with ANYARGS is a bit tricky, because it must match the
|
|
empty list. The list //excluding// the final ANYARGS argument (its length
|
|
minus one) must match the other list.
|
|
|
|
ANYARG and ANYARGS are created as unique identifiers, with local aliases
|
|
for speed.
|
|
|
|
<<Class Argv method equal>>=
|
|
Argv.ANYARGS = newproxy() local ANYARGS = Argv.ANYARGS
|
|
Argv.ANYARG = newproxy() local ANYARG = Argv.ANYARG
|
|
function Argv:equal (other)
|
|
local a1, n1 = self.v, self.len
|
|
local a2, n2 = other.v, other.len
|
|
if n1-1 <= n2 and a1[n1] == ANYARGS then
|
|
n1 = n1-1
|
|
n2 = n1
|
|
elseif n2-1 <= n1 and a2[n2] == ANYARGS then
|
|
n2 = n2-1
|
|
n1 = n2
|
|
end
|
|
if n1 ~= n2 then
|
|
return false
|
|
end
|
|
for i = 1, n1 do
|
|
local v1, v2 = a1[i], a2[i]
|
|
if not value_equal(v1,v2) and v1 ~= ANYARG and v2 ~= ANYARG then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
@
|
|
|
|
unpack
|
|
------
|
|
|
|
<<Unit test for class Argv method unpack>>=
|
|
function unpack_test ()
|
|
local a, b, c = Argv:new( false, nil, 7 ):unpack()
|
|
assert_equal( false, a )
|
|
assert_equal( nil, b )
|
|
assert_equal( 7, c )
|
|
end
|
|
|
|
<<Class Argv method unpack>>=
|
|
function Argv:unpack ()
|
|
return unpack( self.v, 1, self.len )
|
|
end
|