test-common.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "test-common.h"
#include <stdio.h>
#include <unistd.h> /* _exit() */
#include <setjmp.h> /* for fatal tests */
static bool test_deinit_lib;
/* To test the firing of i_assert, we need non-local jumps, i.e. setjmp */
static volatile bool expecting_fatal = FALSE;
static jmp_buf fatal_jmpbuf;
#define OUT_NAME_ALIGN 70
static char *test_prefix;
static bool test_success;
static unsigned int failure_count;
static unsigned int total_count;
static unsigned int expected_errors;
static char *expected_error_str, *expected_fatal_str;
void test_begin(const char *name)
{
test_success = TRUE;
expected_errors = 0;
if (!expecting_fatal)
else
}
bool test_has_failed(void)
{
return !test_success;
}
{
}
{
}
{
}
void test_end(void)
{
if (!expecting_fatal)
else
}
{
}
{
if (success) {
total_count++;
return;
}
}
{
int i = 0;
if (test_prefix != NULL) {
i += strlen(test_prefix);
if (*name != '\0') {
putchar(':');
i++;
}
putchar(' ');
i++;
}
if (*name != '\0') {
putchar(' ');
}
for (; i < OUT_NAME_ALIGN; i++)
putchar('.');
if (success)
else {
}
putchar('\n');
total_count++;
}
void
test_expect_error_string(const char *substr)
{
i_assert(expected_errors == 0);
expected_errors = 1;
}
void
test_expect_errors(unsigned int expected)
{
i_assert(expected_errors == 0);
}
void
{
expected_errors = 0;
}
static bool ATTR_FORMAT(2, 0)
{
if (*error_strp == NULL)
return TRUE;
bool suppress;
T_BEGIN {
/* test_assert() will reset test_success if need be. */
} T_END;
return suppress;
}
static void ATTR_FORMAT(2, 0)
{
if (expected_errors > 0) {
} else {
}
if (!suppress) {
}
}
void test_expect_fatal_string(const char *substr)
{
}
{
/* Prevent recursion, we can't handle our own errors */
if (suppress) {
} else {
}
i_unreached(); /* we simply can't get here */
}
static void test_init(void)
{
test_prefix = NULL;
failure_count = 0;
total_count = 0;
if (!lib_is_initialized()) {
lib_init();
} else
/* Don't set fatal handler until actually needed for fatal testing */
}
static int test_deinit(void)
{
if (test_deinit_lib)
lib_deinit();
return failure_count == 0 ? 0 : 1;
}
static void test_run_funcs(void (*const test_functions[])(void))
{
unsigned int i;
for (i = 0; test_functions[i] != NULL; i++) {
T_BEGIN {
test_functions[i]();
} T_END;
}
}
const char *match)
{
unsigned int i;
} T_END;
}
}
{
static unsigned int index = 0;
for (;;) {
if (jumped == 0) {
/* normal flow */
if (ret == FATAL_TEST_FINISHED) {
/* ran out of tests - good */
index = 0;
break;
} else if (ret == FATAL_TEST_FAILURE) {
/* failed to fire assert - bad, but can continue */
index++;
} else { /* FATAL_TEST_ABORT or other value */
test_end();
index = 0;
break;
}
} else {
/* assert fired, continue with next test */
index++;
}
}
}
{
unsigned int i;
for (i = 0; fatal_functions[i] != NULL; i++) {
T_BEGIN {
} T_END;
}
}
{
unsigned int i;
} T_END;
}
}
int test_run(void (*const test_functions[])(void))
{
test_init();
return test_deinit();
}
{
test_init();
return test_deinit();
}
int test_run_with_fatals(void (*const test_functions[])(void),
test_fatal_func_t *const fatal_functions[])
{
test_init();
return test_deinit();
}
const struct named_fatal fatals[])
{
test_init();
return test_deinit();
}
void ATTR_NORETURN
{
t_pop_last_unsafe(); /* as we were within a T_BEGIN { tests[i].func(); } T_END */
lib_deinit();
}