lunit is unmaintained since ~2011. Switch to u-test [1] instead which seems to be more actively maintained. [1]: https://github.com/IUdalov/u-testdev
parent
0d852d7aac
commit
4a5349be96
@ -1,128 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
|
|
||||||
# This file is part of lunit 0.5.
|
|
||||||
#
|
|
||||||
# For Details about lunit look at: http://www.mroth.net/lunit/
|
|
||||||
#
|
|
||||||
# Author: Michael Roth <mroth@nessie.de>
|
|
||||||
#
|
|
||||||
# Copyright (c) 2004-2009 Michael Roth <mroth@nessie.de>
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person
|
|
||||||
# obtaining a copy of this software and associated documentation
|
|
||||||
# files (the "Software"), to deal in the Software without restriction,
|
|
||||||
# including without limitation the rights to use, copy, modify, merge,
|
|
||||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
# and to permit persons to whom the Software is furnished to do so,
|
|
||||||
# subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be
|
|
||||||
# included in all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
|
|
||||||
if test $# = 0 ; then
|
|
||||||
echo "$0: Usage Error. Try $0 --help" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ `uname` = "Darwin" ]; then
|
|
||||||
scriptname="$(readlink -n "$0")"
|
|
||||||
else
|
|
||||||
scriptname="$(readlink -n -f "$0")"
|
|
||||||
fi
|
|
||||||
interpreter="lua"
|
|
||||||
options=""
|
|
||||||
|
|
||||||
while true ; do
|
|
||||||
case "$1" in
|
|
||||||
-h|--help)
|
|
||||||
cat <<EOT
|
|
||||||
lunit 0.5
|
|
||||||
Copyright (c) 2004-2009 Michael Roth <mroth@nessie.de>
|
|
||||||
This program comes WITHOUT WARRANTY OF ANY KIND.
|
|
||||||
|
|
||||||
Usage: lunit [OPTIONS] [--] scripts
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
-i, --interpreter LUA Complete path of the lua binary to use.
|
|
||||||
-p, --path PATH Sets the LUA_PATH environment for the tests.
|
|
||||||
--cpath CPATH Sets the LUA_CPATH environment for the tests.
|
|
||||||
-r, --runner RUNNER Testrunner to use, defaults to 'lunit-console'.
|
|
||||||
-t, --test PATTERN Which tests to run, may contain * or ? wildcards.
|
|
||||||
--loadonly Only load the tests.
|
|
||||||
--dontforce Do not force to load $scriptname*.lua.
|
|
||||||
-h, --help Print this help screen.
|
|
||||||
--version Print lunit version.
|
|
||||||
|
|
||||||
Please report bugs to <mroth@nessie.de>.
|
|
||||||
EOT
|
|
||||||
exit ;;
|
|
||||||
|
|
||||||
--version)
|
|
||||||
echo "lunit 0.5 Copyright 2004-2009 Michael Roth <mroth@nessie.de>"
|
|
||||||
exit ;;
|
|
||||||
|
|
||||||
-i|--interpreter)
|
|
||||||
interpreter="$2"
|
|
||||||
shift 2 ;;
|
|
||||||
|
|
||||||
-p|--path)
|
|
||||||
LUA_PATH="$2"
|
|
||||||
export LUA_PATH
|
|
||||||
shift 2 ;;
|
|
||||||
|
|
||||||
--cpath)
|
|
||||||
LUA_CPATH="$2"
|
|
||||||
export LUA_CPATH
|
|
||||||
shift 2 ;;
|
|
||||||
|
|
||||||
--loadonly)
|
|
||||||
options="$options $1"
|
|
||||||
shift 1 ;;
|
|
||||||
|
|
||||||
--dontforce)
|
|
||||||
scriptname=""
|
|
||||||
shift 1 ;;
|
|
||||||
|
|
||||||
-r|--runner|-t|--test)
|
|
||||||
options="$options $1 $2"
|
|
||||||
shift 2 ;;
|
|
||||||
|
|
||||||
--)
|
|
||||||
break ;;
|
|
||||||
|
|
||||||
-*)
|
|
||||||
echo "$0: Invalid option: $1" >&2
|
|
||||||
exit 1 ;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
break ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
|
|
||||||
exec "$interpreter" - "$scriptname" $options "$@" <<EOT
|
|
||||||
local scriptname = ...
|
|
||||||
local argv = { select(2,...) }
|
|
||||||
if scriptname ~= "" then
|
|
||||||
local function force(name)
|
|
||||||
pcall( function() loadfile(name)() end )
|
|
||||||
end
|
|
||||||
force( scriptname..".lua" )
|
|
||||||
force( scriptname.."-console.lua" )
|
|
||||||
end
|
|
||||||
require "lunit"
|
|
||||||
local stats = lunit.main(argv)
|
|
||||||
if stats.errors > 0 or stats.failed > 0 then
|
|
||||||
os.exit(1)
|
|
||||||
end
|
|
||||||
EOT
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
|
|
||||||
--[[--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This file is part of lunit 0.5.
|
|
||||||
|
|
||||||
For Details about lunit look at: http://www.mroth.net/lunit/
|
|
||||||
|
|
||||||
Author: Michael Roth <mroth@nessie.de>
|
|
||||||
|
|
||||||
Copyright (c) 2006-2008 Michael Roth <mroth@nessie.de>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation
|
|
||||||
files (the "Software"), to deal in the Software without restriction,
|
|
||||||
including without limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
--]]--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--[[
|
|
||||||
|
|
||||||
begin()
|
|
||||||
run(testcasename, testname)
|
|
||||||
err(fullname, message, traceback)
|
|
||||||
fail(fullname, where, message, usermessage)
|
|
||||||
pass(testcasename, testname)
|
|
||||||
done()
|
|
||||||
|
|
||||||
Fullname:
|
|
||||||
testcase.testname
|
|
||||||
testcase.testname:setupname
|
|
||||||
testcase.testname:teardownname
|
|
||||||
|
|
||||||
--]]
|
|
||||||
|
|
||||||
|
|
||||||
require "lunit"
|
|
||||||
|
|
||||||
module( "lunit-console", package.seeall )
|
|
||||||
|
|
||||||
|
|
||||||
local function printformat(format, ...)
|
|
||||||
io.write( string.format(format, ...) )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local columns_printed = 0
|
|
||||||
|
|
||||||
local function writestatus(char)
|
|
||||||
if columns_printed == 0 then
|
|
||||||
io.write(" ")
|
|
||||||
end
|
|
||||||
if columns_printed == 60 then
|
|
||||||
io.write("\n ")
|
|
||||||
columns_printed = 0
|
|
||||||
end
|
|
||||||
io.write(char)
|
|
||||||
io.flush()
|
|
||||||
columns_printed = columns_printed + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local msgs = {}
|
|
||||||
|
|
||||||
|
|
||||||
function begin()
|
|
||||||
local total_tc = 0
|
|
||||||
local total_tests = 0
|
|
||||||
|
|
||||||
for tcname in lunit.testcases() do
|
|
||||||
total_tc = total_tc + 1
|
|
||||||
for testname, test in lunit.tests(tcname) do
|
|
||||||
total_tests = total_tests + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
printformat("Loaded testsuite with %d tests in %d testcases.\n\n", total_tests, total_tc)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function run(testcasename, testname)
|
|
||||||
-- NOP
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function err(fullname, message, traceback)
|
|
||||||
writestatus("E")
|
|
||||||
msgs[#msgs+1] = "Error! ("..fullname.."):\n"..message.."\n\t"..table.concat(traceback, "\n\t") .. "\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function fail(fullname, where, message, usermessage)
|
|
||||||
writestatus("F")
|
|
||||||
local text = "Failure ("..fullname.."):\n"..
|
|
||||||
where..": "..message.."\n"
|
|
||||||
|
|
||||||
if usermessage then
|
|
||||||
text = text .. where..": "..usermessage.."\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
msgs[#msgs+1] = text
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function pass(testcasename, testname)
|
|
||||||
writestatus(".")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function done()
|
|
||||||
printformat("\n\n%d Assertions checked.\n", lunit.stats.assertions )
|
|
||||||
print()
|
|
||||||
|
|
||||||
for i, msg in ipairs(msgs) do
|
|
||||||
printformat( "%3d) %s\n", i, msg )
|
|
||||||
end
|
|
||||||
|
|
||||||
printformat("Testsuite finished (%d passed, %d failed, %d errors).\n",
|
|
||||||
lunit.stats.passed, lunit.stats.failed, lunit.stats.errors )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,682 +0,0 @@
|
|||||||
|
|
||||||
--[[--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
This file is part of lunit 0.5.
|
|
||||||
|
|
||||||
For Details about lunit look at: http://www.mroth.net/lunit/
|
|
||||||
|
|
||||||
Author: Michael Roth <mroth@nessie.de>
|
|
||||||
|
|
||||||
Copyright (c) 2004, 2006-2009 Michael Roth <mroth@nessie.de>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
|
||||||
obtaining a copy of this software and associated documentation
|
|
||||||
files (the "Software"), to deal in the Software without restriction,
|
|
||||||
including without limitation the rights to use, copy, modify, merge,
|
|
||||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
||||||
and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
--]]--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local orig_assert = assert
|
|
||||||
|
|
||||||
local pairs = pairs
|
|
||||||
local ipairs = ipairs
|
|
||||||
local next = next
|
|
||||||
local type = type
|
|
||||||
local error = error
|
|
||||||
local tostring = tostring
|
|
||||||
|
|
||||||
local string_sub = string.sub
|
|
||||||
local string_format = string.format
|
|
||||||
|
|
||||||
|
|
||||||
module("lunit", package.seeall) -- FIXME: Remove package.seeall
|
|
||||||
|
|
||||||
local lunit = _M
|
|
||||||
|
|
||||||
local __failure__ = {} -- Type tag for failed assertions
|
|
||||||
|
|
||||||
local typenames = { "nil", "boolean", "number", "string", "table", "function", "thread", "userdata" }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local traceback_hide -- Traceback function which hides lunit internals
|
|
||||||
local mypcall -- Protected call to a function with own traceback
|
|
||||||
do
|
|
||||||
local _tb_hide = setmetatable( {}, {__mode="k"} )
|
|
||||||
|
|
||||||
function traceback_hide(func)
|
|
||||||
_tb_hide[func] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function my_traceback(errobj)
|
|
||||||
if is_table(errobj) and errobj.type == __failure__ then
|
|
||||||
local info = debug.getinfo(5, "Sl") -- FIXME: Hardcoded integers are bad...
|
|
||||||
errobj.where = string_format( "%s:%d", info.short_src, info.currentline)
|
|
||||||
else
|
|
||||||
errobj = { msg = tostring(errobj) }
|
|
||||||
errobj.tb = {}
|
|
||||||
local i = 2
|
|
||||||
while true do
|
|
||||||
local info = debug.getinfo(i, "Snlf")
|
|
||||||
if not is_table(info) then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if not _tb_hide[info.func] then
|
|
||||||
local line = {} -- Ripped from ldblib.c...
|
|
||||||
line[#line+1] = string_format("%s:", info.short_src)
|
|
||||||
if info.currentline > 0 then
|
|
||||||
line[#line+1] = string_format("%d:", info.currentline)
|
|
||||||
end
|
|
||||||
if info.namewhat ~= "" then
|
|
||||||
line[#line+1] = string_format(" in function '%s'", info.name)
|
|
||||||
else
|
|
||||||
if info.what == "main" then
|
|
||||||
line[#line+1] = " in main chunk"
|
|
||||||
elseif info.what == "C" or info.what == "tail" then
|
|
||||||
line[#line+1] = " ?"
|
|
||||||
else
|
|
||||||
line[#line+1] = string_format(" in function <%s:%d>", info.short_src, info.linedefined)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
errobj.tb[#errobj.tb+1] = table.concat(line)
|
|
||||||
end
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return errobj
|
|
||||||
end
|
|
||||||
|
|
||||||
function mypcall(func)
|
|
||||||
orig_assert( is_function(func) )
|
|
||||||
local ok, errobj = xpcall(func, my_traceback)
|
|
||||||
if not ok then
|
|
||||||
return errobj
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide(mypcall)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Type check functions
|
|
||||||
|
|
||||||
for _, typename in ipairs(typenames) do
|
|
||||||
lunit["is_"..typename] = function(x)
|
|
||||||
return type(x) == typename
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local is_nil = is_nil
|
|
||||||
local is_boolean = is_boolean
|
|
||||||
local is_number = is_number
|
|
||||||
local is_string = is_string
|
|
||||||
local is_table = is_table
|
|
||||||
local is_function = is_function
|
|
||||||
local is_thread = is_thread
|
|
||||||
local is_userdata = is_userdata
|
|
||||||
|
|
||||||
|
|
||||||
local function failure(name, usermsg, defaultmsg, ...)
|
|
||||||
local errobj = {
|
|
||||||
type = __failure__,
|
|
||||||
name = name,
|
|
||||||
msg = string_format(defaultmsg,...),
|
|
||||||
usermsg = usermsg
|
|
||||||
}
|
|
||||||
error(errobj, 0)
|
|
||||||
end
|
|
||||||
traceback_hide( failure )
|
|
||||||
|
|
||||||
|
|
||||||
local function format_arg(arg)
|
|
||||||
local argtype = type(arg)
|
|
||||||
if argtype == "string" then
|
|
||||||
return "'"..arg.."'"
|
|
||||||
elseif argtype == "number" or argtype == "boolean" or argtype == "nil" then
|
|
||||||
return tostring(arg)
|
|
||||||
else
|
|
||||||
return "["..tostring(arg).."]"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function fail(msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
failure( "fail", msg, "failure" )
|
|
||||||
end
|
|
||||||
traceback_hide( fail )
|
|
||||||
|
|
||||||
|
|
||||||
function assert(assertion, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if not assertion then
|
|
||||||
failure( "assert", msg, "assertion failed" )
|
|
||||||
end
|
|
||||||
return assertion
|
|
||||||
end
|
|
||||||
traceback_hide( assert )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_true(actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
local actualtype = type(actual)
|
|
||||||
if actualtype ~= "boolean" then
|
|
||||||
failure( "assert_true", msg, "true expected but was a "..actualtype )
|
|
||||||
end
|
|
||||||
if actual ~= true then
|
|
||||||
failure( "assert_true", msg, "true expected but was false" )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_true )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_false(actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
local actualtype = type(actual)
|
|
||||||
if actualtype ~= "boolean" then
|
|
||||||
failure( "assert_false", msg, "false expected but was a "..actualtype )
|
|
||||||
end
|
|
||||||
if actual ~= false then
|
|
||||||
failure( "assert_false", msg, "false expected but was true" )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_false )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_equal(expected, actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if expected ~= actual then
|
|
||||||
failure( "assert_equal", msg, "expected %s but was %s", format_arg(expected), format_arg(actual) )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_equal )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_not_equal(unexpected, actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if unexpected == actual then
|
|
||||||
failure( "assert_not_equal", msg, "%s not expected but was one", format_arg(unexpected) )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_not_equal )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_match(pattern, actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
local patterntype = type(pattern)
|
|
||||||
if patterntype ~= "string" then
|
|
||||||
failure( "assert_match", msg, "expected the pattern as a string but was a "..patterntype )
|
|
||||||
end
|
|
||||||
local actualtype = type(actual)
|
|
||||||
if actualtype ~= "string" then
|
|
||||||
failure( "assert_match", msg, "expected a string to match pattern '%s' but was a %s", pattern, actualtype )
|
|
||||||
end
|
|
||||||
if not string.find(actual, pattern) then
|
|
||||||
failure( "assert_match", msg, "expected '%s' to match pattern '%s' but doesn't", actual, pattern )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_match )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_not_match(pattern, actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
local patterntype = type(pattern)
|
|
||||||
if patterntype ~= "string" then
|
|
||||||
failure( "assert_not_match", msg, "expected the pattern as a string but was a "..patterntype )
|
|
||||||
end
|
|
||||||
local actualtype = type(actual)
|
|
||||||
if actualtype ~= "string" then
|
|
||||||
failure( "assert_not_match", msg, "expected a string to not match pattern '%s' but was a %s", pattern, actualtype )
|
|
||||||
end
|
|
||||||
if string.find(actual, pattern) then
|
|
||||||
failure( "assert_not_match", msg, "expected '%s' to not match pattern '%s' but it does", actual, pattern )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( assert_not_match )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_error(msg, func)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if func == nil then
|
|
||||||
func, msg = msg, nil
|
|
||||||
end
|
|
||||||
local functype = type(func)
|
|
||||||
if functype ~= "function" then
|
|
||||||
failure( "assert_error", msg, "expected a function as last argument but was a "..functype )
|
|
||||||
end
|
|
||||||
local ok, errmsg = pcall(func)
|
|
||||||
if ok then
|
|
||||||
failure( "assert_error", msg, "error expected but no error occurred" )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide( assert_error )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_error_match(msg, pattern, func)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if func == nil then
|
|
||||||
msg, pattern, func = nil, msg, pattern
|
|
||||||
end
|
|
||||||
local patterntype = type(pattern)
|
|
||||||
if patterntype ~= "string" then
|
|
||||||
failure( "assert_error_match", msg, "expected the pattern as a string but was a "..patterntype )
|
|
||||||
end
|
|
||||||
local functype = type(func)
|
|
||||||
if functype ~= "function" then
|
|
||||||
failure( "assert_error_match", msg, "expected a function as last argument but was a "..functype )
|
|
||||||
end
|
|
||||||
local ok, errmsg = pcall(func)
|
|
||||||
if ok then
|
|
||||||
failure( "assert_error_match", msg, "error expected but no error occurred" )
|
|
||||||
end
|
|
||||||
local errmsgtype = type(errmsg)
|
|
||||||
if errmsgtype ~= "string" then
|
|
||||||
failure( "assert_error_match", msg, "error as string expected but was a "..errmsgtype )
|
|
||||||
end
|
|
||||||
if not string.find(errmsg, pattern) then
|
|
||||||
failure( "assert_error_match", msg, "expected error '%s' to match pattern '%s' but doesn't", errmsg, pattern )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide( assert_error_match )
|
|
||||||
|
|
||||||
|
|
||||||
function assert_pass(msg, func)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if func == nil then
|
|
||||||
func, msg = msg, nil
|
|
||||||
end
|
|
||||||
local functype = type(func)
|
|
||||||
if functype ~= "function" then
|
|
||||||
failure( "assert_pass", msg, "expected a function as last argument but was a %s", functype )
|
|
||||||
end
|
|
||||||
local ok, errmsg = pcall(func)
|
|
||||||
if not ok then
|
|
||||||
failure( "assert_pass", msg, "no error expected but error was: '%s'", errmsg )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide( assert_pass )
|
|
||||||
|
|
||||||
|
|
||||||
-- lunit.assert_typename functions
|
|
||||||
|
|
||||||
for _, typename in ipairs(typenames) do
|
|
||||||
local assert_typename = "assert_"..typename
|
|
||||||
lunit[assert_typename] = function(actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
local actualtype = type(actual)
|
|
||||||
if actualtype ~= typename then
|
|
||||||
failure( assert_typename, msg, typename.." expected but was a "..actualtype )
|
|
||||||
end
|
|
||||||
return actual
|
|
||||||
end
|
|
||||||
traceback_hide( lunit[assert_typename] )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- lunit.assert_not_typename functions
|
|
||||||
|
|
||||||
for _, typename in ipairs(typenames) do
|
|
||||||
local assert_not_typename = "assert_not_"..typename
|
|
||||||
lunit[assert_not_typename] = function(actual, msg)
|
|
||||||
stats.assertions = stats.assertions + 1
|
|
||||||
if type(actual) == typename then
|
|
||||||
failure( assert_not_typename, msg, typename.." not expected but was one" )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide( lunit[assert_not_typename] )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function lunit.clearstats()
|
|
||||||
stats = {
|
|
||||||
assertions = 0;
|
|
||||||
passed = 0;
|
|
||||||
failed = 0;
|
|
||||||
errors = 0;
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local report, reporterrobj
|
|
||||||
do
|
|
||||||
local testrunner
|
|
||||||
|
|
||||||
function lunit.setrunner(newrunner)
|
|
||||||
if not ( is_table(newrunner) or is_nil(newrunner) ) then
|
|
||||||
return error("lunit.setrunner: Invalid argument", 0)
|
|
||||||
end
|
|
||||||
local oldrunner = testrunner
|
|
||||||
testrunner = newrunner
|
|
||||||
return oldrunner
|
|
||||||
end
|
|
||||||
|
|
||||||
function lunit.loadrunner(name)
|
|
||||||
if not is_string(name) then
|
|
||||||
return error("lunit.loadrunner: Invalid argument", 0)
|
|
||||||
end
|
|
||||||
local ok, runner = pcall( require, name )
|
|
||||||
if not ok then
|
|
||||||
return error("lunit.loadrunner: Can't load test runner: "..runner, 0)
|
|
||||||
end
|
|
||||||
return setrunner(runner)
|
|
||||||
end
|
|
||||||
|
|
||||||
function report(event, ...)
|
|
||||||
local f = testrunner and testrunner[event]
|
|
||||||
if is_function(f) then
|
|
||||||
pcall(f, ...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function reporterrobj(context, tcname, testname, errobj)
|
|
||||||
local fullname = tcname .. "." .. testname
|
|
||||||
if context == "setup" then
|
|
||||||
fullname = fullname .. ":" .. setupname(tcname, testname)
|
|
||||||
elseif context == "teardown" then
|
|
||||||
fullname = fullname .. ":" .. teardownname(tcname, testname)
|
|
||||||
end
|
|
||||||
if errobj.type == __failure__ then
|
|
||||||
stats.failed = stats.failed + 1
|
|
||||||
report("fail", fullname, errobj.where, errobj.msg, errobj.usermsg)
|
|
||||||
else
|
|
||||||
stats.errors = stats.errors + 1
|
|
||||||
report("err", fullname, errobj.msg, errobj.tb)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function key_iter(t, k)
|
|
||||||
return (next(t,k))
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local testcase
|
|
||||||
do
|
|
||||||
-- Array with all registered testcases
|
|
||||||
local _testcases = {}
|
|
||||||
|
|
||||||
-- Marks a module as a testcase.
|
|
||||||
-- Applied over a module from module("xyz", lunit.testcase).
|
|
||||||
function lunit.testcase(m)
|
|
||||||
orig_assert( is_table(m) )
|
|
||||||
--orig_assert( m._M == m )
|
|
||||||
orig_assert( is_string(m._NAME) )
|
|
||||||
--orig_assert( is_string(m._PACKAGE) )
|
|
||||||
|
|
||||||
-- Register the module as a testcase
|
|
||||||
_testcases[m._NAME] = m
|
|
||||||
|
|
||||||
-- Import lunit, fail, assert* and is_* function to the module/testcase
|
|
||||||
m.lunit = lunit
|
|
||||||
m.fail = lunit.fail
|
|
||||||
for funcname, func in pairs(lunit) do
|
|
||||||
if "assert" == string_sub(funcname, 1, 6) or "is_" == string_sub(funcname, 1, 3) then
|
|
||||||
m[funcname] = func
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Iterator (testcasename) over all Testcases
|
|
||||||
function lunit.testcases()
|
|
||||||
-- Make a copy of testcases to prevent confusing the iterator when
|
|
||||||
-- new testcase are defined
|
|
||||||
local _testcases2 = {}
|
|
||||||
for k,v in pairs(_testcases) do
|
|
||||||
_testcases2[k] = true
|
|
||||||
end
|
|
||||||
return key_iter, _testcases2, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function testcase(tcname)
|
|
||||||
return _testcases[tcname]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
do
|
|
||||||
-- Finds a function in a testcase case insensitive
|
|
||||||
local function findfuncname(tcname, name)
|
|
||||||
for key, value in pairs(testcase(tcname)) do
|
|
||||||
if is_string(key) and is_function(value) and string.lower(key) == name then
|
|
||||||
return key
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function lunit.setupname(tcname)
|
|
||||||
return findfuncname(tcname, "setup")
|
|
||||||
end
|
|
||||||
|
|
||||||
function lunit.teardownname(tcname)
|
|
||||||
return findfuncname(tcname, "teardown")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Iterator over all test names in a testcase.
|
|
||||||
-- Have to collect the names first in case one of the test
|
|
||||||
-- functions creates a new global and throws off the iteration.
|
|
||||||
function lunit.tests(tcname)
|
|
||||||
local testnames = {}
|
|
||||||
for key, value in pairs(testcase(tcname)) do
|
|
||||||
if is_string(key) and is_function(value) then
|
|
||||||
local lfn = string.lower(key)
|
|
||||||
if string.sub(lfn, 1, 4) == "test" or string.sub(lfn, -4) == "test" then
|
|
||||||
testnames[key] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return key_iter, testnames, nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function lunit.runtest(tcname, testname)
|
|
||||||
orig_assert( is_string(tcname) )
|
|
||||||
orig_assert( is_string(testname) )
|
|
||||||
|
|
||||||
local function callit(context, func)
|
|
||||||
if func then
|
|
||||||
local err = mypcall(func)
|
|
||||||
if err then
|
|
||||||
reporterrobj(context, tcname, testname, err)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
traceback_hide(callit)
|
|
||||||
|
|
||||||
report("run", tcname, testname)
|
|
||||||
|
|
||||||
local tc = testcase(tcname)
|
|
||||||
local setup = tc[setupname(tcname)]
|
|
||||||
local test = tc[testname]
|
|
||||||
local teardown = tc[teardownname(tcname)]
|
|
||||||
|
|
||||||
local setup_ok = callit( "setup", setup )
|
|
||||||
local test_ok = setup_ok and callit( "test", test )
|
|
||||||
local teardown_ok = setup_ok and callit( "teardown", teardown )
|
|
||||||
|
|
||||||
if setup_ok and test_ok and teardown_ok then
|
|
||||||
stats.passed = stats.passed + 1
|
|
||||||
report("pass", tcname, testname)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
traceback_hide(runtest)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function lunit.run(patterns)
|
|
||||||
clearstats()
|
|
||||||
report("begin")
|
|
||||||
for testcasename in lunit.testcases() do
|
|
||||||
-- Run tests in the testcases
|
|
||||||
for testname in lunit.tests(testcasename) do
|
|
||||||
local run = true
|
|
||||||
if patterns ~= nil then
|
|
||||||
run = false
|
|
||||||
for _, pat in ipairs(patterns) do
|
|
||||||
if string.match(testname, pat) ~= nil then
|
|
||||||
run = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if run then
|
|
||||||
runtest(testcasename, testname)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
report("done")
|
|
||||||
return stats
|
|
||||||
end
|
|
||||||
traceback_hide(run)
|
|
||||||
|
|
||||||
|
|
||||||
function lunit.loadonly()
|
|
||||||
clearstats()
|
|
||||||
report("begin")
|
|
||||||
report("done")
|
|
||||||
return stats
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local lunitpat2luapat
|
|
||||||
do
|
|
||||||
local conv = {
|
|
||||||
["^"] = "%^",
|
|
||||||
["$"] = "%$",
|
|
||||||
["("] = "%(",
|
|
||||||
[")"] = "%)",
|
|
||||||
["%"] = "%%",
|
|
||||||
["."] = "%.",
|
|
||||||
["["] = "%[",
|
|
||||||
["]"] = "%]",
|
|
||||||
["+"] = "%+",
|
|
||||||
["-"] = "%-",
|
|
||||||
["?"] = ".",
|
|
||||||
["*"] = ".*"
|
|
||||||
}
|
|
||||||
function lunitpat2luapat(str)
|
|
||||||
return "^" .. string.gsub(str, "%W", conv) .. "$"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function in_patternmap(map, name)
|
|
||||||
if map[name] == true then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
for _, pat in ipairs(map) do
|
|
||||||
if string.find(name, pat) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Called from 'lunit' shell script.
|
|
||||||
|
|
||||||
function main(argv)
|
|
||||||
argv = argv or {}
|
|
||||||
|
|
||||||
-- FIXME: Error handling and error messages aren't nice.
|
|
||||||
|
|
||||||
local function checkarg(optname, arg)
|
|
||||||
if not is_string(arg) then
|
|
||||||
return error("lunit.main: option "..optname..": argument missing.", 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function loadtestcase(filename)
|
|
||||||
if not is_string(filename) then
|
|
||||||
return error("lunit.main: invalid argument")
|
|
||||||
end
|
|
||||||
local chunk, err = loadfile(filename)
|
|
||||||
if err then
|
|
||||||
return error(err)
|
|
||||||
else
|
|
||||||
chunk()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local testpatterns = nil
|
|
||||||
local doloadonly = false
|
|
||||||
local runner = nil
|
|
||||||
|
|
||||||
local i = 0
|
|
||||||
while i < #argv do
|
|
||||||
i = i + 1
|
|
||||||
local arg = argv[i]
|
|
||||||
if arg == "--loadonly" then
|
|
||||||
doloadonly = true
|
|
||||||
elseif arg == "--runner" or arg == "-r" then
|
|
||||||
local optname = arg; i = i + 1; arg = argv[i]
|
|
||||||
checkarg(optname, arg)
|
|
||||||
runner = arg
|
|
||||||
elseif arg == "--test" or arg == "-t" then
|
|
||||||
local optname = arg; i = i + 1; arg = argv[i]
|
|
||||||
checkarg(optname, arg)
|
|
||||||
testpatterns = testpatterns or {}
|
|
||||||
testpatterns[#testpatterns+1] = lunitpat2luapat(arg)
|
|
||||||
elseif arg == "--" then
|
|
||||||
while i < #argv do
|
|
||||||
i = i + 1; arg = argv[i]
|
|
||||||
loadtestcase(arg)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
loadtestcase(arg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
loadrunner(runner or "lunit-console")
|
|
||||||
|
|
||||||
if doloadonly then
|
|
||||||
return loadonly()
|
|
||||||
else
|
|
||||||
return run(testpatterns)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
clearstats()
|
|
||||||
@ -1,188 +0,0 @@
|
|||||||
require("lunit")
|
|
||||||
|
|
||||||
local serialization = require("serialization")
|
|
||||||
local BaseControl = require("bc")
|
|
||||||
|
|
||||||
module("local", package.seeall, lunit.testcase)
|
|
||||||
|
|
||||||
function test_construct()
|
|
||||||
local function is_a_bc(bc)
|
|
||||||
assert_true(bc.local_nouns ~= nil)
|
|
||||||
assert_true(bc.local_verbs ~= nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Short init
|
|
||||||
is_a_bc(BaseControl())
|
|
||||||
is_a_bc(BaseControl:new())
|
|
||||||
is_a_bc(BaseControl:finalize())
|
|
||||||
is_a_bc(BaseControl:finalize({}, 10))
|
|
||||||
is_a_bc(BaseControl:finalize({}))
|
|
||||||
|
|
||||||
-- Long init
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:finalize()
|
|
||||||
is_a_bc(bc)
|
|
||||||
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:finalize({}, 10)
|
|
||||||
is_a_bc(bc)
|
|
||||||
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:finalize({})
|
|
||||||
is_a_bc(bc)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_register()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register("register1", 1234)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
-- Register after finalizing
|
|
||||||
local bc = BaseControl:finalize()
|
|
||||||
assert_error_match("after finalizing", function()
|
|
||||||
bc:register("register2", 4321)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Register exisiting
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register("register3", 123)
|
|
||||||
assert_error_match("already registered", function()
|
|
||||||
bc:register("register3", 12)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_register_batch()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register{
|
|
||||||
rb1=1234,
|
|
||||||
rb2=4321,
|
|
||||||
rb3v=function() end,
|
|
||||||
}
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_true(bc:has_noun("rb1"))
|
|
||||||
assert_true(bc:has_noun("rb2"))
|
|
||||||
assert_true(bc:has_verb("rb3v"))
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_available()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register("available1", 1234)
|
|
||||||
bc:register("available2v", function() end)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_equal(1234, bc.local_nouns["available1"])
|
|
||||||
assert_true(bc.local_verbs["available2v"] ~= nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_get()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register("get1", 1234)
|
|
||||||
bc:register("get2v", function() end)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_equal(1234, bc:get("get1"), "wrong value for noun")
|
|
||||||
assert_error_match("unknown", function()
|
|
||||||
bc:get("get2")
|
|
||||||
end)
|
|
||||||
assert_error_match("not a noun", function()
|
|
||||||
bc:get("get2v")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_set()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
bc:register("set1", 31415)
|
|
||||||
bc:register("set2v", function() end)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_equal(31415, bc:get("set1"), "wrong value for noun")
|
|
||||||
bc:set("set1", 14142)
|
|
||||||
assert_equal(14142, bc:get("set1"), "wrong value for noun")
|
|
||||||
|
|
||||||
assert_error_match("not a local", function()
|
|
||||||
bc:set("set2", 12345)
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert_error_match("can't be cast into a noun", function()
|
|
||||||
bc:set("set2v", 12345)
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert_pass(function()
|
|
||||||
bc:set("set2v", function() end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
assert_error_match("can't be cast into a verb", function()
|
|
||||||
bc:set("set1", function() end)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_has_iter_nouns()
|
|
||||||
local bc = BaseControl:new(
|
|
||||||
BaseControl.Network(31213) -- Network isolation
|
|
||||||
)
|
|
||||||
bc:register("hin1", 123)
|
|
||||||
bc:register("hin2v", function() end)
|
|
||||||
bc:register("hin3", 321)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_true(bc:has_noun("hin1"), "exisiting noun not found")
|
|
||||||
assert_false(bc:has_noun("hin2"), "non-existing noun found")
|
|
||||||
assert_false(bc:has_noun("hin2v"), "verb found as noun")
|
|
||||||
assert_true(bc:has_noun("hin3"), "exisiting noun not found")
|
|
||||||
|
|
||||||
local nouns = bc:nouns()
|
|
||||||
table.sort(nouns)
|
|
||||||
assert_equal(2, #nouns, "noun-list incorrect")
|
|
||||||
assert_equal("hin1", nouns[1], "noun-list incorrect")
|
|
||||||
assert_equal("hin3", nouns[2], "noun-list incorrect")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_call_verb()
|
|
||||||
local bc = BaseControl:new()
|
|
||||||
local flag1, flag2 = 0, 0
|
|
||||||
bc:register("call1", function(a, b)
|
|
||||||
flag1 = a + b
|
|
||||||
flag2 = flag2 + 1
|
|
||||||
end)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
bc:call("call1", 1, 2)
|
|
||||||
assert_equal(3, flag1, "call failed")
|
|
||||||
assert_equal(1, flag2, "call failed")
|
|
||||||
|
|
||||||
bc:call("call1", 10, 10)
|
|
||||||
assert_equal(20, flag1, "call failed")
|
|
||||||
assert_equal(2, flag2, "call failed")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_has_iter_verbs()
|
|
||||||
local bc = BaseControl:new(
|
|
||||||
BaseControl.Network(31214) -- Network isolation
|
|
||||||
)
|
|
||||||
bc:register("hiv1v", function() end)
|
|
||||||
bc:register("hiv2", 123)
|
|
||||||
bc:register("hiv3v", function() end)
|
|
||||||
bc:finalize()
|
|
||||||
|
|
||||||
assert_true(bc:has_verb("hiv1v"), "exisiting verb not found")
|
|
||||||
assert_false(bc:has_verb("hiv2v"), "non-existing verb found")
|
|
||||||
assert_false(bc:has_verb("hiv2"), "noun found as verb")
|
|
||||||
assert_true(bc:has_verb("hiv3v"), "exisiting verb not found")
|
|
||||||
|
|
||||||
local verbs = bc:verbs()
|
|
||||||
table.sort(verbs)
|
|
||||||
assert_equal(2, #verbs, "verb-list incorrect")
|
|
||||||
assert_equal("hiv1v", verbs[1], "verb-list incorrect")
|
|
||||||
assert_equal("hiv3v", verbs[2], "verb-list incorrect")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_iter_empty()
|
|
||||||
local bc = BaseControl:new(
|
|
||||||
BaseControl.Network(31211) -- Network isolation
|
|
||||||
):finalize()
|
|
||||||
|
|
||||||
assert_equal(31211, bc.network.port, "wrong port")
|
|
||||||
assert_equal(0, #bc:nouns(), "nouns found in empty network")
|
|
||||||
assert_equal(0, #bc:verbs(), "verbs found in empty network")
|
|
||||||
end
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
require("lunit")
|
|
||||||
|
|
||||||
local network = require("network")
|
|
||||||
local serialization = require("serialization")
|
|
||||||
local BaseControl = require("bc")
|
|
||||||
|
|
||||||
module("network", package.seeall, lunit.testcase)
|
|
||||||
|
|
||||||
function test_multinode()
|
|
||||||
local bc1 = BaseControl:finalize()
|
|
||||||
local bc2 = BaseControl:new()
|
|
||||||
bc2:register("multinode1", 123)
|
|
||||||
bc2:register("multinode2v", function() end)
|
|
||||||
bc2:finalize()
|
|
||||||
local bc3 = BaseControl:finalize()
|
|
||||||
|
|
||||||
assert_true(bc1:has_noun("multinode1"), "d1: remote noun missing")
|
|
||||||
assert_true(bc1:has_verb("multinode2v"), "d1: remote verb missing")
|
|
||||||
assert_true(bc3:has_noun("multinode1"), "d2: remote noun missing")
|
|
||||||
assert_true(bc3:has_verb("multinode2v"), "d2: remote verb missing")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_get_network()
|
|
||||||
local bc1 = BaseControl:new()
|
|
||||||
bc1:register("getnw1", 123)
|
|
||||||
bc1:finalize()
|
|
||||||
|
|
||||||
local bc2 = BaseControl:new()
|
|
||||||
|
|
||||||
assert_equal(123, bc2:get("getnw1"), "wrong value")
|
|
||||||
assert_error_match("unknown", function()
|
|
||||||
bc2:unknown("getnw2")
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_call_network()
|
|
||||||
local bc1 = BaseControl:new()
|
|
||||||
local tmp, n = 0, 0
|
|
||||||
bc1:register("callnw1", function(param, p2)
|
|
||||||
assert_equal(p2, 1234)
|
|
||||||
tmp = param
|
|
||||||
n = n + 1
|
|
||||||
end)
|
|
||||||
bc1:finalize()
|
|
||||||
|
|
||||||
local bc2 = BaseControl:new()
|
|
||||||
|
|
||||||
bc2:call("callnw1", 4321, 1234)
|
|
||||||
assert_equal(4321, tmp, "call incomplete")
|
|
||||||
assert_equal(1, n, "call not correct")
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_call_sync()
|
|
||||||
local bc1 = BaseControl:new()
|
|
||||||
local n = 0
|
|
||||||
bc1:register("sync1", function(p1, p2)
|
|
||||||
assert_equal(p2, 12)
|
|
||||||
n = n + 1
|
|
||||||
return p1 + 10, "hello"
|
|
||||||
end)
|
|
||||||
bc1:finalize()
|
|
||||||
|
|
||||||
-- Test locally
|
|
||||||
assert_true(bc1:call("sync1", 20, 12), "call not true")
|
|
||||||
local ret, val = bc1:call_sync("sync1", 30, 12)
|
|
||||||
assert_equal(40, ret, "local sync not correct")
|
|
||||||
assert_equal("hello", val, "local sync not multiple")
|
|
||||||
assert_equal(2, n, "wrong invokation number")
|
|
||||||
|
|
||||||
-- Test remote
|
|
||||||
local bc2 = BaseControl:new()
|
|
||||||
assert_true(bc2:call("sync1", 20, 12), "call not true")
|
|
||||||
local ret, val = bc2:call_sync("sync1", 30, 12)
|
|
||||||
assert_equal(40, ret, "local sync not correct")
|
|
||||||
assert_equal("hello", val, "local sync not multiple")
|
|
||||||
assert_equal(4, n, "wrong invokation number")
|
|
||||||
end
|
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env lua5.2
|
||||||
|
|
||||||
|
-- Insert necessary directories into lua search path
|
||||||
|
package.path = "./?.lua;./tests/?.lua;./tests/support/?.lua;"..package.path
|
||||||
|
|
||||||
|
local test = require("u-test")
|
||||||
|
|
||||||
|
test_sources = {
|
||||||
|
"tests/cleanup.lua",
|
||||||
|
"tests/dirty.lua",
|
||||||
|
"tests/iters.lua",
|
||||||
|
"tests/listening.lua",
|
||||||
|
"tests/local.lua",
|
||||||
|
"tests/network.lua",
|
||||||
|
"tests/timeout.lua",
|
||||||
|
}
|
||||||
|
for _, source in ipairs(test_sources) do
|
||||||
|
loadfile("./tests/"..source)()
|
||||||
|
end
|
||||||
|
|
||||||
|
test.result()
|
||||||
|
test.summary()
|
||||||
@ -0,0 +1,184 @@
|
|||||||
|
local test = require("u-test")
|
||||||
|
|
||||||
|
local serialization = require("serialization")
|
||||||
|
local BaseControl = require("bc")
|
||||||
|
|
||||||
|
function test.construct()
|
||||||
|
local function is_a_bc(bc)
|
||||||
|
test.is_true(bc.local_nouns ~= nil)
|
||||||
|
test.is_true(bc.local_verbs ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Short init
|
||||||
|
is_a_bc(BaseControl())
|
||||||
|
is_a_bc(BaseControl:new())
|
||||||
|
is_a_bc(BaseControl:finalize())
|
||||||
|
is_a_bc(BaseControl:finalize({}, 10))
|
||||||
|
is_a_bc(BaseControl:finalize({}))
|
||||||
|
|
||||||
|
-- Long init
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:finalize()
|
||||||
|
is_a_bc(bc)
|
||||||
|
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:finalize({}, 10)
|
||||||
|
is_a_bc(bc)
|
||||||
|
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:finalize({})
|
||||||
|
is_a_bc(bc)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.register()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register("register1", 1234)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
-- Register after finalizing
|
||||||
|
local bc = BaseControl:finalize()
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:register("register2", 4321)
|
||||||
|
end, "after finalizing")
|
||||||
|
|
||||||
|
-- Register exisiting
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register("register3", 123)
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:register("register3", 12)
|
||||||
|
end, "already registered")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.register_batch()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register{
|
||||||
|
rb1=1234,
|
||||||
|
rb2=4321,
|
||||||
|
rb3v=function() end,
|
||||||
|
}
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.is_true(bc:has_noun("rb1"))
|
||||||
|
test.is_true(bc:has_noun("rb2"))
|
||||||
|
test.is_true(bc:has_verb("rb3v"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.available()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register("available1", 1234)
|
||||||
|
bc:register("available2v", function() end)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.equal(1234, bc.local_nouns["available1"])
|
||||||
|
test.is_true(bc.local_verbs["available2v"] ~= nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.get()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register("get1", 1234)
|
||||||
|
bc:register("get2v", function() end)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.equal(1234, bc:get("get1"), "wrong value for noun")
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:get("get2")
|
||||||
|
end, "unknown")
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:get("get2v")
|
||||||
|
end, "not a noun")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.set()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
bc:register("set1", 31415)
|
||||||
|
bc:register("set2v", function() end)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.equal(31415, bc:get("set1"), "wrong value for noun")
|
||||||
|
bc:set("set1", 14142)
|
||||||
|
test.equal(14142, bc:get("set1"), "wrong value for noun")
|
||||||
|
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:set("set2", 12345)
|
||||||
|
end, "not a local")
|
||||||
|
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:set("set2v", 12345)
|
||||||
|
end, "can't be cast into a noun")
|
||||||
|
|
||||||
|
bc:set("set2v", function() end)
|
||||||
|
|
||||||
|
test.error_raised(function()
|
||||||
|
bc:set("set1", function() end)
|
||||||
|
end, "can't be cast into a verb")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.has_iter_nouns()
|
||||||
|
local bc = BaseControl:new(
|
||||||
|
BaseControl.Network(31213) -- Network isolation
|
||||||
|
)
|
||||||
|
bc:register("hin1", 123)
|
||||||
|
bc:register("hin2v", function() end)
|
||||||
|
bc:register("hin3", 321)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.is_true(bc:has_noun("hin1"), "exisiting noun not found")
|
||||||
|
test.is_false(bc:has_noun("hin2"), "non-existing noun found")
|
||||||
|
test.is_false(bc:has_noun("hin2v"), "verb found as noun")
|
||||||
|
test.is_true(bc:has_noun("hin3"), "exisiting noun not found")
|
||||||
|
|
||||||
|
local nouns = bc:nouns()
|
||||||
|
table.sort(nouns)
|
||||||
|
test.equal(2, #nouns, "noun-list incorrect")
|
||||||
|
test.equal("hin1", nouns[1], "noun-list incorrect")
|
||||||
|
test.equal("hin3", nouns[2], "noun-list incorrect")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.call_verb()
|
||||||
|
local bc = BaseControl:new()
|
||||||
|
local flag1, flag2 = 0, 0
|
||||||
|
bc:register("call1", function(a, b)
|
||||||
|
flag1 = a + b
|
||||||
|
flag2 = flag2 + 1
|
||||||
|
end)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
bc:call("call1", 1, 2)
|
||||||
|
test.equal(3, flag1, "call failed")
|
||||||
|
test.equal(1, flag2, "call failed")
|
||||||
|
|
||||||
|
bc:call("call1", 10, 10)
|
||||||
|
test.equal(20, flag1, "call failed")
|
||||||
|
test.equal(2, flag2, "call failed")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.has_iter_verbs()
|
||||||
|
local bc = BaseControl:new(
|
||||||
|
BaseControl.Network(31214) -- Network isolation
|
||||||
|
)
|
||||||
|
bc:register("hiv1v", function() end)
|
||||||
|
bc:register("hiv2", 123)
|
||||||
|
bc:register("hiv3v", function() end)
|
||||||
|
bc:finalize()
|
||||||
|
|
||||||
|
test.is_true(bc:has_verb("hiv1v"), "exisiting verb not found")
|
||||||
|
test.is_false(bc:has_verb("hiv2v"), "non-existing verb found")
|
||||||
|
test.is_false(bc:has_verb("hiv2"), "noun found as verb")
|
||||||
|
test.is_true(bc:has_verb("hiv3v"), "exisiting verb not found")
|
||||||
|
|
||||||
|
local verbs = bc:verbs()
|
||||||
|
table.sort(verbs)
|
||||||
|
test.equal(2, #verbs, "verb-list incorrect")
|
||||||
|
test.equal("hiv1v", verbs[1], "verb-list incorrect")
|
||||||
|
test.equal("hiv3v", verbs[2], "verb-list incorrect")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.iter_empty()
|
||||||
|
local bc = BaseControl:new(
|
||||||
|
BaseControl.Network(31211) -- Network isolation
|
||||||
|
):finalize()
|
||||||
|
|
||||||
|
test.equal(31211, bc.network.port, "wrong port")
|
||||||
|
test.equal(0, #bc:nouns(), "nouns found in empty network")
|
||||||
|
test.equal(0, #bc:verbs(), "verbs found in empty network")
|
||||||
|
end
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
local test = require("u-test")
|
||||||
|
|
||||||
|
local network = require("network")
|
||||||
|
local serialization = require("serialization")
|
||||||
|
local BaseControl = require("bc")
|
||||||
|
|
||||||
|
function test.multinode()
|
||||||
|
local bc1 = BaseControl:finalize()
|
||||||
|
local bc2 = BaseControl:new()
|
||||||
|
bc2:register("multinode1", 123)
|
||||||
|
bc2:register("multinode2v", function() end)
|
||||||
|
bc2:finalize()
|
||||||
|
local bc3 = BaseControl:finalize()
|
||||||
|
|
||||||
|
test.is_true(bc1:has_noun("multinode1"), "d1: remote noun missing")
|
||||||
|
test.is_true(bc1:has_verb("multinode2v"), "d1: remote verb missing")
|
||||||
|
test.is_true(bc3:has_noun("multinode1"), "d2: remote noun missing")
|
||||||
|
test.is_true(bc3:has_verb("multinode2v"), "d2: remote verb missing")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.get_network()
|
||||||
|
local bc1 = BaseControl:new()
|
||||||
|
bc1:register("getnw1", 123)
|
||||||
|
bc1:finalize()
|
||||||
|
|
||||||
|
local bc2 = BaseControl:new()
|
||||||
|
|
||||||
|
test.equal(123, bc2:get("getnw1"), "wrong value")
|
||||||
|
test.error_raised(function()
|
||||||
|
bc2:unknown("getnw2")
|
||||||
|
end, "unknown")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.call_network()
|
||||||
|
local bc1 = BaseControl:new()
|
||||||
|
local tmp, n = 0, 0
|
||||||
|
bc1:register("callnw1", function(param, p2)
|
||||||
|
test.equal(p2, 1234)
|
||||||
|
tmp = param
|
||||||
|
n = n + 1
|
||||||
|
end)
|
||||||
|
bc1:finalize()
|
||||||
|
|
||||||
|
local bc2 = BaseControl:new()
|
||||||
|
|
||||||
|
bc2:call("callnw1", 4321, 1234)
|
||||||
|
test.equal(4321, tmp, "call incomplete")
|
||||||
|
test.equal(1, n, "call not correct")
|
||||||
|
end
|
||||||
|
|
||||||
|
function test.call_sync()
|
||||||
|
local bc1 = BaseControl:new()
|
||||||
|
local n = 0
|
||||||
|
bc1:register("sync1", function(p1, p2)
|
||||||
|
test.equal(p2, 12)
|
||||||
|
n = n + 1
|
||||||
|
return p1 + 10, "hello"
|
||||||
|
end)
|
||||||
|
bc1:finalize()
|
||||||
|
|
||||||
|
-- Test locally
|
||||||
|
test.is_true(bc1:call("sync1", 20, 12), "call not true")
|
||||||
|
local ret, val = bc1:call_sync("sync1", 30, 12)
|
||||||
|
test.equal(40, ret, "local sync not correct")
|
||||||
|
test.equal("hello", val, "local sync not multiple")
|
||||||
|
test.equal(2, n, "wrong invokation number")
|
||||||
|
|
||||||
|
-- Test remote
|
||||||
|
local bc2 = BaseControl:new()
|
||||||
|
test.is_true(bc2:call("sync1", 20, 12), "call not true")
|
||||||
|
local ret, val = bc2:call_sync("sync1", 30, 12)
|
||||||
|
test.equal(40, ret, "local sync not correct")
|
||||||
|
test.equal("hello", val, "local sync not multiple")
|
||||||
|
test.equal(4, n, "wrong invokation number")
|
||||||
|
end
|
||||||
@ -0,0 +1,311 @@
|
|||||||
|
-- COMMAND LINE ----------------------------------------------------------------
|
||||||
|
local function print_help()
|
||||||
|
print "Usage: target.lua [options] [regex]"
|
||||||
|
print "\t-h show this message"
|
||||||
|
print "\t-q quiet mode"
|
||||||
|
print "\t-s disable colours"
|
||||||
|
end
|
||||||
|
|
||||||
|
local quiet, grey, test_regex
|
||||||
|
if arg then
|
||||||
|
for i = 1, #arg do
|
||||||
|
if arg[i] == "-h" then
|
||||||
|
print_help()
|
||||||
|
os.exit(0)
|
||||||
|
elseif arg[i] == "-q" then
|
||||||
|
quiet = true
|
||||||
|
elseif arg[i] == "-s" then
|
||||||
|
grey = true
|
||||||
|
elseif not test_regex then
|
||||||
|
test_regex = arg[i]
|
||||||
|
else
|
||||||
|
print_help()
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- UTILS -----------------------------------------------------------------------
|
||||||
|
local function red(str) return grey and str or "\27[1;31m" .. str .. "\27[0m" end
|
||||||
|
local function blue(str) return grey and str or "\27[1;34m" .. str .. "\27[0m" end
|
||||||
|
local function green(str) return grey and str or "\27[1;32m" .. str .. "\27[0m" end
|
||||||
|
local function yellow(str) return grey and str or "\27[1;33m" .. str .. "\27[0m" end
|
||||||
|
|
||||||
|
local tab_tag = blue "[----------]"
|
||||||
|
local done_tag = blue "[==========]"
|
||||||
|
local run_tag = blue "[ RUN ]"
|
||||||
|
local ok_tag = green "[ OK ]"
|
||||||
|
local fail_tag = red "[ FAIL]"
|
||||||
|
local disabled_tag = yellow "[ DISABLED ]"
|
||||||
|
local passed_tag = green "[ PASSED ]"
|
||||||
|
local failed_tag = red "[ FAILED ]"
|
||||||
|
|
||||||
|
local ntests = 0
|
||||||
|
local failed = false
|
||||||
|
local failed_list = {}
|
||||||
|
|
||||||
|
local function trace(start_frame)
|
||||||
|
print "Trace:"
|
||||||
|
local frame = start_frame
|
||||||
|
while true do
|
||||||
|
local info = debug.getinfo(frame, "Sl")
|
||||||
|
if not info then break end
|
||||||
|
if info.what == "C" then
|
||||||
|
print(frame - start_frame, "??????")
|
||||||
|
else
|
||||||
|
print(frame - start_frame, info.short_src .. ":" .. info.currentline .. " ")
|
||||||
|
end
|
||||||
|
frame = frame + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function log(msg)
|
||||||
|
if not quiet then
|
||||||
|
print(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fail(msg, start_frame)
|
||||||
|
failed = true
|
||||||
|
print("Fail: " .. msg)
|
||||||
|
trace(start_frame or 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function stringize_var_arg(...)
|
||||||
|
local args = { n = select("#", ...), ... }
|
||||||
|
local result = {}
|
||||||
|
for i = 1, args.n do
|
||||||
|
if type(args[i]) == 'string' then
|
||||||
|
result[i] = '"' .. tostring(args[i]) .. '"'
|
||||||
|
else
|
||||||
|
result[i] = tostring(args[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(result, ", ")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function test_pretty_name(suite_name, test_name)
|
||||||
|
if suite_name == "__root" then
|
||||||
|
return test_name
|
||||||
|
else
|
||||||
|
return suite_name .. "." .. test_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- PUBLIC API -----------------------------------------------------------------
|
||||||
|
local api = { test_suite_name = "__root", skip = false }
|
||||||
|
|
||||||
|
api.assert = function (cond)
|
||||||
|
if not cond then
|
||||||
|
fail("assertion " .. tostring(cond) .. " failed")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.equal = function (l, r)
|
||||||
|
if l ~= r then
|
||||||
|
fail(tostring(l) .. " ~= " .. tostring(r))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.not_equal = function (l, r)
|
||||||
|
if l == r then
|
||||||
|
fail(tostring(l) .. " == " .. tostring(r))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.almost_equal = function (l, r, diff)
|
||||||
|
if require("math").abs(l - r) > diff then
|
||||||
|
fail("|" .. tostring(l) .. " - " .. tostring(r) .."| > " .. tostring(diff))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.is_false = function (maybe_false)
|
||||||
|
if maybe_false or type(maybe_false) ~= "boolean" then
|
||||||
|
fail("got " .. tostring(maybe_false) .. " instead of false")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.is_true = function (maybe_true)
|
||||||
|
if not maybe_true or type(maybe_true) ~= "boolean" then
|
||||||
|
fail("got " .. tostring(maybe_true) .. " instead of true")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.is_not_nil = function (maybe_not_nil)
|
||||||
|
if type(maybe_not_nil) == "nil" then
|
||||||
|
fail("got nil")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.error_raised = function (f, error_message, ...)
|
||||||
|
local status, err = pcall(f, ...)
|
||||||
|
if status == true then
|
||||||
|
fail("error not raised")
|
||||||
|
else
|
||||||
|
if error_message ~= nil then
|
||||||
|
-- we set "plain" to true to avoid pattern matching in string.find
|
||||||
|
if err:find(error_message, 1, true) == nil then
|
||||||
|
fail("'" .. error_message .. "' not found in error '" .. tostring(err) .. "'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.register_assert = function(assert_name, assert_func)
|
||||||
|
rawset(api, assert_name, function(...)
|
||||||
|
local result, msg = assert_func(...)
|
||||||
|
if not result then
|
||||||
|
msg = msg or "Assertion "..assert_name.." failed"
|
||||||
|
fail(msg)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function make_type_checker(typename)
|
||||||
|
api["is_" .. typename] = function (maybe_type)
|
||||||
|
if type(maybe_type) ~= typename then
|
||||||
|
fail("got " .. tostring(maybe_type) .. " instead of " .. typename, 4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local supported_types = {"nil", "boolean", "string", "number", "userdata", "table", "function", "thread"}
|
||||||
|
for i, supported_type in ipairs(supported_types) do
|
||||||
|
make_type_checker(supported_type)
|
||||||
|
end
|
||||||
|
|
||||||
|
local last_test_suite
|
||||||
|
local function run_test(test_suite, test_name, test_function, ...)
|
||||||
|
local suite_name = test_suite.test_suite_name
|
||||||
|
local full_test_name = test_pretty_name(suite_name, test_name)
|
||||||
|
|
||||||
|
if test_regex and not string.match(full_test_name, test_regex) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if test_suite.skip then
|
||||||
|
log(disabled_tag .. " " .. full_test_name)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if suite_name ~= last_test_suite then
|
||||||
|
log(tab_tag)
|
||||||
|
last_test_suite = suite_name
|
||||||
|
end
|
||||||
|
|
||||||
|
ntests = ntests + 1
|
||||||
|
failed = false
|
||||||
|
|
||||||
|
log(run_tag .. " " .. full_test_name)
|
||||||
|
|
||||||
|
local start = os.time()
|
||||||
|
|
||||||
|
local status, err
|
||||||
|
for _, f in ipairs({test_suite.start_up, test_function, test_suite.tear_down}) do
|
||||||
|
status, err = pcall(f, ...)
|
||||||
|
if not status then
|
||||||
|
failed = true
|
||||||
|
print(tostring(err))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local stop = os.time()
|
||||||
|
|
||||||
|
local is_test_failed = not status or failed
|
||||||
|
log(string.format("%s %s %d sec",
|
||||||
|
is_test_failed and fail_tag or ok_tag,
|
||||||
|
full_test_name,
|
||||||
|
os.difftime(stop, start)))
|
||||||
|
|
||||||
|
if is_test_failed then
|
||||||
|
table.insert(failed_list, full_test_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.summary = function ()
|
||||||
|
log(done_tag)
|
||||||
|
local nfailed = #failed_list
|
||||||
|
if nfailed == 0 then
|
||||||
|
log(passed_tag .. " " .. ntests .. " test(s)")
|
||||||
|
os.exit(0)
|
||||||
|
else
|
||||||
|
log(failed_tag .. " " .. nfailed .. " out of " .. ntests .. ":")
|
||||||
|
for _, test_name in ipairs(failed_list) do
|
||||||
|
log(failed_tag .. "\t" .. test_name)
|
||||||
|
end
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
api.result = function ( ... )
|
||||||
|
return ntests, #failed_list
|
||||||
|
end
|
||||||
|
|
||||||
|
local default_start_up = function () end
|
||||||
|
local default_tear_down = function () collectgarbage() end
|
||||||
|
|
||||||
|
api.start_up = default_start_up
|
||||||
|
api.tear_down = default_tear_down
|
||||||
|
|
||||||
|
local all_test_cases = { __root = {} }
|
||||||
|
local function handle_new_test(suite, test_name, test_function)
|
||||||
|
local suite_name = suite.test_suite_name
|
||||||
|
if not all_test_cases[suite_name] then
|
||||||
|
all_test_cases[suite_name] = {}
|
||||||
|
end
|
||||||
|
all_test_cases[suite_name][test_name] = test_function
|
||||||
|
|
||||||
|
local info = debug.getinfo(test_function)
|
||||||
|
if info.nparams == nil and
|
||||||
|
string.sub(test_name, #test_name - 1, #test_name) ~= "_p"
|
||||||
|
or info.nparams == 0 then
|
||||||
|
run_test(suite, test_name, test_function)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function lookup_test_with_params(suite, test_name)
|
||||||
|
local suite_name = suite.test_suite_name
|
||||||
|
|
||||||
|
if all_test_cases[suite_name] and all_test_cases[suite_name][test_name] then
|
||||||
|
return function (...)
|
||||||
|
run_test(suite
|
||||||
|
, test_name .. "(" .. stringize_var_arg(...) .. ")"
|
||||||
|
, all_test_cases[suite_name][test_name], ...)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local full_test_name = test_pretty_name(suite_name, test_name)
|
||||||
|
table.insert(failed_list, full_test_name)
|
||||||
|
ntests = ntests + 1
|
||||||
|
log(fail_tag .. " No " .. full_test_name .. " parametrized test case!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new_test_suite(_, name)
|
||||||
|
local test_suite = {
|
||||||
|
test_suite_name = name,
|
||||||
|
start_up = default_start_up,
|
||||||
|
tear_down = default_tear_down,
|
||||||
|
skip = false }
|
||||||
|
|
||||||
|
setmetatable(test_suite, {
|
||||||
|
__newindex = handle_new_test,
|
||||||
|
__index = lookup_test_with_params })
|
||||||
|
return test_suite
|
||||||
|
end
|
||||||
|
|
||||||
|
local test_suites = {}
|
||||||
|
setmetatable(api, {
|
||||||
|
__index = function (tbl, name)
|
||||||
|
if all_test_cases.__root[name] then
|
||||||
|
return lookup_test_with_params(tbl, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not test_suites[name] then
|
||||||
|
test_suites[name] = new_test_suite(tbl, name)
|
||||||
|
end
|
||||||
|
return test_suites[name]
|
||||||
|
end,
|
||||||
|
__newindex = handle_new_test
|
||||||
|
})
|
||||||
|
|
||||||
|
return api
|
||||||
Loading…
Reference in new issue