unit-tests: Add ability to issue a warning message for a test case

This way we can warn if we e.g. skipped actually doing something due to
dependencies (otherwise the test case would just appear to have succeeded).
This commit is contained in:
Tobias Brunner 2017-09-26 14:55:14 +02:00
parent 90a3bc5075
commit 4c5dd39aa3
3 changed files with 116 additions and 6 deletions

View File

@ -385,10 +385,29 @@ static void collect_failure_info(array_t *failures, char *name, int i)
array_insert(failures, -1, &failure);
}
/**
* Collect warning information, add failure_t to array
*/
static bool collect_warning_info(array_t *warnings, char *name, int i)
{
failure_t warning = {
.name = name,
.i = i,
};
warning.line = test_warning_get(warning.msg, sizeof(warning.msg),
&warning.file);
if (warning.line)
{
array_insert(warnings, -1, &warning);
}
return warning.line;
}
/**
* Print array of collected failure_t to stderr
*/
static void print_failures(array_t *failures)
static void print_failures(array_t *failures, bool warnings)
{
failure_t failure;
@ -397,8 +416,16 @@ static void print_failures(array_t *failures)
while (array_remove(failures, 0, &failure))
{
fprintf(stderr, " %sFailure in '%s': %s (",
TTY(RED), failure.name, failure.msg);
if (warnings)
{
fprintf(stderr, " %sWarning in '%s': %s (",
TTY(YELLOW), failure.name, failure.msg);
}
else
{
fprintf(stderr, " %sFailure in '%s': %s (",
TTY(RED), failure.name, failure.msg);
}
if (failure.line)
{
fprintf(stderr, "%s:%d, ", failure.file, failure.line);
@ -423,9 +450,10 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init, char *cfg)
enumerator_t *enumerator;
test_function_t *tfun;
int passed = 0;
array_t *failures;
array_t *failures, *warnings;
failures = array_create(sizeof(failure_t), 0);
warnings = array_create(sizeof(failure_t), 0);
fprintf(stderr, " Running case '%s': ", tcase->name);
fflush(stderr);
@ -470,7 +498,14 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init, char *cfg)
if (!leaks)
{
rounds++;
fprintf(stderr, "%s+%s", TTY(GREEN), TTY(DEF));
if (!collect_warning_info(warnings, tfun->name, i))
{
fprintf(stderr, "%s+%s", TTY(GREEN), TTY(DEF));
}
else
{
fprintf(stderr, "%s~%s", TTY(YELLOW), TTY(DEF));
}
}
}
else
@ -497,8 +532,10 @@ static bool run_case(test_case_t *tcase, test_runner_init_t init, char *cfg)
fprintf(stderr, "\n");
print_failures(failures);
print_failures(warnings, TRUE);
print_failures(failures, FALSE);
array_destroy(failures);
array_destroy(warnings);
return passed == array_count(tcase->functions);
}

View File

@ -49,6 +49,21 @@ static backtrace_t *failure_backtrace;
*/
static bool worker_failed;
/**
* Warning message buf
*/
static char warning_buf[4096];
/**
* Source file warning was issued
*/
static const char *warning_file;
/**
* Line of source file warning was issued
*/
static int warning_line;
/**
* See header.
*/
@ -419,6 +434,21 @@ void test_fail_vmsg(const char *file, int line, char *fmt, va_list args)
test_failure();
}
/**
* See header.
*/
void test_warn_msg(const char *file, int line, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsnprintf(warning_buf, sizeof(warning_buf), fmt, args);
warning_line = line;
warning_file = file;
va_end(args);
}
/**
* See header.
*/
@ -446,6 +476,25 @@ int test_failure_get(char *msg, int len, const char **file)
return failure_line;
}
/**
* See header.
*/
int test_warning_get(char *msg, int len, const char **file)
{
int line = warning_line;
if (!line)
{
return 0;
}
strncpy(msg, warning_buf, len - 1);
msg[len - 1] = 0;
*file = warning_file;
/* reset state */
warning_line = 0;
return line;
}
/**
* See header.
*/

View File

@ -219,6 +219,17 @@ void test_setup_timeout(int s);
*/
int test_failure_get(char *msg, int len, const char **file);
/**
* Get info about a warning if one was issued during the test. Resets the
* warning state.
*
* @param msg buffer receiving warning
* @param len size of msg buffer
* @param file pointer receiving source code file
* @return source code line number, 0 if no warning issued
*/
int test_warning_get(char *msg, int len, const char **file);
/**
* Get a backtrace for a failure.
*
@ -246,6 +257,18 @@ void test_fail_vmsg(const char *file, int line, char *fmt, va_list args);
*/
void test_fail_msg(const char *file, int line, char *fmt, ...);
/**
* Issue a warning for a particular test with a message using printf style
* arguments. This does not fail the test, and only the last warning for each
* test is kept.
*
* @param file source code file name
* @param line source code line number
* @param fmt printf format string
* @param ... arguments for fmt
*/
void test_warn_msg(const char *file, int line, char *fmt, ...);
/**
* Let a test fail if one of the worker threads has failed (only if called from
* the main thread).
@ -345,6 +368,7 @@ void test_fail_if_worker_failed();
#define ck_assert_msg test_assert_msg
#define ck_assert_str_eq test_str_eq
#define ck_assert_chunk_eq test_chunk_eq
#define warn(fmt, ...) test_warn_msg(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define fail(fmt, ...) test_fail_msg(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define fail_if(x, fmt, ...) \
({ \