mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-29 00:07:58 +03:00

* Add portable ldoc compiler and build event * Remove broken ldoc compiler * Remove unneeded file, remove timestamp * Update documentation
164 lines
5 KiB
Lua
164 lines
5 KiB
Lua
--- Useful test utilities.
|
|
--
|
|
-- test.asserteq({1,2},{1,2}) -- can compare tables
|
|
-- test.asserteq(1.2,1.19,0.02) -- compare FP numbers within precision
|
|
-- T = test.tuple -- used for comparing multiple results
|
|
-- test.asserteq(T(string.find(" me","me")),T(2,3))
|
|
--
|
|
-- Dependencies: `pl.utils`, `pl.tablex`, `pl.pretty`, `pl.path`, `debug`
|
|
-- @module pl.test
|
|
|
|
local tablex = require 'pl.tablex'
|
|
local utils = require 'pl.utils'
|
|
local pretty = require 'pl.pretty'
|
|
local path = require 'pl.path'
|
|
local type,unpack,pack = type,utils.unpack,utils.pack
|
|
local clock = os.clock
|
|
local debug = require 'debug'
|
|
local io = io
|
|
|
|
local function dump(x)
|
|
if type(x) == 'table' and not (getmetatable(x) and getmetatable(x).__tostring) then
|
|
return pretty.write(x,' ',true)
|
|
elseif type(x) == 'string' then
|
|
return '"'..x..'"'
|
|
else
|
|
return tostring(x)
|
|
end
|
|
end
|
|
|
|
local test = {}
|
|
|
|
---- error handling for test results.
|
|
-- By default, this writes to stderr and exits the program.
|
|
-- Re-define this function to raise an error and/or redirect output
|
|
function test.error_handler(file,line,got_text, needed_text,msg)
|
|
local err = io.stderr
|
|
err:write(path.basename(file)..':'..line..': assertion failed\n')
|
|
err:write("got:\t",got_text,'\n')
|
|
err:write("needed:\t",needed_text,'\n')
|
|
utils.quit(1,msg or "these values were not equal")
|
|
end
|
|
|
|
local function complain (x,y,msg,where)
|
|
local i = debug.getinfo(3 + (where or 0))
|
|
test.error_handler(i.short_src,i.currentline,dump(x),dump(y),msg)
|
|
end
|
|
|
|
--- general test complain message.
|
|
-- Useful for composing new test functions (see tests/tablex.lua for an example)
|
|
-- @param x a value
|
|
-- @param y value to compare first value against
|
|
-- @param msg message
|
|
-- @param where extra level offset for errors
|
|
-- @function complain
|
|
test.complain = complain
|
|
|
|
--- like assert, except takes two arguments that must be equal and can be tables.
|
|
-- If they are plain tables, it will use tablex.deepcompare.
|
|
-- @param x any value
|
|
-- @param y a value equal to x
|
|
-- @param eps an optional tolerance for numerical comparisons
|
|
-- @param where extra level offset
|
|
function test.asserteq (x,y,eps,where)
|
|
local res = x == y
|
|
if not res then
|
|
res = tablex.deepcompare(x,y,true,eps)
|
|
end
|
|
if not res then
|
|
complain(x,y,nil,where)
|
|
end
|
|
end
|
|
|
|
--- assert that the first string matches the second.
|
|
-- @param s1 a string
|
|
-- @param s2 a string
|
|
-- @param where extra level offset
|
|
function test.assertmatch (s1,s2,where)
|
|
if not s1:match(s2) then
|
|
complain (s1,s2,"these strings did not match",where)
|
|
end
|
|
end
|
|
|
|
--- assert that the function raises a particular error.
|
|
-- @param fn a function or a table of the form {function,arg1,...}
|
|
-- @param e a string to match the error against
|
|
-- @param where extra level offset
|
|
function test.assertraise(fn,e,where)
|
|
local ok, err
|
|
if type(fn) == 'table' then
|
|
ok, err = pcall(unpack(fn))
|
|
else
|
|
ok, err = pcall(fn)
|
|
end
|
|
if ok or err:match(e)==nil then
|
|
complain (err,e,"these errors did not match",where)
|
|
end
|
|
end
|
|
|
|
--- a version of asserteq that takes two pairs of values.
|
|
-- <code>x1==y1 and x2==y2</code> must be true. Useful for functions that naturally
|
|
-- return two values.
|
|
-- @param x1 any value
|
|
-- @param x2 any value
|
|
-- @param y1 any value
|
|
-- @param y2 any value
|
|
-- @param where extra level offset
|
|
function test.asserteq2 (x1,x2,y1,y2,where)
|
|
if x1 ~= y1 then complain(x1,y1,nil,where) end
|
|
if x2 ~= y2 then complain(x2,y2,nil,where) end
|
|
end
|
|
|
|
-- tuple type --
|
|
|
|
local tuple_mt = {
|
|
unpack = unpack
|
|
}
|
|
tuple_mt.__index = tuple_mt
|
|
|
|
function tuple_mt.__tostring(self)
|
|
local ts = {}
|
|
for i=1, self.n do
|
|
local s = self[i]
|
|
ts[i] = type(s) == 'string' and ('%q'):format(s) or tostring(s)
|
|
end
|
|
return 'tuple(' .. table.concat(ts, ', ') .. ')'
|
|
end
|
|
|
|
function tuple_mt.__eq(a, b)
|
|
if a.n ~= b.n then return false end
|
|
for i=1, a.n do
|
|
if a[i] ~= b[i] then return false end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function tuple_mt.__len(self)
|
|
return self.n
|
|
end
|
|
|
|
--- encode an arbitrary argument list as a tuple.
|
|
-- This can be used to compare to other argument lists, which is
|
|
-- very useful for testing functions which return a number of values.
|
|
-- Unlike regular array-like tables ('sequences') they may contain nils.
|
|
-- Tuples understand equality and know how to print themselves out.
|
|
-- The # operator is defined to be the size, irrespecive of any nils,
|
|
-- and there is an `unpack` method.
|
|
-- @usage asserteq(tuple( ('ab'):find 'a'), tuple(1,1))
|
|
function test.tuple(...)
|
|
return setmetatable(pack(...), tuple_mt)
|
|
end
|
|
|
|
--- Time a function. Call the function a given number of times, and report the number of seconds taken,
|
|
-- together with a message. Any extra arguments will be passed to the function.
|
|
-- @string msg a descriptive message
|
|
-- @int n number of times to call the function
|
|
-- @func fun the function
|
|
-- @param ... optional arguments to fun
|
|
function test.timer(msg,n,fun,...)
|
|
local start = clock()
|
|
for i = 1,n do fun(...) end
|
|
utils.printf("%s: took %7.2f sec\n",msg,clock()-start)
|
|
end
|
|
|
|
return test
|