You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
3.8 KiB
Lua

--- `assert_` macro library support.
-- This module may of course be used on its own; `assert_` merely provides
-- some syntactical sugar for its functionality. It is based on Penlight's
-- `pl.test` module.
-- @module macro.libs.test
local test = {}
local _eq,_tostring
-- very much like tablex.deepcompare from Penlight
function _eq (v1,v2)
if type(v1) ~= type(v2) then return false end
-- if the value isn't a table, or it has defined the equality operator..
local mt = getmetatable(v1)
if (mt and mt.__eq) or type(v1) ~= 'table' then
return v1 == v2
end
-- both values are plain tables
if v1 == v2 then return true end -- they were the same table...
for k1,x1 in pairs(v1) do
local x2 = v2[k1]
if x2 == nil or not _eq(x1,x2) then return false end
end
for k2,x2 in pairs(v2) do
local x1 = v1[k2]
if x1 == nil or not _eq(x1,x2) then return false end
end
return true
end
local function keyv (k)
if type(k) ~= 'string' then
k = '['..k..']'
end
return k
end
function _tostring (val)
local mt = getmetatable(val)
if (mt and mt.__tostring) or type(val) ~= 'table' then
if type(val) == 'string' then
return '"'..tostring(val)..'"'
else
return tostring(val)
end
end
-- dump the table; doesn't need to be pretty!
local res = {}
local function put(s) res[#res+1] = s end
put '{'
for k,v in pairs(val) do
put(keyv(k)..'=')
put(_tostring(v))
put ','
end
table.remove(res) -- remove last ','
put '}'
return table.concat(res)
end
local function _lt (v1,v2) return v1 < v2 end
local function _gt (v1,v2) return v1 > v2 end
local function _match (v1,v2) return v1:match(v2) end
local function _assert (v1,v2,cmp,msg)
if not cmp(v1,v2) then
print('first:',_tostring(v1))
print(msg)
print('second:',_tostring(v2))
error('assertion failed',3)
end
end
--- assert if parameters are not equal. If the values are tables,
-- they will be compared by value.
-- @param v1 given value
-- @param v2 test value
function test.assert_eq (v1,v2)
_assert(v1,v2,_eq,"is not equal to");
end
--- assert if first parameter is not less than second.
-- @param v1 given value
-- @param v2 test value
function test.assert_lt (v1,v2)
_assert(v1,v2,_lt,"is not less than")
end
--- assert if first parameter is not greater than second.
-- @param v1 given value
-- @param v2 test value
function test.assert_gt (v1,v2)
_assert(v1,v2,_gt,"is not greater than")
end
--- assert if first parameter string does not match the second.
-- The condition is `v1:match(v2)`.
-- @param v1 given value
-- @param v2 test value
function test.assert_match (v1,v2)
_assert(v1,v2,_match,"does not match")
end
-- return the error message from a function that raises an error.
-- Will raise an error if the function did not raise an error.
-- @param fun the function
-- @param ... any arguments to the function
-- @return the error message
function test.pcall_no(fun,...)
local ok,err = pcall(fun,...)
if ok then error('expression did not throw error',3) end
return err
end
local tuple = {}
function tuple.__eq (a,b)
if a.n ~= b.n then return false end
for i=1, a.n do
if not _eq(a[i],b[i]) then return false end
end
return true
end
function tuple.__tostring (self)
local ts = {}
for i = 1,self.n do
ts[i] = _tostring(self[i])
end
return '('..table.concat(ts,',')..')'
end
--- create a tuple capturing multiple return values.
-- Equality between tuples means that all of their values are equal;
-- values may be `nil`
-- @param ... any values
-- @return a tuple object
function test.tuple(...)
return setmetatable({n=select('#',...),...},tuple)
end
return test