[asterisk-commits] mnicholson: branch mnicholson/asttest r167122 - /team/mnicholson/asttest/astt...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Dec 31 19:34:43 CST 2008
Author: mnicholson
Date: Wed Dec 31 19:34:42 2008
New Revision: 167122
URL: http://svn.digium.com/view/asterisk?view=rev&rev=167122
Log:
Added logging and test result analysis.
* asttest/asttest.c (test_suite_*): renamed test_suite_* functions to ts_*
* asttest/asttest.c (ts_log, ts_log_va): added
* asttest/asttest.c (struct test_suite): added FILE *log member
* asttest/asttest.c (run_test): added test_name paramater and modified to
process the test result
* asttest/asttest.c (process_test_result, result_equals): added, used to
process test results
Modified:
team/mnicholson/asttest/asttest/asttest.c
Modified: team/mnicholson/asttest/asttest/asttest.c
URL: http://svn.digium.com/view/asterisk/team/mnicholson/asttest/asttest/asttest.c?view=diff&rev=167122&r1=167121&r2=167122
==============================================================================
--- team/mnicholson/asttest/asttest/asttest.c (original)
+++ team/mnicholson/asttest/asttest/asttest.c Wed Dec 31 19:34:42 2008
@@ -37,13 +37,28 @@
unsigned int xfail;
unsigned int skip;
unsigned int total;
+ FILE *log;
};
-void test_suite_init(struct test_suite *ts) {
+int ts_init(struct test_suite *ts, const char *log_file_path) {
memset(ts, 0, sizeof(struct test_suite));
-}
-
-void test_suite_print_results(struct test_suite *ts) {
+
+ ts->log = fopen(log_file_path, "w");
+ if (!ts->log) {
+ fprintf(stderr, "Error log file (%s): %s\n", log_file_path, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+void ts_cleanup(struct test_suite *ts) {
+ if (ts->log) {
+ fclose(ts->log);
+ }
+}
+
+void ts_print(struct test_suite *ts) {
printf("Test results:\n");
printf(" tests passed: %d\n", ts->pass);
printf(" test failures: %d\n", ts->fail);
@@ -53,27 +68,142 @@
printf("Total test run: %d\n", ts->total);
}
-void test_suite_pass(struct test_suite *ts) {
+int ts_log_va(struct test_suite *ts, const char *test_name, const char *fmt, va_list ap) {
+ int res;
+ res = fprintf(ts->log, "%s: ", test_name);
+ res += vfprintf(ts->log, fmt, ap);
+ return res;
+}
+
+int __attribute__((format(printf, 3, 4))) ts_log(struct test_suite *ts, const char *test_name, const char *fmt, ...) {
+ va_list ap;
+ int res;
+ va_start(ap, fmt);
+ res = ts_log_va(ts, test_name, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
+void ts_pass(struct test_suite *ts, const char *test_name) {
ts->pass++;
ts->total++;
-}
-
-void test_suite_fail(struct test_suite *ts) {
+
+ ts_log(ts, test_name, "test passed\n");
+}
+
+void ts_fail(struct test_suite *ts, const char *test_name) {
ts->fail++;
ts->total++;
-}
-
-void test_suite_xfail(struct test_suite *ts) {
+
+ ts_log(ts, test_name, "test failed\n");
+}
+
+void ts_xfail(struct test_suite *ts, const char *test_name) {
ts->xfail++;
ts->total++;
-}
-
-void test_suite_skip(struct test_suite *ts) {
+
+ ts_log(ts, test_name, "expected failure\n");
+}
+
+void ts_skip(struct test_suite *ts, const char *test_name) {
ts->skip++;
ts->total++;
-}
-
-int run_test(struct test_suite *ts, const char *test_dir_path) {
+
+ ts_log(ts, test_name, "test skipped\n");
+}
+
+/*
+ * \brief Check if the given result string equals the string stored at the
+ * given index.
+ * \param L the lua state to use
+ * \param result_index the index of the result string
+ * \param result_string the result string to check for equality with the string
+ * at the given index
+ */
+int result_equals(lua_State *L, int result_index, const char *result_string) {
+ int res;
+ lua_pushstring(L, result_string);
+ res = lua_equal(L, -1, result_index);
+ lua_pop(L, 1);
+ return res;
+}
+
+/*
+ * \brief Process the result of a test.
+ * \param ts the current test suite
+ * \param L the lua state the test was run in
+ *
+ * This function expects to be called after luaL_dofile/lua_pcall and will
+ * analyze the result of running the test. The testing framework will pass a
+ * special table containg the test result to lua_error() that is used by this
+ * function.
+ *
+ * The table is expected in the following format:
+ *
+ * \code
+ * table = {
+ * result = "pass" or "fail" or "xfail" or "skip";
+ * reason = nil or "reason string";
+ * }
+ * \endcode
+ */
+void process_test_result(struct test_suite *ts, const char *test_name, lua_State *L) {
+ 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);
+
+ ts_skip(ts, test_name);
+ } else if (lua_type(L, -1) == LUA_TTABLE) {
+ int result_table = lua_gettop(L);
+ int reason_string = 0;
+ int test_result = 0;
+
+ lua_getfield(L, result_table, "reason");
+ if (!lua_isnil(L, -1) && lua_isstring(L, -1))
+ reason_string = lua_gettop(L);
+ else
+ lua_pop(L, 1);
+
+ lua_getfield(L, result_table, "result");
+ if (lua_isnil(L, -1)) {
+ lua_pop(L, 1);
+ ts_log(ts, test_name, "error reading test result\n");
+ ts_skip(ts, test_name);
+ } else {
+ test_result = lua_gettop(L);
+
+ if (reason_string)
+ ts_log(ts, test_name, "%s\n", lua_tostring(L, reason_string));
+
+ if (result_equals(L, test_result, "pass")) {
+ ts_pass(ts, test_name);
+ } else if (result_equals(L, test_result, "fail")) {
+ ts_fail(ts, test_name);
+ } else if (result_equals(L, test_result, "xfail")) {
+ ts_xfail(ts, test_name);
+ } else if (result_equals(L, test_result, "skip")) {
+ ts_skip(ts, test_name);
+ } else {
+ ts_log(ts, test_name, "unknown result '%s'\n", lua_tostring(L, test_result));
+ ts_skip(ts, test_name);
+ }
+ }
+
+ if (reason_string)
+ lua_remove(L, reason_string);
+ if (test_result)
+ lua_remove(L, test_result);
+
+ lua_pop(L, 1);
+ } else {
+ lua_pop(L, 1);
+ ts_log(ts, test_name, "missing test result\n");
+ ts_skip(ts, test_name);
+ }
+}
+
+int run_test(struct test_suite *ts, const char *test_name, const char *test_dir_path) {
char test_file_path[1024];
lua_State *L = luaL_newstate();
if (!L) {
@@ -84,11 +214,15 @@
luaL_openlibs(L);
// TODO load the standard test libraries
-
- snprintf(test_file_path, sizeof(test_file_path), "%s/test.lua", test_file_path);
+
+ snprintf(test_file_path, sizeof(test_file_path), "%s/test.lua", test_dir_path);
if (luaL_dofile(L, test_file_path)) {
- // TODO print error message
- test_suite_skip(ts);
+ process_test_result(ts, test_name, L);
+ lua_close(L);
+ return 1;
+ } else {
+ ts_log(ts, test_name, "test did not return a result\n");
+ ts_skip(ts, test_name);
lua_close(L);
return 1;
}
@@ -129,17 +263,19 @@
return 1;
}
- test_suite_init(&ts);
+ ts_init(&ts, "asttest.log");
while ((ent = readdir(main_dir))) {
snprintf(full_path, sizeof(full_path), "%s/%s", path, ent->d_name);
if (is_directory(full_path) && !ignored_dir(full_path)) {
- run_test(&ts, full_path);
+ run_test(&ts, ent->d_name, full_path);
}
}
closedir(main_dir);
- test_suite_print_results(&ts);
+ ts_print(&ts);
+
+ ts_cleanup(&ts);
return 0;
}
@@ -155,5 +291,7 @@
return 1;
}
+ // TODO process args and except --log (-l) as an argument for where to log
+
return process_tests_in_dir(argv[1]);
}
More information about the asterisk-commits
mailing list