[asterisk-commits] mnicholson: testsuite/asterisk/trunk r651 - in /asterisk/trunk/asttest: inclu...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Jul 29 13:55:03 CDT 2010
Author: mnicholson
Date: Thu Jul 29 13:54:59 2010
New Revision: 651
URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=651
Log:
Added the ability to have functions run when a test exits (no matter the reason for exit). Also added self tests for this functionality.
Added:
asterisk/trunk/asttest/self-tests/test_atexit1/
asterisk/trunk/asttest/self-tests/test_atexit1/test.lua (with props)
asterisk/trunk/asttest/self-tests/test_atexit2/
asterisk/trunk/asttest/self-tests/test_atexit2/test.lua (with props)
asterisk/trunk/asttest/self-tests/test_atexit3/
asterisk/trunk/asttest/self-tests/test_atexit3/test.lua (with props)
Modified:
asterisk/trunk/asttest/include/asttest/lua/testlib.h
asterisk/trunk/asttest/lib/lua/testlib.c
asterisk/trunk/asttest/lib/lua/testlib.lua
asterisk/trunk/asttest/lib/testutils.c
Modified: asterisk/trunk/asttest/include/asttest/lua/testlib.h
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/include/asttest/lua/testlib.h?view=diff&rev=651&r1=650&r2=651
==============================================================================
--- asterisk/trunk/asttest/include/asttest/lua/testlib.h (original)
+++ asterisk/trunk/asttest/include/asttest/lua/testlib.h Thu Jul 29 13:54:59 2010
@@ -22,6 +22,10 @@
#include <lua.h>
int testlib_expected_fail(lua_State *L);
+int testlib_atexit(lua_State *L, int result_index);
+int testlib_preprocess_result(lua_State *L);
+int testlib_default_result(lua_State *L);
+
int luaopen_testlib(lua_State *L);
#endif
Modified: asterisk/trunk/asttest/lib/lua/testlib.c
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/lib/lua/testlib.c?view=diff&rev=651&r1=650&r2=651
==============================================================================
--- asterisk/trunk/asttest/lib/lua/testlib.c (original)
+++ asterisk/trunk/asttest/lib/lua/testlib.c Thu Jul 29 13:54:59 2010
@@ -23,6 +23,24 @@
#include "asttest/testsuite.h"
#include "testlib_lua.h"
+
+/*
+ * \brief Push the current testsuite on the stack and return a pointer to it.
+ * \param L the lua state to use
+ */
+static struct testsuite *push_ts(lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "testlib_ts");
+ return lua_touserdata(L, -1);
+}
+
+/*
+ * \brief Push the current test's name on the stack and return a pointer to it.
+ * \param L the lua state to use
+ */
+static const char *push_test_name(lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "testlib_name");
+ return lua_tostring(L, -1);
+}
/*
* \brief Check if the current test was expected to fail or not.
@@ -40,21 +58,112 @@
}
/*
- * \brief Push the current testsuite on the stack and return a pointer to it.
- * \param L the lua state to use
- */
-static struct testsuite *push_ts(lua_State *L) {
- lua_getfield(L, LUA_REGISTRYINDEX, "testlib_ts");
- return lua_touserdata(L, -1);
-}
-
-/*
- * \brief Push the current test's name on the stack and return a pointer to it.
- * \param L the lua state to use
- */
-static const char *push_test_name(lua_State *L) {
- lua_getfield(L, LUA_REGISTRYINDEX, "testlib_name");
- return lua_tostring(L, -1);
+ * \brief Run the atexit functions.
+ * \param L the lua state to use
+ * \param result_index the index where the test results are located
+ *
+ * This function runs all of the atexit functions in the order they were
+ * registered. These functions may change the result of the test. Any errors
+ * that are encountered are logged.
+ *
+ * \note This function expects testlib to be loaded, which should always be the
+ * case by the time it is called.
+ * \warn The old results are removed from the stack when new results are pushed.
+ * \return 0 on success, non zero if new test results have been pushed to the stack.
+ */
+int testlib_atexit(lua_State *L, int result_index) {
+ int funcs, res, new_result = 0;
+ struct testsuite *ts;
+ const char *name;
+
+ lua_getfield(L, LUA_REGISTRYINDEX, "testlib_atexit");
+ funcs = lua_gettop(L);
+
+ lua_pushnil(L);
+ while (lua_next(L, funcs)) {
+ lua_pushvalue(L, result_index);
+
+ if ((res = lua_pcall(L, 1, 0, 0))) {
+ if (lua_isstring(L, -1)) {
+ /* error */
+ ts = push_ts(L);
+ name = push_test_name(L);
+ ts_log(ts, name, "atexit error: %s\n", lua_tostring(L, -3));
+
+ /* name, ts, and the error */
+ lua_pop(L, 3);
+ } else if (lua_type(L, -1) == LUA_TTABLE) {
+ /* got a new result */
+ if (new_result) {
+ /* remove the old new result */
+ lua_remove(L, new_result);
+ funcs -= 1;
+ }
+ /* move the new results under 'funcs' in the stack */
+ lua_insert(L, funcs);
+ new_result = funcs;
+ funcs += 1;
+ } else {
+ /* got some other error value returned, probably a missing test result */
+ ts = push_ts(L);
+ name = push_test_name(L);
+ ts_log(ts, name, "atexit error: missing test result\n");
+
+ /* name, ts, and the error */
+ lua_pop(L, 3);
+ }
+ }
+ }
+
+ /* remove the atexit functions */
+ lua_pop(L, 1);
+
+ return new_result;
+}
+
+/*
+ * \brief This function will turn lua errors into result tables and process
+ * unknown results into result tables.
+ * \param L the lua state to use
+ * \note This function expects the result/error to be on the top of the stack.
+ */
+void testlib_preprocess_result(lua_State *L) {
+ int result_index = lua_gettop(L);
+ if (lua_isstring(L, -1)) {
+ /* error string */
+ lua_newtable(L);
+
+ lua_pushliteral(L, "error");
+ lua_setfield(L, -2, "result");
+
+ lua_pushvalue(L, result_index);
+ lua_setfield(L, -2, "reason");
+
+ lua_remove(L, result_index);
+ } else if (lua_type(L, -1) == LUA_TTABLE) {
+ /* do nothing */
+ } else {
+ /* unknown error type, discard it */
+ lua_pop(L, 1);
+ lua_newtable(L);
+
+ lua_pushliteral(L, "error");
+ lua_setfield(L, -2, "result");
+
+ lua_pushliteral(L, "missing test result");
+ lua_setfield(L, -2, "reason");
+ }
+}
+
+/*
+ * \brief Push the default test result to the stack (pass is the default).
+ * \param L the lua state to use
+ */
+void testlib_default_result(lua_State *L) {
+ lua_newtable(L);
+
+ lua_pushliteral(L, "pass");
+ lua_setfield(L, -2, "result");
}
/*
@@ -83,9 +192,54 @@
return 0;
}
+/*
+ * \brief Add a function to the end of the atexit table.
+ *
+ * Each atexit function that is called is passed a table containing the result
+ * of the current test in the following form.
+ *
+ * \code
+ * table = {
+ * result = "pass" or "fail" or "skip" or "error";
+ * reason = nil or "reason string";
+ * }
+ * \endcode
+ *
+ * At exit functions can alter the test result using the same method test
+ * results are returned from a test (pass(), fail(), etc.). All atexit
+ * functions are passed the original test result, not any modified results.
+ * The last modified test result returned will be passed to the testsuite
+ * engine.
+ */
+static int lua_atexit(lua_State *L) {
+ luaL_checktype(L, 1, LUA_TFUNCTION);
+
+ lua_getglobal(L, "table");
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ return luaL_error(L, "error running table.insert, 'table' lib not found");
+ }
+
+ lua_getfield(L, -1, "insert");
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 2);
+ return luaL_error(L, "error running table.insert, 'insert' not found in 'table' lib");
+ }
+
+ /* remove the 'table' table from the stack */
+ lua_remove(L, -2);
+
+ /* call table.insert to add the function to the atexit table */
+ lua_getfield(L, LUA_REGISTRYINDEX, "testlib_atexit");
+ lua_pushvalue(L, 1);
+ lua_call(L, 2, 0);
+ return 0;
+}
+
static luaL_Reg testlib[] = {
{"log", lua_ts_log},
{"xfail", lua_xfail},
+ {"atexit", lua_atexit},
{NULL, NULL},
};
@@ -96,6 +250,10 @@
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
ts = lua_touserdata(L, 1);
test_name = luaL_checkstring(L, 2);
+
+ /* set up atexit table */
+ lua_newtable(L);
+ lua_setfield(L, LUA_REGISTRYINDEX, "testlib_atexit");
/* set up some registry values */
lua_pushlightuserdata(L, ts);
Modified: asterisk/trunk/asttest/lib/lua/testlib.lua
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/lib/lua/testlib.lua?view=diff&rev=651&r1=650&r2=651
==============================================================================
--- asterisk/trunk/asttest/lib/lua/testlib.lua (original)
+++ asterisk/trunk/asttest/lib/lua/testlib.lua Thu Jul 29 13:54:59 2010
@@ -38,6 +38,7 @@
_G.lua_error = _G.error
_G.xfail = xfail
+_G.atexit = atexit
--
-- basic pass/fail/skip/error functions
Modified: asterisk/trunk/asttest/lib/testutils.c
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/lib/testutils.c?view=diff&rev=651&r1=650&r2=651
==============================================================================
--- asterisk/trunk/asttest/lib/testutils.c (original)
+++ asterisk/trunk/asttest/lib/testutils.c Thu Jul 29 13:54:59 2010
@@ -66,7 +66,7 @@
*
* \code
* table = {
- * result = "pass" or "fail" or "xfail" or "skip";
+ * result = "pass" or "fail" or "skip" or "error";
* reason = nil or "reason string";
* }
* \endcode
@@ -74,13 +74,9 @@
static enum ts_result process_test_result(struct testsuite *ts, const char *test_name, lua_State *L) {
enum ts_result res = TS_ERROR;
- if (lua_isstring(L, -1)) {
- /* this is not a test result, log the error */
- ts_log(ts, test_name, "error: %s\n", lua_tostring(L, -1));
- lua_pop(L, 1);
-
- res = ts_error(ts, test_name);
- } else if (lua_type(L, -1) == LUA_TTABLE) {
+ testlib_preprocess_result(L);
+
+ if (lua_type(L, -1) == LUA_TTABLE) {
int result_table = lua_gettop(L);
int reason_string = 0;
int test_result = 0;
@@ -129,6 +125,8 @@
lua_pop(L, 1);
} else {
+ /* this should never happen, testlib_preprocess_result() should
+ * convert any values to proper result tables for us */
lua_pop(L, 1);
ts_log(ts, test_name, "missing test result\n");
res = ts_error(ts, test_name);
@@ -191,6 +189,7 @@
lua_State *L;
char original_path[PATH_MAX];
enum ts_result result;
+ int result_index;
if (!getcwd(original_path, PATH_MAX)) {
ts_log(ts, test_name, "internal error storing current path, PATH_MAX is too small\n");
@@ -209,15 +208,20 @@
return ts_error(ts, test_name);
}
- if (luaL_dofile(L, "test.lua")) {
- result = process_test_result(ts, test_name, L);
- } else {
- /* we got no explicit result, consider it a pass or xpass*/
- if (testlib_expected_fail(L))
- result = ts_xpass(ts, test_name);
- else
- result = ts_pass(ts, test_name);
- }
+ if (!luaL_dofile(L, "test.lua")) {
+ /* we got no explicit result, consider it a pass for now */
+ testlib_default_result(L);
+ }
+
+ /* run our atexit functions */
+ testlib_preprocess_result(L);
+ result_index = lua_gettop(L);
+ if (testlib_atexit(L, result_index)) {
+ lua_remove(L, result_index);
+ }
+
+ /* process the test result */
+ result = process_test_result(ts, test_name, L);
if (chdir(original_path))
ts_log(ts, test_name, "error changing directories, this may cause further errors (%s)\n", strerror(errno));
Added: asterisk/trunk/asttest/self-tests/test_atexit1/test.lua
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/self-tests/test_atexit1/test.lua?view=auto&rev=651
==============================================================================
--- asterisk/trunk/asttest/self-tests/test_atexit1/test.lua (added)
+++ asterisk/trunk/asttest/self-tests/test_atexit1/test.lua Thu Jul 29 13:54:59 2010
@@ -1,0 +1,15 @@
+function do_error(result)
+ fail_if(result.result ~= "fail", "expected result to be 'fail' here in do_error()")
+ print("I am going to cause an error")
+ this_will_cause_an_error()
+end
+
+function do_pass(result)
+ fail_if(result.result ~= "fail", "expected result to be 'fail' here in do_pass()")
+ pass()
+end
+
+test.atexit(do_error)
+test.atexit(do_pass)
+fail("this test shouldn't actually fail")
+
Propchange: asterisk/trunk/asttest/self-tests/test_atexit1/test.lua
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/trunk/asttest/self-tests/test_atexit1/test.lua
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/trunk/asttest/self-tests/test_atexit1/test.lua
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: asterisk/trunk/asttest/self-tests/test_atexit2/test.lua
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/self-tests/test_atexit2/test.lua?view=auto&rev=651
==============================================================================
--- asterisk/trunk/asttest/self-tests/test_atexit2/test.lua (added)
+++ asterisk/trunk/asttest/self-tests/test_atexit2/test.lua Thu Jul 29 13:54:59 2010
@@ -1,0 +1,15 @@
+function do_error()
+ fail_if(result.result ~= "pass", "expected 'pass' here in do_error()")
+ print("I am going to cause an error")
+ this_will_cause_an_error()
+end
+
+function do_nothing()
+ fail_if(result.result ~= "pass", "expected 'pass' here in do_nothing()")
+end
+
+test.atexit(do_error)
+test.atexit(do_nothing)
+test.atexit(do_nothing)
+test.atexit(do_nothing)
+
Propchange: asterisk/trunk/asttest/self-tests/test_atexit2/test.lua
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/trunk/asttest/self-tests/test_atexit2/test.lua
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/trunk/asttest/self-tests/test_atexit2/test.lua
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: asterisk/trunk/asttest/self-tests/test_atexit3/test.lua
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/asttest/self-tests/test_atexit3/test.lua?view=auto&rev=651
==============================================================================
--- asterisk/trunk/asttest/self-tests/test_atexit3/test.lua (added)
+++ asterisk/trunk/asttest/self-tests/test_atexit3/test.lua Thu Jul 29 13:54:59 2010
@@ -1,0 +1,19 @@
+function do_fail()
+ fail_if(result.result ~= "pass", "result in do_fail() was not 'pass'")
+ fail()
+end
+
+function do_pass(result)
+ fail_if(result.result ~= "pass", "result in do_pass() was not 'pass'")
+ pass()
+end
+
+function do_nothing()
+ fail_if(result.result ~= "pass", "result in do_nothing() was not 'pass'")
+end
+
+test.atexit(do_fail)
+test.atexit(do_pass)
+test.atexit(do_pass)
+test.atexit(do_nothing)
+
Propchange: asterisk/trunk/asttest/self-tests/test_atexit3/test.lua
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: asterisk/trunk/asttest/self-tests/test_atexit3/test.lua
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: asterisk/trunk/asttest/self-tests/test_atexit3/test.lua
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list