# HG changeset patch # User Tero Marttila # Date 1241736182 -10800 # Node ID 808b1b0476207b9dda0ed0bc1f6cdaece884113c # Parent 9f8c6eaf9d5032f63221d1a8d2f1401e3f35ad0d add a new test/fail module, and rewrite test/assert to use it diff -r 9f8c6eaf9d50 -r 808b1b047620 src/log.c --- a/src/log.c Fri May 08 01:42:44 2009 +0300 +++ b/src/log.c Fri May 08 01:43:02 2009 +0300 @@ -72,11 +72,7 @@ _log_output_ctx.arg = arg; } -/** - * Format the full output line, and pass it to the log_output_func. The line will be of the form: - * "[] : [ ]" - */ -static void log_output (enum log_level level, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...) +void log_output_tag (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...) { char buf[LOG_MSG_MAX], *buf_ptr = buf; size_t buf_size = sizeof(buf); @@ -86,7 +82,7 @@ return; // output the header - buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, buf_size, "[%5s] %20s : ", log_level_name(level), func)); + buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, buf_size, "[%5s] %20s : ", tag, func)); // output the user data buf_ptr += str_advance(NULL, &buf_size, str_append_fmt_va(buf_ptr, buf_size, user_fmt, user_fmtargs)); @@ -110,7 +106,7 @@ // formatted output: no suffix va_start(vargs, format); - log_output(level, func, format, vargs, NULL); + log_output_tag(level, log_level_name(level), func, format, vargs, NULL); va_end(vargs); } @@ -120,7 +116,7 @@ // formatted output: suffix error_name() va_start(vargs, format); - log_output(level, func, format, vargs, ": %s", error_name(err)); + log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_name(err)); va_end(vargs); } @@ -130,7 +126,7 @@ // formatted output: suffix error_msg() va_start(vargs, format); - log_output(level, func, format, vargs, ": %s", error_msg(err)); + log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_msg(err)); va_end(vargs); } @@ -140,7 +136,7 @@ // formatted output: suffix strerror() va_start(vargs, format); - log_output(level, func, format, vargs, ": %s", strerror(errno)); + log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", strerror(errno)); va_end(vargs); } diff -r 9f8c6eaf9d50 -r 808b1b047620 src/log.h --- a/src/log.h Fri May 08 01:42:44 2009 +0300 +++ b/src/log.h Fri May 08 01:43:02 2009 +0300 @@ -6,6 +6,7 @@ * Local logging functions */ #include "error.h" +#include /** * Log level definitions @@ -53,6 +54,15 @@ void log_set_func (log_output_func func, void *arg); /** + * Internal logging func, meant for using custom level tags. This performs the filtering of log levels. + * + * Format the full output line, and pass it to the log_output_func. The line will be of the form: + * "[] : [ ]" + */ +void log_output_tag (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...) + __attribute__ ((format (printf, 6, 7))); + +/** * Log a message with the given level */ void log_msg (enum log_level level, const char *func, const char *format, ...) diff -r 9f8c6eaf9d50 -r 808b1b047620 src/test/assert.c --- a/src/test/assert.c Fri May 08 01:42:44 2009 +0300 +++ b/src/test/assert.c Fri May 08 01:43:02 2009 +0300 @@ -1,70 +1,62 @@ #include "assert.h" #include "util.h" -#include "backtrace.h" #include -#define ASSERT_FAIL(...) do { log_fatal(__VA_ARGS__); test_backtrace(1); abort(); } while (0) -void assert_true (bool cond, const char *msg) +#define _ASSERT_FUNC_FAIL(...) test_fail(func, file, line, 1, __VA_ARGS__) + +void _assert_null (_ASSERT_FUNC_ARGS, const void *ptr) { - if (!cond) - ASSERT_FAIL("%s", msg); + if (ptr) + _ASSERT_FUNC_FAIL("%p != NULL", ptr); } -void assert_null (const void *ptr) -{ - if (ptr) - ASSERT_FAIL("%p != NULL", ptr); -} - -void assert_strcmp (const char *is, const char *should_be) +void _assert_strcmp (_ASSERT_FUNC_ARGS, const char *is, const char *should_be) { if (!should_be && !is) return; - + if (!is || strcmp(is, should_be)) - ASSERT_FAIL("%s != %s", dump_str(is), dump_str(should_be)); -} - -void assert_strncmp (const char *is, const char *should_be, size_t n) -{ - if (!should_be && !is) - return; - - if (!is || strncmp(is, should_be, n)) - ASSERT_FAIL("%s:%u != %s", dump_strn(is, n), (unsigned) n, dump_strn(should_be, n)); -} - -void assert_strlen (const char *str, size_t n) -{ - if (!str || strlen(str) != n) - ASSERT_FAIL("strlen(%s) != %u", dump_str(str), (unsigned) n); + _ASSERT_FUNC_FAIL("%s != %s", dump_str(is), dump_str(should_be)); } -void assert_strnull (const char *str) +void _assert_strncmp (_ASSERT_FUNC_ARGS, const char *is, const char *should_be, size_t n) { - if (str != NULL) - ASSERT_FAIL("%s != NULL", dump_str(str)); -} - -void assert_success (err_t err) -{ - if (err != SUCCESS) - ASSERT_FAIL("error: %s", error_name(err)); + if (!should_be && !is) + return; + + if (!is || strncmp(is, should_be, n)) + _ASSERT_FUNC_FAIL("%s:%u != %s", dump_strn(is, n), (unsigned) n, dump_strn(should_be, n)); } -void assert_err (err_t err, err_t target) +void _assert_strlen (_ASSERT_FUNC_ARGS, const char *str, size_t n) { - if (err != target) - ASSERT_FAIL("error: <%s> != <%s>", error_name(err), error_name(target)); + if (!str || strlen(str) != n) + _ASSERT_FUNC_FAIL("strlen(%s) != %u", dump_str(str), (unsigned) n); } -void assert_error (error_t *is, error_t *should_be) +void _assert_strnull (_ASSERT_FUNC_ARGS, const char *str) +{ + if (str) + _ASSERT_FUNC_FAIL("%s != NULL", dump_str(str)); +} + +void _assert_success (_ASSERT_FUNC_ARGS, err_t err) +{ + if (err) + _ASSERT_FUNC_FAIL("err: %s", dump_str(error_name(err))); +} + +void _assert_err (_ASSERT_FUNC_ARGS, err_t is, err_t should_be) +{ + if (is != should_be) + _ASSERT_FUNC_FAIL("err: %s != %s", dump_str(error_name(is)), dump_str(error_name(should_be))); +} + +void _assert_error (_ASSERT_FUNC_ARGS, error_t *is, error_t *should_be) { if (ERROR_CODE(is) != ERROR_CODE(should_be) || ERROR_EXTRA(is) != ERROR_EXTRA(should_be)) - // XXX: dual use of error_msg - ASSERT_FAIL("error: <%s> != <%s>", error_msg(is), error_msg(should_be)); + _ASSERT_FUNC_FAIL("error: %s != %s", dump_str(error_msg(is)), dump_str(error_msg(should_be))); + } - - diff -r 9f8c6eaf9d50 -r 808b1b047620 src/test/assert.h --- a/src/test/assert.h Fri May 08 01:42:44 2009 +0300 +++ b/src/test/assert.h Fri May 08 01:43:02 2009 +0300 @@ -6,58 +6,76 @@ * * Various general assert-condition tests used to fail tests */ +#include "fail.h" #include "../error.h" -#include "../log.h" /* * Also accept the existance of the system assert() function */ #include -#include + +/* + * Internal shorthand macros for passing func/file/line args + */ +#define _ASSERT_FUNC_ARGS const char *func, const char *file, int line +#define _ASSERT_FUNC_CALL(func, ...) func(__func__, __FILE__, __LINE__, __VA_ARGS__) /** * Assert that the given condition is true, and fail with the given error if not */ -void assert_true (bool cond, const char *msg); +#define assert_true(cond, ...) fail_if(cond, __VA_ARGS__) + +/** + * Assert failure unconditionally + */ +#define assert_fail(...) fail(__VA_ARGS__) /** * Assert that the given pointer value is NULL. */ -void assert_null (const void *ptr); +#define assert_null(ptr) _ASSERT_FUNC_CALL(_assert_null, ptr) +void _assert_null (_ASSERT_FUNC_ARGS, const void *ptr); /** * Assert that the given NUL-terminated string matches the given target string exactly. */ -void assert_strcmp (const char *is, const char *should_be); +#define assert_strcmp(is, should_be) _ASSERT_FUNC_CALL(_assert_strcmp, is, should_be) +void _assert_strcmp (_ASSERT_FUNC_ARGS, const char *is, const char *should_be); /** * Assert that the first \a n chars of the first string matches the second string exactly. */ -void assert_strncmp (const char *is, const char *should_be, size_t n); +#define assert_strncmp(is, should_be, n) _ASSERT_FUNC_CALL(_assert_strncmp, is, should_be, n) +void _assert_strncmp (_ASSERT_FUNC_ARGS, const char *is, const char *should_be, size_t n); /** * Assert that the given \a str is \a n chars long. */ -void assert_strlen (const char *str, size_t n); +#define assert_strlen(str, n) _ASSERT_FUNC_CALL(_assert_strlen, str, n) +void _assert_strlen (_ASSERT_FUNC_ARGS, const char *str, size_t n); /** * Assert that the given \a str is NULL. */ -void assert_strnull (const char *str); +#define assert_strnull(str) _ASSERT_FUNC_CALL(_assert_strnull, str) +void _assert_strnull (_ASSERT_FUNC_ARGS, const char *str); /** * Assert that the given error code is SUCCESS. */ -void assert_success (err_t err); +#define assert_success(err) _ASSERT_FUNC_CALL(_assert_success, err) +void _assert_success (_ASSERT_FUNC_ARGS, err_t err); /** - * Assert that the given actual error code \a err matches the expected error code \target. + * Assert that the given actual error code \a err matches the expected error code \a should_be. */ -void assert_err (err_t err, err_t target); +#define assert_err(is, should_be) _ASSERT_FUNC_CALL(_assert_err, is, should_be) +void _assert_err (_ASSERT_FUNC_ARGS, err_t is, err_t should_be); /** * Assert that the given actual error \a is matches the expected error \a should_be */ -void assert_error (error_t *is, error_t *should_be); +#define assert_error(is, should_be) _ASSERT_FUNC_CALL(_assert_error, is, should_be) +void _assert_error (_ASSERT_FUNC_ARGS, error_t *is, error_t *should_be); #endif diff -r 9f8c6eaf9d50 -r 808b1b047620 src/test/fail.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/fail.c Fri May 08 01:43:02 2009 +0300 @@ -0,0 +1,30 @@ +#include "fail.h" +#include "../str.h" +#include "../log.h" +#include "backtrace.h" + +#include + +void test_fail_va (const char *func, const char *file, int line, int skip, const char *fmt, va_list vargs) +{ + // log it + log_output_tag(LOG_ERROR, "FAIL", func, fmt, vargs, " @@ %s@%s:%d - backtrace follows:", func, file, line); + + // print out a stack dump, not including this function or the backtrace func + test_backtrace(skip + 2); + + // then exit with a failure code + abort(); +} + +void test_fail (const char *func, const char *file, int line, int skip, const char *fmt, ...) +{ + va_list vargs; + + va_start(vargs, fmt); + + test_fail_va(func, file, line, skip, fmt, vargs); + + va_end(vargs); +} + diff -r 9f8c6eaf9d50 -r 808b1b047620 src/test/fail.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/fail.h Fri May 08 01:43:02 2009 +0300 @@ -0,0 +1,50 @@ +#ifndef TEST_FAIL_H +#define TEST_FAIL_H + +/** + * @file + * + * Various ways to mark the current test as failed. + */ +#include "../error.h" +#include + +#define NORETURN __attribute((noreturn)) + +/** + * Output a message representing the given failure using log_output. + * + * Also dumps out a stacktrace for the calling function using log_debug, skipping this func, the backtrace func, and + * the given number of frames. + */ +void test_fail_va (const char *func, const char *file, int line, int skip, const char *fmt, va_list vargs) NORETURN; + +/** + * Output given fail using test_fail_va(). + */ +void test_fail (const char *func, const char *file, int line, int skip, const char *fmt, ...) NORETURN; + +/** + * Fail with a simply error message + */ +#define fail(...) test_fail(__func__, __FILE__, __LINE__, 0, __VA_ARGS__) + +/** + * Fail conditionally + */ +#define fail_if(cond, ...) do { \ + if (cond) \ + fail(__VA_ARGS__); \ + } while (0) + +/** + * Fail with an error code + */ +#define fail_err(err, fmt, ...) fail(fmt ": %s", __VA_ARGS__, ## error_name(err)) + +/** + * Fail with an error info + */ +#define fail_error(error, fmt, ...) fail(fmt ": %s", __VA_ARGS__, ## error_msg(error)) + +#endif /* TEST_FAIL_H */ diff -r 9f8c6eaf9d50 -r 808b1b047620 src/test/test.h --- a/src/test/test.h Fri May 08 01:42:44 2009 +0300 +++ b/src/test/test.h Fri May 08 01:43:02 2009 +0300 @@ -9,8 +9,11 @@ #include "assert.h" #include "util.h" +#include "../log.h" + #include #include +#include /** * Global test-running state