From adc698673376267e4a501b58d98e62abff38061f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 9 Nov 2009 07:41:59 +0000 Subject: [PATCH] preparing for unit tests (setting package.path) --- src/common/settings-eressea.h | 2 +- src/eressea/server.c | 21 +- src/external/lunit/ANNOUNCE | 15 + src/external/lunit/CHANGES | 30 + src/external/lunit/DOCUMENTATION | 245 +++++++ src/external/lunit/LICENSE | 32 + src/external/lunit/PATCHES | 12 + src/external/lunit/README | 12 + src/external/lunit/example.lua | 40 ++ src/external/lunit/lunit | 128 ++++ src/external/lunit/lunit-console.lua | 141 ++++ src/external/lunit/lunit-tests.lua | 991 +++++++++++++++++++++++++++ src/external/lunit/lunit.lua | 670 ++++++++++++++++++ 13 files changed, 2337 insertions(+), 2 deletions(-) create mode 100644 src/external/lunit/ANNOUNCE create mode 100644 src/external/lunit/CHANGES create mode 100644 src/external/lunit/DOCUMENTATION create mode 100644 src/external/lunit/LICENSE create mode 100644 src/external/lunit/PATCHES create mode 100644 src/external/lunit/README create mode 100644 src/external/lunit/example.lua create mode 100644 src/external/lunit/lunit create mode 100644 src/external/lunit/lunit-console.lua create mode 100644 src/external/lunit/lunit-tests.lua create mode 100644 src/external/lunit/lunit.lua diff --git a/src/common/settings-eressea.h b/src/common/settings-eressea.h index f7f9cf9a7..cbf907261 100644 --- a/src/common/settings-eressea.h +++ b/src/common/settings-eressea.h @@ -49,7 +49,7 @@ #define DUNGEON_MODULE 0 #define INFOCMD_MODULE 0 #define CHANGED_CROSSBOWS 0 /* use the WTF_ARMORPIERCING flag */ -#define GLOBAL_WARMING 200 /* number of turns before global warming sets in */ +#undef GLOBAL_WARMING /* number of turns before global warming sets in */ #define SIMPLE_COMBAT #define SIMPLE_ESCAPE diff --git a/src/eressea/server.c b/src/eressea/server.c index cfef725aa..5393851e5 100644 --- a/src/eressea/server.c +++ b/src/eressea/server.c @@ -171,6 +171,7 @@ static boolean g_writemap = false; static boolean g_ignore_errors = false; static const char * luafile = NULL; static const char * preload = NULL; +static const char * lua_path = NULL; static const char * script_path = "scripts"; static int memdebug = 0; static int g_console = 1; @@ -267,8 +268,8 @@ static const struct { {LUA_IOLIBNAME, luaopen_io}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, -/* {LUA_LOADLIBNAME, luaopen_package}, +/* {LUA_DBLIBNAME, luaopen_debug}, */ #if LUA_VERSION_NUM>=501 @@ -554,6 +555,22 @@ read_args(int argc, char **argv, lua_State * luaState) sprintf(str, "?;?.lua;%s/?.lua;%s/?", script_path, script_path); setLuaString(luaState, "LUA_PATH", str); } + if (lua_path) { + char buffer[512]; + const char * str; + int t; + lua_getglobal(luaState, "package"); + t = lua_type(luaState, -1); + lua_pushstring(luaState, "path"); + lua_gettable(luaState, -2); + t = lua_type(luaState, -1); + str = lua_tostring(luaState, -1); + lua_pop(luaState, 1); + sprintf(buffer, "%s;%s", str, lua_path); + lua_pushstring(luaState, "path"); + lua_pushstring(luaState, buffer); + lua_settable(luaState, -3); + } setLuaString(luaState, "datapath", datapath()); setLuaString(luaState, "scriptpath", script_path); setLuaString(luaState, "basepath", basepath()); @@ -589,6 +606,8 @@ load_inifile(const char * filename) lomem = iniparser_getint(d, "common:lomem", lomem)?1:0; memdebug = iniparser_getint(d, "common:memcheck", memdebug); + lua_path = iniparser_getstring(d, "common:luapath", lua_path); + str = iniparser_getstring(d, "common:encoding", NULL); if (str) enc_gamedata = xmlParseCharEncoding(str); diff --git a/src/external/lunit/ANNOUNCE b/src/external/lunit/ANNOUNCE new file mode 100644 index 000000000..c2e97fab5 --- /dev/null +++ b/src/external/lunit/ANNOUNCE @@ -0,0 +1,15 @@ + + Lunit Release 0.5 + =================== + +Lunit is a unit testing framework for lua, written in lua. + +Lunit provides 27 assert functions, and a few misc functions +for usage in an easy unit testing framework. + +Lunit comes with a test suite to test itself. The testsuite +consists of approximately 710 assertions. + +Lunit is licensed under the MIT license. + +Lunit can downloaded from http://www.mroth.net/lunit/ diff --git a/src/external/lunit/CHANGES b/src/external/lunit/CHANGES new file mode 100644 index 000000000..09927e537 --- /dev/null +++ b/src/external/lunit/CHANGES @@ -0,0 +1,30 @@ +Release 0.5: + + New test function assert_error_match(). + Lunit shell script returns an error code on failed tests. + Be more compatible with Darwin / Mac OS X. + Bug fixes. + +Release 0.4: + + Mostly complete rewrite. + Lua-5.1 only. + + +Release 0.3 (alpha): + + New function lunit.wrap() to wrap a single function in a + complete test case. + + Now a backtrace is printed, if an error or failure occurs + in a test case. + + +Release 0.2 (alpha): + + The test suite consists now of approximately 630 assertions. + + Fixed an ugly bug in lunit.assert()! Testcases for lunit.assert() + added. + + Now all assert functions return the actual value on success. diff --git a/src/external/lunit/DOCUMENTATION b/src/external/lunit/DOCUMENTATION new file mode 100644 index 000000000..bcf33762e --- /dev/null +++ b/src/external/lunit/DOCUMENTATION @@ -0,0 +1,245 @@ + +To use the lunit unit testing framework copy these files to your +lua search path or include it to your package: + + lunit + lunit.lua + lunit-console.lua + + +To write a testcase, open the framework using require. The "lunit" shell script +works hard to find the "lunit.lua" and "lunit-console.lua" in all cases. + + require "lunit" + + +Lunit uses the lua-5.1 module system. A testcase is a arbitrarily named module +marked with "lunit.testcase" as a testcase. An example: + + require "lunit" + + module( "my_testcase", lunit.testcase, package.seeall ) + + +The tests itself in a testcase are functions whose names must begin +or end with 'test'. The function names are case insensitive. Example: + + require "lunit" + + module( "my_testcase", lunit.testcase, package.seeall ) + + function FirstTest() + -- Test code goes here + end + + function test_something() + -- Test code goes here + end + + +Inside the test functions you use asserts to test your code or package. +Lunit defines 26 assert functions: + + fail( [msg] ) + + Always fails. + + assert( assertion, [msg] ) + + Fails, if 'assertion' is false or nil. + + assert_true( actual, [msg] ) + + Fails, if 'actual' isn't true. + + assert_false( actual, [msg] ) + + Fails, if 'actual' isn't false. (Even fails if 'actual' is + a nil value!) + + assert_equal( expected, actual, [msg] ) + + Fails, if 'actual' is different from 'expected'. Make sure + that you don't mix 'expected' and 'actual' because they are + used to build a nice error message. + + assert_not_equal( unexpected, actual, [msg] ) + + Fails, if 'actual' and 'unexpected' are equal. + + assert_match( pattern, actual, [msg] ) + + Fails, if the string 'actual' doesn't match 'pattern'. + + assert_not_match( pattern, actual, [msg] ) + + Fails, if the string 'actual' match 'pattern'. + + assert_nil( actual, [msg] ) + + Fails, if 'actual' isn't a nil value. + + assert_not_nil( actual, [msg] ) + + Fails, if 'actual' is a nil value. + + assert_boolean( actual, [msg] ) + + Fails, if 'actual' isn't true or false. + + assert_not_boolean( actual, [msg] ) + + Fails, if 'actual' is true or false. + + assert_number( actual, [msg] ) + + Fails, if 'actual' isn't a number. + + assert_not_number( actual, [msg] ) + + Fails, if 'actual' is a number. + + assert_string( actual, [msg] ) + + Fails, if 'actual' isn't a string. + + assert_not_string( actual, [msg] ) + + Fails, if 'actual' is a string. + + assert_table( actual, [msg] ) + + Fails, if 'actual' isn't a table. + + assert_not_table( actual, [msg] ) + + Fails, if 'actual' is a table. + + assert_function( actual, [msg] ) + + Fails, if 'actual' isn't a function. + + assert_not_function( actual, [msg] ) + + Fails, if 'actual' is a function. + + assert_thread( actual, [msg] ) + + Fails, if 'actual' isn't a thread (created by + coroutine.create or coroutine.wrap). + + assert_not_thread( actual, [msg] ) + + Fails, if 'actual' is a thread. + + assert_userdata( actual, [msg] ) + + Fails, if 'actual' isn't userdata. + + assert_not_userdata( actual, [msg] ) + + Fails, if 'actual' is userdata. + + assert_error( [msg], func ) + + Fails, if 'func' doesn't raises an error (using error()). + + assert_pass( [msg], func ) + + Fails, if 'func' raises an error. + + +All assert functions take an optional message as the last argument. Only +assert_pass() and assert_error() require the optional message as the first +argument. The last argument of these two are functions. + +There are also useful functions to test for the type of a value: + + is_nil( actual ) + is_boolean( actual ) + is_number( actual ) + is_string( actual ) + is_table( actual ) + is_function( actual ) + is_thread( actual ) + is_userdata( actual ) + +These all returns true if 'actual' is of correct type, otherwise false. + +You use the assert functions and the is_type functions in your tests to check +your code or package. Example: + + require "lunit" + + module( "my_testcase", lunit.testcase, package.seeall ) + + function FirstTest() + local result = compute_some_value() + assert_string( result ) + assert_equal("foobar", result) + end + + function test_something() + local result = flip_coin() -- flip_coin returns at random 0 or 1 + assert_number(result) + if result == 0 then + -- ok + elseif result == 1 then + -- ok + else + fail("flip_coin: invalid number: "..tostring(result)) + end + end + + +You can define the functions setup() and teardown() if you have to allocate +some resources or obtain some handles for your tests. +The setup() function is called before every test and teardown() is +called after every test. Example: + + require "lunit" + + module( "resource_testcase", lunit.testcase, package.seeall ) + + local orig_content, handle + + function setup() + orig_content = { "row 1", "row 2", "row 3" } + handle = database_open("test.db") + database_create_table(handle, ...) + database_fill_table(handle, orig_content, ...) + end + + function teardown() + database_drop_table(handle, ...) + database_close(handle) + handle = nil + orig_content = nil + delete_file("test.db") + end + + function test_select() + local content = database_select(handle, ...) + assert_table( content ) + assert_equal( orig_content, content ) + end + + function test_insert() + database_insert(handle, "row 4", ...) + local content = database_select(handle, ...) + assert_table( content ) + assert_equal( { "row 1", "row 2", "row 3", "row 4" }, content ) + end + + function test_delete() + database_delete(handle, "row 2", ...) + local content = database_select(handle, ...) + assert_table( content ) + assert_equal( { "row 1", "row 3" }, content ) + end + + +To run your testcases, simply use the shell script "lunit". Example: + + # ./lunit my_testcase.lua + diff --git a/src/external/lunit/LICENSE b/src/external/lunit/LICENSE new file mode 100644 index 000000000..1cd362603 --- /dev/null +++ b/src/external/lunit/LICENSE @@ -0,0 +1,32 @@ + +Lunit License +------------- + +Lunit is written by Michael Roth and is licensed +under the terms of the MIT license reproduced below. + +======================================================================== + +Copyright (c) 2004-2009 Michael Roth + +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. + +======================================================================== + diff --git a/src/external/lunit/PATCHES b/src/external/lunit/PATCHES new file mode 100644 index 000000000..2226ac119 --- /dev/null +++ b/src/external/lunit/PATCHES @@ -0,0 +1,12 @@ +Lunit is available through a public GIT repository. +To get the latest lunit source code, do: + + git clone git://repo.or.cz/lunit.git + +Currently there is no mailing list dedicated to lunit so if you have patches, +please send them to: + + mroth@nessie.de + +Please don't forget to add a Signed-Off-By line (git option -s or --signoff) +to state that your patches apply to the MIT license. diff --git a/src/external/lunit/README b/src/external/lunit/README new file mode 100644 index 000000000..690c148a1 --- /dev/null +++ b/src/external/lunit/README @@ -0,0 +1,12 @@ +This is lunit Version 0.5. + +Lunit is a unit testing framework for lua. + +To learn more about lunit take a look in ANNOUNCE +and look in DOCUMENTATION and check example.lua. + +If you have suggestions, questions or feature request please +feel free to contact me. + + +Michael Roth diff --git a/src/external/lunit/example.lua b/src/external/lunit/example.lua new file mode 100644 index 000000000..45347d5bc --- /dev/null +++ b/src/external/lunit/example.lua @@ -0,0 +1,40 @@ + +require "lunit" + + + +module( "simple", package.seeall, lunit.testcase ) + +function test_success() + assert_true( true, "This test never fails.") +end + +function test_failure() + assert_true( false, "This test always fails!") +end + + + +module( "enhanced", package.seeall, lunit.testcase ) + +local foobar = nil + +function setup() + foobar = "Hello World" +end + +function teardown() + foobar = nil +end + +function test1() + assert_equal("Hello World", foobar) + foobar = string.sub(foobar, 1, 5) + assert_equal("Hello", foobar) +end + +function test2() + assert_equal("Hello World", foobar) + foobar = string.sub(foobar, -5) + assert_equal("World", foobar) +end diff --git a/src/external/lunit/lunit b/src/external/lunit/lunit new file mode 100644 index 000000000..6bc010abd --- /dev/null +++ b/src/external/lunit/lunit @@ -0,0 +1,128 @@ +#! /bin/sh + +# This file is part of lunit 0.5. +# +# For Details about lunit look at: http://www.mroth.net/lunit/ +# +# Author: Michael Roth +# +# Copyright (c) 2004-2009 Michael Roth +# +# 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 < +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 . +EOT + exit ;; + + --version) + echo "lunit 0.5 Copyright 2004-2009 Michael Roth " + 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 "$@" < 0 or stats.failed > 0 then + os.exit(1) + end +EOT diff --git a/src/external/lunit/lunit-console.lua b/src/external/lunit/lunit-console.lua new file mode 100644 index 000000000..90c5165ed --- /dev/null +++ b/src/external/lunit/lunit-console.lua @@ -0,0 +1,141 @@ + +--[[-------------------------------------------------------------------------- + + This file is part of lunit 0.5. + + For Details about lunit look at: http://www.mroth.net/lunit/ + + Author: Michael Roth + + Copyright (c) 2006-2008 Michael Roth + + 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 + + + + + diff --git a/src/external/lunit/lunit-tests.lua b/src/external/lunit/lunit-tests.lua new file mode 100644 index 000000000..c5e39623a --- /dev/null +++ b/src/external/lunit/lunit-tests.lua @@ -0,0 +1,991 @@ + +--[[-------------------------------------------------------------------------- + + This file is part of lunit 0.5. + + For Details about lunit look at: http://www.mroth.net/lunit/ + + Author: Michael Roth + + Copyright (c) 2004, 2006-2009 Michael Roth + + 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. + +--]]-------------------------------------------------------------------------- + + +require "lunit" + + +local a_number = 123 +local a_string = "A string" +local a_table = { } +local a_function = function() end +local a_thread = coroutine.create(function() end) + +local pcall = pcall +local error = error +local pairs = pairs +local ipairs = ipairs + +local module = module + + + +module( "lunit-tests.interface", lunit.testcase ) + +function test() + local funcnames = { + "main", "run", "runtest", "testcase", "testcases", "tests", "setupname", + "teardownname", "loadrunner", "setrunner", "loadonly", + "assert", "assert_true", "assert_false", "assert_equal", "assert_not_equal", + "assert_match", "assert_not_match", "assert_nil", "assert_not_nil", + "assert_boolean", "assert_not_boolean", "assert_number", "assert_not_number", + "assert_string", "assert_not_string", "assert_table", "assert_not_table", + "assert_function", "assert_not_function", "assert_thread", "assert_not_thread", + "assert_userdata", "assert_not_userdata", "assert_pass", "assert_error", + "assert_error_match", "fail", "clearstats", + "is_nil", "is_boolean", "is_number", "is_string", "is_table", "is_function", + "is_thread", "is_userdata" + } + + for _, funcname in ipairs(funcnames) do + assert_function( lunit[funcname], "Public function missing: "..funcname ) + end + + assert_table( lunit.stats, "Statistic table missing" ) + + do + local map = {} + for _, name in ipairs(funcnames) do + map[name] = true + end + for _, name in ipairs{"lunit", "_PACKAGE", "_M", "_NAME", "stats"} do + map[name] = true + end + for name, _ in pairs(lunit) do + assert( map[name], "Invalid public variable: lunit."..name ) + end + end +end + + + +-- We must assume that errors thrown by test functions are detected. We use +-- the stdlib error() function to signal errors instead of fail(). +module( "lunit-tests.basics", lunit.testcase ) + +function test_fail() + local ok, errmsg + + ok, errmsg = pcall(function() fail() end) + if ok then + error("fail() doesn't fail!") + end + + ok, errmsg = pcall(function() fail("A message") end) + if ok then + error("fail(\"A message\") doesn't fail!") + end +end + +function test_assert_error() + local ok, errmsg + + ok, errmsg = pcall(function() assert_error(function() error("Error!") end) end) + if not ok then + error("assert_error( ) doesn't work!") + end + + ok, errmsg = pcall(function() assert_error("A message", function() error("Error") end) end) + if not ok then + error("assert_error(\"A message\", ) doesn't work!") + end + + ok, errmsg = pcall(function() assert_error(function() end) end) + if ok then + error("assert_error( ) doesn't fail!") + end + + ok, errmsg = pcall(function() assert_error("A Message", function() end) end) + if ok then + error("assert_error(\"A message\", ) doesn't fail!") + end +end + +function test_assert_pass() + local ok, errmsg + + ok, errmsg = pcall(function() assert_pass(function() error("Error!") end) end) + if ok then + error("assert_pass( ) doesn't fail!") + end + + ok, errmsg = pcall(function() assert_pass("A message", function() error("Error") end) end) + if ok then + error("assert_pass(\"A message\", ) doesn't fail!") + end + + ok, errmsg = pcall(function() assert_pass(function() end) end) + if not ok then + error("assert_pass( ) doesn't work!") + end + + ok, errmsg = pcall(function() assert_pass("A Message", function() end) end) + if not ok then + error("assert_pass(\"A message\", ) doesn't work!") + end +end + +function test_assert_true() + assert_pass("assert_true(true) doesn't work!", function() assert_true(true) end) + assert_pass("assert_true(true, \"A message\" doesn't work!", function() assert_true(true, "A Message") end) + assert_error("assert_true(false) doesn't fail!", function() assert_true(false) end) + assert_error("assert_true(false, \"A message\" doesn't fail!", function() assert_true(false, "A Message") end) +end + +function test_assert_false() + assert_pass("assert_false(false) doesn't work!", function() assert_false(false) end) + assert_pass("assert_false(false, \"A message\" doesn't work!", function() assert_false(false, "A Message") end) + assert_error("assert_false(true) doesn't fail!", function() assert_false(true) end) + assert_error("assert_false(true, \"A message\" doesn't fail!", function() assert_false(true, "A Message") end) +end + +function test_assert() + assert_pass("assert(true) doesn't work!", function() assert(true) end) + assert_pass("assert(12345) doesn't work!", function() assert(12345) end) + assert_pass("assert(\"A string\") doesn't work!", function() assert("A string") end) + assert_pass("assert( {} ) doesn't work!", function() assert( {} ) end) + assert_error("assert_(false) doesn't fail!", function() assert(false) end) + assert_error("assert_(nil) doesn't fail!", function() assert(nil) end) +end + +function test_assert_equal() + assert_pass("assert_equal(\"A String\", \"A String\") doesn't work!", function() + local a_string = assert_equal("A String", "A String") + assert_true("A String" == a_string) + end) + + assert_pass("assert_equal(\"A String\", \"A String\", \"A message\") doesn't work!", function() + local a_string = assert_equal("A String", "A String", "A message") + assert_true("A String" == a_string) + end) + + assert_pass("assert_equal(12345, 12345) doesn't work!", function() + local a_number = assert_equal(12345, 12345) + assert_true(12345 == a_number) + end) + + assert_pass("assert_equal(12345, 12345, \"A message\") doesn't work!", function() + local a_number = assert_equal(12345, 12345, "A message") + assert_true(12345 == a_number) + end) + + assert_pass("assert_equal(nil, nil) doesn't work!", function() + local a_nil = assert_equal(nil, nil) + assert_true(nil == a_nil) + end) + + assert_pass("assert_equal(12345, 12345, \"A message\") doesn't work!", function() + local a_nil = assert_equal(nil, nil, "A message") + assert_true(nil == a_nil) + end) + + assert_pass("assert_equal(false, false) doesn't work!", function() + local a_false = assert_equal(false, false) + assert_true(false == a_false) + end) + + assert_pass("assert_equal(false, false, \"A message\") doesn't work!", function() + local a_false = assert_equal(false, false, "A message") + assert_true(false == a_false) + end) + + assert_pass("assert_equal(true, true) doesn't work!", function() + local a_true = assert_equal(true, true) + assert_true(true == a_true) + end) + + assert_pass("assert_equal(true, true, \"A message\") doesn't work!", function() + local a_true = assert_equal(true, true, "A message") + assert_true(true == a_true) + end) + + assert_error("assert_equal(\"A String\", \"Another String\") doesn't fail!", function() + assert_equal("A String", "Another String") + end) + + assert_error("assert_equal(\"A String\", \"Another String\", \"A message\") doesn't fail!", function() + assert_equal("A String", "Another String", "A message") + end) + + assert_error("assert_equal(123, 456) doesn't fail!", function() + assert_equal(123, 456) + end) + + assert_error("assert_equal(123, 456) \"A message\") doesn't fail!", function() + assert_equal(123, 456, "A message") + end) + + assert_error("assert_equal(true, false) doesn't fail!", function() + assert_equal(true, false) + end) + + assert_error("assert_equal(true, false) \"A message\") doesn't fail!", function() + assert_equal(true, false, "A message") + end) + + assert_error("assert_equal(true, nil) doesn't fail!", function() + assert_equal(true, nil) + end) + + assert_error("assert_equal(true, nil) \"A message\") doesn't fail!", function() + assert_equal(true, nil, "A message") + end) + + assert_error("assert_equal(false, true) doesn't fail!", function() + assert_equal(false, true) + end) + + assert_error("assert_equal(false, true, \"A message\") doesn't fail!", function() + assert_equal(false, true, "A message") + end) + + assert_error("assert_equal(false, nil) doesn't fail!", function() + assert_equal(false, nil) + end) + + assert_error("assert_equal(false, nil) \"A message\") doesn't fail!", function() + assert_equal(false, nil, "A message") + end) + + assert_error("assert_equal(nil, true) doesn't fail!", function() + assert_equal(nil, true) + end) + + assert_error("assert_equal(nil, true) \"A message\") doesn't fail!", function() + assert_equal(nil, true, "A message") + end) + + assert_error("assert_equal(nil, false) doesn't fail!", function() + assert_equal(nil, false) + end) + + assert_error("assert_equal(nil, false) \"A message\") doesn't fail!", function() + assert_equal(nil, false, "A message") + end) +end + + +function test_assert_not_equal() + assert_pass("assert_not_equal(\"A String\", \"Another String\") doesn't work!", function() + local a_string = assert_not_equal("A String", "Another String") + assert_true("Another String" == a_string) + end) + + assert_pass("assert_not_equal(\"A String\", \"Another String\", \"A message\") doesn't work!", function() + local a_string = assert_not_equal("A String", "Another String", "A message") + assert_true("Another String" == a_string) + end) + + assert_pass("assert_not_equal(123, 456) doesn't work!", function() + local a_number = assert_not_equal(123, 456) + assert_true(456 == a_number) + end) + + assert_pass("assert_not_equal(123, 456, \"A message\") doesn't work!", function() + local a_number = assert_not_equal(123, 456, "A message") + assert_true(456 == a_number) + end) + + assert_pass("assert_not_equal(true, false) doesn't work!", function() + local a_false = assert_not_equal(true, false) + assert_true(false == a_false) + end) + + assert_pass("assert_not_equal(true, false) \"A message\") doesn't work!", function() + local a_false = assert_not_equal(true, false, "A message") + assert_true(false == a_false) + end) + + assert_pass("assert_not_equal(true, nil) doesn't work!", function() + local a_nil = assert_not_equal(true, nil) + assert_true(nil == a_nil) + end) + + assert_pass("assert_not_equal(true, nil) \"A message\") doesn't work!", function() + local a_nil = assert_not_equal(true, nil, "A message") + assert_true(nil == a_nil) + end) + + assert_pass("assert_not_equal(false, true) doesn't work!", function() + local a_true = assert_not_equal(false, true) + assert_true(true == a_true) + end) + + assert_pass("assert_not_equal(false, true, \"A message\") doesn't work!", function() + local a_true = assert_not_equal(false, true, "A message") + assert_true(true == a_true) + end) + + assert_pass("assert_not_equal(false, nil) doesn't work!", function() + local a_nil = assert_not_equal(false, nil) + assert_true(nil == a_nil) + end) + + assert_pass("assert_not_equal(false, nil) \"A message\") doesn't work!", function() + local a_nil = assert_not_equal(false, nil, "A message") + assert_true(nil == a_nil) + end) + + assert_pass("assert_not_equal(nil, true) doesn't work!", function() + local a_true = assert_not_equal(nil, true) + assert_true(true == a_true) + end) + + assert_pass("assert_not_equal(nil, true) \"A message\") doesn't work!", function() + local a_true = assert_not_equal(nil, true, "A message") + assert_true(true == a_true) + end) + + assert_pass("assert_not_equal(nil, false) doesn't work!", function() + local a_false = assert_not_equal(nil, false) + assert_true(false == a_false) + end) + + assert_pass("assert_not_equal(nil, false) \"A message\") doesn't work!", function() + local a_false = assert_not_equal(nil, false, "A message") + assert_true(false == a_false) + end) + + assert_error("assert_not_equal(\"A String\", \"A String\") doesn't work!", function() + assert_not_equal("A String", "A String") + end) + + assert_error("assert_not_equal(\"A String\", \"A String\", \"A message\") doesn't fail!", function() + assert_not_equal("A String", "A String", "A message") + end) + + assert_error("assert_not_equal(12345, 12345) doesn't fail!", function() + assert_not_equal(12345, 12345) + end) + + assert_error("assert_not_equal(12345, 12345, \"A message\") doesn't fail!", function() + assert_not_equal(12345, 12345, "A message") + end) + + assert_error("assert_not_equal(nil, nil) doesn't fail!", function() + assert_not_equal(nil, nil) + end) + + assert_error("assert_not_equal(nil, nil, \"A message\") doesn't fail!", function() + assert_not_equal(nil, nil, "A message") + end) + + assert_error("assert_not_equal(false, false) doesn't fail!", function() + assert_not_equal(false, false) + end) + + assert_error("assert_not_equal(false, false, \"A message\") doesn't fail!", function() + assert_not_equal(false, false, "A message") + end) + + assert_error("assert_not_equal(true, true) doesn't fail!", function() + assert_not_equal(true, true) + end) + + assert_error("assert_not_equal(true, true, \"A message\") doesn't fail!", function() + assert_not_equal(true, true, "A message") + end) +end + + + +module( "lunit-tests.is_xyz", lunit.testcase ) + +function test_is_nil() + assert_true( is_nil(nil) ) + assert_false( is_nil(true) ) + assert_false( is_nil(false) ) + assert_false( is_nil(a_number) ) + assert_false( is_nil(a_string) ) + assert_false( is_nil(a_table) ) + assert_false( is_nil(a_function) ) + assert_false( is_nil(a_thread) ) +end + +function test_is_boolean() + assert_true( is_boolean(false) ) + assert_true( is_boolean(true) ) + assert_false( is_boolean(nil) ) + assert_false( is_boolean(a_number) ) + assert_false( is_boolean(a_string) ) + assert_false( is_boolean(a_table) ) + assert_false( is_boolean(a_function) ) + assert_false( is_boolean(a_thread) ) +end + +function test_is_number() + assert_true( is_number(a_number) ) + assert_false( is_number(nil) ) + assert_false( is_number(true) ) + assert_false( is_number(false) ) + assert_false( is_number(a_string) ) + assert_false( is_number(a_table) ) + assert_false( is_number(a_function) ) + assert_false( is_number(a_thread) ) +end + +function test_is_string() + assert_true( is_string(a_string) ) + assert_false( is_string(nil) ) + assert_false( is_string(true) ) + assert_false( is_string(false) ) + assert_false( is_string(a_number) ) + assert_false( is_string(a_table) ) + assert_false( is_string(a_function) ) + assert_false( is_string(a_thread) ) +end + +function test_is_table() + assert_true( is_table(a_table) ) + assert_false( is_table(nil) ) + assert_false( is_table(true) ) + assert_false( is_table(false) ) + assert_false( is_table(a_number) ) + assert_false( is_table(a_string) ) + assert_false( is_table(a_function) ) + assert_false( is_table(a_thread) ) +end + +function test_is_function() + assert_true( is_function(a_function) ) + assert_false( is_function(nil) ) + assert_false( is_function(true) ) + assert_false( is_function(false) ) + assert_false( is_function(a_number) ) + assert_false( is_function(a_string) ) + assert_false( is_function(a_table) ) + assert_false( is_function(a_thread) ) +end + +function test_is_thread() + assert_true( is_thread(a_thread) ) + assert_false( is_thread(nil) ) + assert_false( is_thread(true) ) + assert_false( is_thread(false) ) + assert_false( is_thread(a_number) ) + assert_false( is_thread(a_string) ) + assert_false( is_thread(a_table) ) + assert_false( is_thread(a_function) ) +end + + + +module( "lunit-tests.assert_not_xyz", lunit.testcase ) + +function test_assert_not_nil() + assert_not_nil( true ) + assert_not_nil( false ) + assert_not_nil( a_number ) + assert_not_nil( a_string ) + assert_not_nil( a_table ) + assert_not_nil( a_function ) + assert_not_nil( a_thread ) + + assert_not_nil( true, "A message") + assert_not_nil( false, "A message") + assert_not_nil( a_number, "A message") + assert_not_nil( a_string, "A message") + assert_not_nil( a_table, "A message") + assert_not_nil( a_function, "A message") + assert_not_nil( a_thread, "A message") + + assert_error(function() assert_not_nil(nil) end) + assert_error(function() assert_not_nil(nil, "A message") end) +end + +function test_assert_not_boolean() + assert_not_boolean( nil ) + assert_not_boolean( a_number ) + assert_not_boolean( a_string ) + assert_not_boolean( a_table ) + assert_not_boolean( a_function ) + assert_not_boolean( a_thread ) + + assert_not_boolean( nil, "A message") + assert_not_boolean( a_number, "A message") + assert_not_boolean( a_string, "A message") + assert_not_boolean( a_table, "A message") + assert_not_boolean( a_function, "A message") + assert_not_boolean( a_thread, "A message") + + assert_error(function() assert_not_boolean(true) end) + assert_error(function() assert_not_boolean(true, "A message") end) + assert_error(function() assert_not_boolean(false) end) + assert_error(function() assert_not_boolean(false, "A message") end) +end + +function test_assert_not_number() + assert_not_number( nil ) + assert_not_number( true ) + assert_not_number( false ) + assert_not_number( a_string ) + assert_not_number( a_table ) + assert_not_number( a_function ) + assert_not_number( a_thread ) + + assert_not_number( nil, "A message") + assert_not_number( true, "A message") + assert_not_number( false, "A message") + assert_not_number( a_string, "A message") + assert_not_number( a_table, "A message") + assert_not_number( a_function, "A message") + assert_not_number( a_thread, "A message") + + assert_error(function() assert_not_number(a_number) end) + assert_error(function() assert_not_number(a_number, "A message") end) +end + +function test_assert_not_string() + assert_not_string( nil ) + assert_not_string( true ) + assert_not_string( false ) + assert_not_string( a_number ) + assert_not_string( a_table ) + assert_not_string( a_function ) + assert_not_string( a_thread ) + + assert_not_string( nil, "A message") + assert_not_string( true, "A message") + assert_not_string( false, "A message") + assert_not_string( a_number, "A message") + assert_not_string( a_table, "A message") + assert_not_string( a_function, "A message") + assert_not_string( a_thread, "A message") + + assert_error(function() assert_not_string(a_string) end) + assert_error(function() assert_not_string(a_string, "A message") end) +end + +function test_assert_not_table() + assert_not_table( nil ) + assert_not_table( true ) + assert_not_table( false ) + assert_not_table( a_number ) + assert_not_table( a_string ) + assert_not_table( a_function ) + assert_not_table( a_thread ) + + assert_not_table( nil, "A message") + assert_not_table( true, "A message") + assert_not_table( false, "A message") + assert_not_table( a_number, "A message") + assert_not_table( a_string, "A message") + assert_not_table( a_function, "A message") + assert_not_table( a_thread, "A message") + + assert_error(function() assert_not_table(a_table) end) + assert_error(function() assert_not_table(a_table, "A message") end) +end + +function test_assert_not_function() + assert_not_function( nil ) + assert_not_function( true ) + assert_not_function( false ) + assert_not_function( a_number ) + assert_not_function( a_string ) + assert_not_function( a_table ) + assert_not_function( a_thread ) + + assert_not_function( nil, "A message") + assert_not_function( true, "A message") + assert_not_function( false, "A message") + assert_not_function( a_number, "A message") + assert_not_function( a_string, "A message") + assert_not_function( a_table, "A message") + assert_not_function( a_thread, "A message") + + assert_error(function() assert_not_function(a_function) end) + assert_error(function() assert_not_function(a_function, "A message") end) +end + +function test_assert_not_thread() + assert_not_thread( nil ) + assert_not_thread( true ) + assert_not_thread( false ) + assert_not_thread( a_number ) + assert_not_thread( a_string ) + assert_not_thread( a_table ) + assert_not_thread( a_function ) + + assert_not_thread( nil, "A message") + assert_not_thread( true, "A message") + assert_not_thread( false, "A message") + assert_not_thread( a_number, "A message") + assert_not_thread( a_string, "A message") + assert_not_thread( a_table, "A message") + assert_not_thread( a_function, "A message") + + assert_error(function() assert_not_thread(a_thread) end) + assert_error(function() assert_not_thread(a_thread, "A message") end) +end + + + +module( "lunit-tests.assert_xyz", lunit.testcase ) + +function test_assert_nil() + assert_nil( nil ) + assert_nil( nil, "A message" ) + + assert_error( function() assert_nil( true ) end) + assert_error( function() assert_nil( false ) end) + assert_error( function() assert_nil( a_number ) end) + assert_error( function() assert_nil( a_string ) end) + assert_error( function() assert_nil( a_table ) end) + assert_error( function() assert_nil( a_function ) end) + assert_error( function() assert_nil( a_thread ) end) + + assert_error( function() assert_nil( true, "A message" ) end) + assert_error( function() assert_nil( false, "A message" ) end) + assert_error( function() assert_nil( a_number, "A message" ) end) + assert_error( function() assert_nil( a_string, "A message" ) end) + assert_error( function() assert_nil( a_table, "A message" ) end) + assert_error( function() assert_nil( a_function, "A message" ) end) + assert_error( function() assert_nil( a_thread, "A message" ) end) +end + +function test_assert_boolean() + assert_boolean( true ) + assert_boolean( false ) + assert_boolean( true, "A message" ) + assert_boolean( false, "A message" ) + + assert_error( function() assert_boolean( nil ) end) + assert_error( function() assert_boolean( a_number ) end) + assert_error( function() assert_boolean( a_string ) end) + assert_error( function() assert_boolean( a_table ) end) + assert_error( function() assert_boolean( a_function ) end) + assert_error( function() assert_boolean( a_thread ) end) + + assert_error( function() assert_boolean( nil, "A message" ) end) + assert_error( function() assert_boolean( a_number, "A message" ) end) + assert_error( function() assert_boolean( a_string, "A message" ) end) + assert_error( function() assert_boolean( a_table, "A message" ) end) + assert_error( function() assert_boolean( a_function, "A message" ) end) + assert_error( function() assert_boolean( a_thread, "A message" ) end) +end + +function test_assert_number() + assert_number( a_number ) + assert_number( a_number, "A message" ) + + assert_error( function() assert_number( nil ) end) + assert_error( function() assert_number( true ) end) + assert_error( function() assert_number( false ) end) + assert_error( function() assert_number( a_string ) end) + assert_error( function() assert_number( a_table ) end) + assert_error( function() assert_number( a_function ) end) + assert_error( function() assert_number( a_thread ) end) + + assert_error( function() assert_number( nil, "A message" ) end) + assert_error( function() assert_number( true, "A message" ) end) + assert_error( function() assert_number( false, "A message" ) end) + assert_error( function() assert_number( a_string, "A message" ) end) + assert_error( function() assert_number( a_table, "A message" ) end) + assert_error( function() assert_number( a_function, "A message" ) end) + assert_error( function() assert_number( a_thread, "A message" ) end) +end + +function test_assert_string() + assert_string( a_string ) + assert_string( a_string, "A message" ) + + assert_error( function() assert_string( nil ) end) + assert_error( function() assert_string( true ) end) + assert_error( function() assert_string( false ) end) + assert_error( function() assert_string( a_number ) end) + assert_error( function() assert_string( a_table ) end) + assert_error( function() assert_string( a_function ) end) + assert_error( function() assert_string( a_thread ) end) + + assert_error( function() assert_string( nil, "A message" ) end) + assert_error( function() assert_string( true, "A message" ) end) + assert_error( function() assert_string( false, "A message" ) end) + assert_error( function() assert_string( a_number, "A message" ) end) + assert_error( function() assert_string( a_table, "A message" ) end) + assert_error( function() assert_string( a_function, "A message" ) end) + assert_error( function() assert_string( a_thread, "A message" ) end) +end + +function test_assert_table() + assert_table( a_table ) + assert_table( a_table, "A message" ) + + assert_error( function() assert_table( nil ) end) + assert_error( function() assert_table( true ) end) + assert_error( function() assert_table( false ) end) + assert_error( function() assert_table( a_number ) end) + assert_error( function() assert_table( a_string ) end) + assert_error( function() assert_table( a_function ) end) + assert_error( function() assert_table( a_thread ) end) + + assert_error( function() assert_table( nil, "A message" ) end) + assert_error( function() assert_table( true, "A message" ) end) + assert_error( function() assert_table( false, "A message" ) end) + assert_error( function() assert_table( a_number, "A message" ) end) + assert_error( function() assert_table( a_string, "A message" ) end) + assert_error( function() assert_table( a_function, "A message" ) end) + assert_error( function() assert_table( a_thread, "A message" ) end) +end + +function test_assert_function() + assert_function( a_function ) + assert_function( a_function, "A message" ) + + assert_error( function() assert_function( nil ) end) + assert_error( function() assert_function( true ) end) + assert_error( function() assert_function( false ) end) + assert_error( function() assert_function( a_number ) end) + assert_error( function() assert_function( a_string ) end) + assert_error( function() assert_function( a_table ) end) + assert_error( function() assert_function( a_thread ) end) + + assert_error( function() assert_function( nil, "A message" ) end) + assert_error( function() assert_function( true, "A message" ) end) + assert_error( function() assert_function( false, "A message" ) end) + assert_error( function() assert_function( a_number, "A message" ) end) + assert_error( function() assert_function( a_string, "A message" ) end) + assert_error( function() assert_function( a_table, "A message" ) end) + assert_error( function() assert_function( a_thread, "A message" ) end) +end + +function test_assert_thread() + assert_thread( a_thread ) + assert_thread( a_thread, "A message" ) + + assert_error( function() assert_thread( nil ) end) + assert_error( function() assert_thread( true ) end) + assert_error( function() assert_thread( false ) end) + assert_error( function() assert_thread( a_number ) end) + assert_error( function() assert_thread( a_string ) end) + assert_error( function() assert_thread( a_table ) end) + assert_error( function() assert_thread( a_function ) end) + + assert_error( function() assert_thread( nil, "A message" ) end) + assert_error( function() assert_thread( true, "A message" ) end) + assert_error( function() assert_thread( false, "A message" ) end) + assert_error( function() assert_thread( a_number, "A message" ) end) + assert_error( function() assert_thread( a_string, "A message" ) end) + assert_error( function() assert_thread( a_table, "A message" ) end) + assert_error( function() assert_thread( a_function, "A message" ) end) +end + + + +module( "lunit-tests.match", lunit.testcase ) + +function test_assert_match() + assert_pass("assert_match(\"^Hello\", \"Hello World\") doesn't work!", function() + local a_string = assert_match("^Hello", "Hello World") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_match(\"^Hello\", \"Hello World\", \"A Message\") doesn't work!", function() + local a_string = assert_match("^Hello", "Hello World", "A message") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_match(\"World$\", \"Hello World\") doesn't work!", function() + local a_string = assert_match("World$", "Hello World") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_match(\"World$\", \"Hello World\", \"A Message\") doesn't work!", function() + local a_string = assert_match("World$", "Hello World", "A message") + assert_equal("Hello World", a_string) + end) + + assert_error("assert_match(\"Hello$\", \"Hello World\") doesn't fail!", function() + assert_match("Hello$", "Hello World") + end) + + assert_error("assert_match(\"Hello$\", \"Hello World\", \"A Message\") doesn't fail!", function() + assert_match("Hello$", "Hello World", "A message") + end) + + assert_error("assert_match(\"^World\", \"Hello World\") doesn't fail!", function() + assert_match("^World", "Hello World") + end) + + assert_error("assert_match(\"^World\", \"Hello World\", \"A Message\") doesn't fail!", function() + assert_match("^World", "Hello World", "A message") + end) + + assert_error("assert_match(nil, \"Hello World\") doesn't fail!", function() + assert_match(nil, "Hello World") + end) + + assert_error("assert_match(nil, \"Hello World\", \"A Message\") doesn't fail!", function() + assert_match(nil, "Hello World", "A message") + end) + + assert_error("assert_match(\"^World\", nil) doesn't fail!", function() + assert_match("^World", nil) + end) + + assert_error("assert_match(\"^World\", nil, \"A Message\") doesn't fail!", function() + assert_match("^World", nil, "A message") + end) +end + +function test_assert_not_match() + assert_pass("assert_not_match(\"Hello$\", \"Hello World\") doesn't work!", function() + local a_string = assert_not_match("Hello$", "Hello World") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_not_match(\"Hello$\", \"Hello World\", \"A Message\") doesn't work!", function() + local a_string = assert_not_match("Hello$", "Hello World", "A message") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_not_match(\"^World\", \"Hello World\") doesn't work!", function() + local a_string = assert_not_match("^World", "Hello World") + assert_equal("Hello World", a_string) + end) + + assert_pass("assert_not_match(\"^World\", \"Hello World\", \"A Message\") doesn't work!", function() + local a_string = assert_not_match("^World", "Hello World", "A message") + assert_equal("Hello World", a_string) + end) + + assert_error("assert_not_match(\"^Hello\", \"Hello World\") doesn't fail!", function() + assert_not_match("^Hello", "Hello World") + end) + + assert_error("assert_not_match(\"^Hello\", \"Hello World\", \"A Message\") doesn't fail!", function() + assert_not_match("^Hello", "Hello World", "A message") + end) + + assert_error("assert_not_match(\"World$\", \"Hello World\") doesn't fail!", function() + assert_not_match("World$", "Hello World") + end) + + assert_error("assert_not_match(\"World$\", \"Hello World\", \"A Message\") doesn't fail!", function() + assert_not_match("World$", "Hello World", "A message") + end) + + assert_error("assert_not_match(nil, \"Hello World\") doesn't fail!", function() + assert_not_match(nil, "Hello World") + end) + + assert_error("assert_not_match(nil, \"Hello World\", \"A Message\") doesn't fail!", function() + assert_not_match(nil, "Hello World", "A message") + end) + + assert_error("assert_not_match(\"^World\", nil) doesn't fail!", function() + assert_not_match("^World", nil) + end) + + assert_error("assert_not_match(\"^World\", nil, \"A Message\") doesn't fail!", function() + assert_not_match("^World", nil, "A message") + end) +end + +function test_assert_error_match() + local ok, errobj, usrmsg + + local function errfunc() + error("My Error!") + end + + local errpattern = "Error!$" + local wrongpattern = "^_foobar_$" + + local function goodfunc() + -- NOP + end + + ok = pcall(function() assert_error_match(errpattern, errfunc) end) + assert_true(ok, "assert_error_match( , )") + + ok = pcall(function() assert_error_match("A message", errpattern, errfunc) end) + assert_true(ok, "assert_error_match(\"A message\", , )") + + usrmsg = "assert_error_match( , )" + ok, errobj = pcall(function() assert_error_match(wrongpattern, errfunc) end) + assert_false(ok, usrmsg) + assert_table(errobj, usrmsg) + assert_match("expected error '.+: My Error!' to match pattern '"..wrongpattern.."' but doesn't$", errobj.msg, usrmsg) + + usrmsg = "assert_error_match(\"A message\", , )" + ok, errobj = pcall(function() assert_error_match("A message", wrongpattern, errfunc) end) + assert_false(ok, usrmsg) + assert_table(errobj, usrmsg) + assert_match("expected error '.+: My Error!' to match pattern '"..wrongpattern.."' but doesn't$", errobj.msg, usrmsg) + + usrmsg = "assert_error_match( , )" + ok, errobj = pcall(function() assert_error_match(errpattern, goodfunc) end) + assert_false(ok, usrmsg) + assert_table(errobj, usrmsg) + assert_match("error expected but no error occurred$", errobj.msg, usrmsg) + + usrmsg = "assert_error_match(\"A message\", , )" + ok, errobj = pcall(function() assert_error_match("A Message", errpattern, goodfunc) end) + assert_false(ok, usrmsg) + assert_table(errobj, usrmsg) + assert_match("error expected but no error occurred$", errobj.msg, usrmsg) +end + + + +module( "lunit-tests.setup-teardown", lunit.testcase ) + +local setup_called = 0 +local teardown_called = 0 +local helper_called = 0 + +function setup() + setup_called = setup_called + 1 +end + +function Teardown() + teardown_called = teardown_called + 1 +end + +local function helper() + helper_called = helper_called + 1 + assert(setup_called == helper_called, "setup() not called") + assert(teardown_called == helper_called - 1, "teardown() not called") +end + +function test1() + helper() +end + +function test2() + helper() +end + +function test3() + helper() +end diff --git a/src/external/lunit/lunit.lua b/src/external/lunit/lunit.lua new file mode 100644 index 000000000..52d45880a --- /dev/null +++ b/src/external/lunit/lunit.lua @@ -0,0 +1,670 @@ + +--[[-------------------------------------------------------------------------- + + This file is part of lunit 0.5. + + For Details about lunit look at: http://www.mroth.net/lunit/ + + Author: Michael Roth + + Copyright (c) 2004, 2006-2009 Michael Roth + + 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() + clearstats() + report("begin") + for testcasename in lunit.testcases() do + -- Run tests in the testcases + for testname in lunit.tests(testcasename) do + runtest(testcasename, testname) + 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] = 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()