test-common.c revision f8a9af77130785a9d75b133862aa5c341a0b95e6
/* Copyright (c) 2007-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream-private.h"
#include "test-common.h"
#include <stdio.h>
#include <unistd.h> /* _exit() */
#include <setjmp.h> /* for fatal tests */
/* 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;
struct test_istream {
struct istream_private istream;
const void *orig_buffer;
unsigned int skip_diff;
bool allow_eof;
};
{
unsigned int new_skip_diff;
return -2;
}
/* we seeked past the end of file. */
ret = 0;
} else {
/* copy data to a buffer in somewhat random place. this could
help catch bugs. */
/* use exactly correct buffer size so valgrind can catch
read overflows */
cur_max);
}
if (size > 0)
}
if (ret > 0)
return ret;
return 0;
else {
return -1;
}
}
bool mark ATTR_UNUSED)
{
}
{
struct test_istream *tstream;
}
{
}
{
}
}
{
}
{
}
{
}
void test_begin(const char *name)
{
test_success = TRUE;
if (!expecting_fatal)
else
}
bool test_has_failed(void)
{
return !test_success;
}
{
}
{
}
{
}
static void
test_dump_rand_state(void)
{
static int seen_count = -1;
int count = rand_get_seed_count();
if (count == seen_count)
return;
seen_count = count;
if (count > 0)
printf("test: random seed #%i was %u\n",
else
printf("test: random seed unknown\n");
}
void test_end(void)
{
if (!expecting_fatal)
else
if (!test_success)
}
{
}
{
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 void ATTR_FORMAT(2, 0)
{
if (expected_errors > 0) {
/* test_assert() will reset test_success if need be. */
} T_END;
} else {
}
if (!suppress) {
}
}
{
/* Prevent recursion, we can't handle our own errors */
/* we simply can't get here - will the compiler complain? */
}
static void test_init(void)
{
test_prefix = NULL;
failure_count = 0;
total_count = 0;
lib_init();
/* Don't set fatal handler until actually needed for fatal testing */
}
static int test_deinit(void)
{
lib_deinit();
return failure_count == 0 ? 0 : 1;
}
static void test_run_funcs(void (*test_functions[])(void))
{
unsigned int i;
for (i = 0; test_functions[i] != NULL; i++) {
T_BEGIN {
test_functions[i]();
} T_END;
}
}
{
unsigned int i;
} T_END;
}
}
{
static 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 (*test_functions[])(void))
{
test_init();
return test_deinit();
}
{
test_init();
return test_deinit();
}
int test_run_with_fatals(void (*test_functions[])(void),
enum fatal_test_state (*fatal_functions[])(int))
{
test_init();
return test_deinit();
}
struct named_fatal fatals[])
{
test_init();
return test_deinit();
}
void ATTR_NORETURN
{
#ifndef STATIC_CHECKER
data_stack_frame_t id = 0;
#endif
lib_deinit();
}