[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