2015-03-03 12:51:35 +00:00
|
|
|
/*
|
2015-03-19 17:38:38 +00:00
|
|
|
* BIRD -- Unit Test Framework (BIRD Test)
|
2015-03-03 12:51:35 +00:00
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
2015-03-17 10:27:40 +00:00
|
|
|
#ifndef _BIRDTEST_H_
|
|
|
|
#define _BIRDTEST_H_
|
|
|
|
|
2015-03-03 12:51:35 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
extern int bt_success;
|
2015-04-15 09:51:24 +00:00
|
|
|
extern int bt_test_suite_success;
|
2015-04-13 08:52:21 +00:00
|
|
|
|
2015-03-03 12:51:35 +00:00
|
|
|
extern int bt_verbose;
|
2015-04-13 08:52:21 +00:00
|
|
|
#define BT_VERBOSE_NOTHING 0
|
|
|
|
#define BT_VERBOSE_TEST_CASE 1
|
|
|
|
#define BT_VERBOSE_DEBUG 2
|
|
|
|
|
2015-03-03 12:51:35 +00:00
|
|
|
extern const char *bt_filename;
|
|
|
|
extern const char *bt_test_id;
|
|
|
|
|
2015-03-17 10:27:40 +00:00
|
|
|
void bt_init(int argc, char *argv[]);
|
2015-04-13 08:52:21 +00:00
|
|
|
int bt_end(void);
|
2015-04-13 08:42:10 +00:00
|
|
|
void bt_test_suite5(int (*fn)(void), const char *id, const char *dsc, int forked, int timeout);
|
2015-03-27 13:03:47 +00:00
|
|
|
int bt_rand_num(void);
|
2015-04-13 08:52:21 +00:00
|
|
|
void bt_result(const char *result, const char *msg, ...);
|
|
|
|
|
|
|
|
#define BT_SUCCESS 1
|
|
|
|
#define BT_FAILURE 0
|
2015-03-03 12:51:35 +00:00
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
#define BT_DEFAULT_TIMEOUT 5
|
|
|
|
#define BT_DEFAULT_FORKING 1
|
2015-03-13 17:30:03 +00:00
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
#define BT_RANDOM_SEED 982451653
|
2015-03-17 10:27:40 +00:00
|
|
|
|
2015-04-25 08:49:43 +00:00
|
|
|
#define BT_BUFFER_SIZE 10000
|
2015-03-27 13:03:47 +00:00
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
#define BT_PROMPT_GREEN "\e[1;32m"
|
|
|
|
#define BT_PROMPT_RED "\e[1;31m"
|
|
|
|
#define BT_PROMPT_NORMAL "\e[0m"
|
|
|
|
#define BT_PROMPT_OK " [" BT_PROMPT_GREEN " OK " BT_PROMPT_NORMAL "] "
|
|
|
|
#define BT_PROMPT_FAIL " [" BT_PROMPT_RED "FAIL" BT_PROMPT_NORMAL "] "
|
|
|
|
#define BT_PROMPT_OK_FAIL_LEN 8
|
|
|
|
#define BT_PROMPT_FN_GIVES(in_fmt) "%s(" in_fmt ") gives "
|
|
|
|
#define BT_PROMPT_EXPECTING ", but expecting is "
|
2015-03-17 10:27:40 +00:00
|
|
|
|
2015-04-13 08:42:10 +00:00
|
|
|
#define bt_test_suite(fn,dsc) \
|
|
|
|
bt_test_suite4(fn, dsc, BT_DEFAULT_FORKING, BT_DEFAULT_TIMEOUT)
|
|
|
|
|
|
|
|
#define bt_test_suite4(fn,dsc,f,t) \
|
|
|
|
bt_test_suite5(fn, #fn, dsc, f, t)
|
2015-03-03 12:51:35 +00:00
|
|
|
|
|
|
|
#define bt_log(format, ...) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do { \
|
|
|
|
if (bt_test_id == NULL) \
|
|
|
|
fprintf(stderr, "%s: " format "\n", bt_filename, ##__VA_ARGS__); \
|
|
|
|
else \
|
|
|
|
fprintf(stderr, "%s: %s: " format "\n", bt_filename, bt_test_id, ##__VA_ARGS__); \
|
|
|
|
} while(0)
|
2015-03-03 12:51:35 +00:00
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
#define bt_log_test_case(format, ...) \
|
|
|
|
do { if (bt_verbose >= BT_VERBOSE_TEST_CASE) bt_log(format, ##__VA_ARGS__); } while (0)
|
2015-03-03 12:51:35 +00:00
|
|
|
|
2015-03-13 17:27:33 +00:00
|
|
|
#define bt_debug(format, ...) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do { if (bt_verbose >= BT_VERBOSE_DEBUG) printf(format, ##__VA_ARGS__); } while (0)
|
|
|
|
|
|
|
|
#define bt_result_(result, format, ...) bt_result(result, "%s: " format, bt_test_id, ##__VA_ARGS__)
|
|
|
|
#define bt_result_ok(format, ...) bt_result_(BT_PROMPT_OK, format, ##__VA_ARGS__)
|
|
|
|
#define bt_result_fail(format, ...) bt_result_(BT_PROMPT_FAIL, format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define bt_result_check(result, format, ...) \
|
|
|
|
do { if (bt_verbose >= BT_VERBOSE_TEST_CASE) bt_result_(result, format, ##__VA_ARGS__); } while (0)
|
|
|
|
|
|
|
|
#define bt_result_check_ok(format, ...) \
|
|
|
|
do { if (bt_verbose >= BT_VERBOSE_TEST_CASE) bt_result_ok(format, ##__VA_ARGS__); } while (0)
|
|
|
|
|
|
|
|
#define bt_result_check_fail(format, ...) \
|
|
|
|
do { if (bt_verbose >= BT_VERBOSE_TEST_CASE) bt_result_fail(format, ##__VA_ARGS__); } while (0)
|
2015-03-13 17:27:33 +00:00
|
|
|
|
2015-03-03 12:51:35 +00:00
|
|
|
#define bt_abort() \
|
|
|
|
bt_abort_msg("Aborted at %s:%d", __FILE__, __LINE__)
|
|
|
|
|
|
|
|
#define bt_abort_msg(format, ...) \
|
|
|
|
do { bt_log(format, ##__VA_ARGS__); abort(); } while (0)
|
|
|
|
|
|
|
|
#define bt_assert(test) \
|
|
|
|
bt_assert_msg(test, "Assertion (%s) failed at %s:%d", #test, __FILE__, __LINE__)
|
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
#define bt_equal(a, b) \
|
|
|
|
bt_assert_msg((a) == (b), "Assertion (%s == %s) failed at %s:%d.", #a, #b, __FILE__, __LINE__)
|
|
|
|
|
|
|
|
#define bt_assert_msg(test, format, ...) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
if (!(test)) \
|
|
|
|
{ \
|
|
|
|
if (bt_verbose) \
|
|
|
|
bt_log(format, ##__VA_ARGS__); \
|
|
|
|
bt_success = bt_test_suite_success = 0; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2015-03-03 12:51:35 +00:00
|
|
|
|
2015-04-13 08:52:21 +00:00
|
|
|
#define bt_syscall(test,format, ...) \
|
2015-03-03 12:51:35 +00:00
|
|
|
do { if (test) { bt_log(format ": %s", ##__VA_ARGS__, strerror(errno)); exit(3); } } while (0)
|
2015-03-17 10:27:40 +00:00
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
|
|
|
|
#define bt_strncat(buf, str, ...) \
|
|
|
|
snprintf(buf + strlen(buf), sizeof(buf), str, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
void bt_strncat_(char *buf, size_t buf_size, const char *str, ...);
|
|
|
|
|
|
|
|
#define bt_dump_struct(buf, data) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do \
|
|
|
|
{ \
|
2015-04-15 13:42:43 +00:00
|
|
|
unsigned int k; \
|
2015-04-15 09:51:24 +00:00
|
|
|
u32 *pc = (u32*) data; \
|
|
|
|
bt_strncat(buf, "{"); \
|
2015-04-15 13:42:43 +00:00
|
|
|
for (k = 0; k < (sizeof(*data) / sizeof(typeof(*pc))); k++) \
|
|
|
|
bt_strncat(buf, "%s0x%08X", (k ? ", " : ""), pc[k]); \
|
2015-04-15 09:51:24 +00:00
|
|
|
bt_strncat(buf, "}"); \
|
2015-04-13 08:52:21 +00:00
|
|
|
} while (0)
|
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
#define bt_dump(buf, data, fmt) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do \
|
|
|
|
{ \
|
2015-04-15 09:51:24 +00:00
|
|
|
if (fmt == NULL) \
|
|
|
|
bt_dump_struct(buf, &data); \
|
|
|
|
else \
|
|
|
|
bt_strncat_(buf, sizeof(buf), fmt, data); \
|
2015-04-13 08:52:21 +00:00
|
|
|
} while (0)
|
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
#define bt_print_result_line(fn, in, out, fn_out, in_fmt, out_fmt, result) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
char buf[BT_BUFFER_SIZE]; \
|
|
|
|
strcpy(buf, ""); \
|
|
|
|
snprintf(buf, sizeof(buf), "%s(", #fn); \
|
|
|
|
bt_dump(buf, in, in_fmt); \
|
|
|
|
bt_strncat(buf, ") gives "); \
|
|
|
|
bt_dump(buf, fn_out, out_fmt); \
|
|
|
|
if (!result) \
|
|
|
|
{ \
|
|
|
|
bt_strncat(buf, BT_PROMPT_EXPECTING); \
|
|
|
|
bt_dump(buf, out, out_fmt); \
|
|
|
|
} \
|
|
|
|
bt_result_check((single_test_case_success ? BT_PROMPT_OK : BT_PROMPT_FAIL), "%s", buf); \
|
|
|
|
} while (0)
|
2015-04-13 08:52:21 +00:00
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
/**
|
|
|
|
* Usage:
|
|
|
|
* u32 my_function(const char *input_data) { ... }
|
|
|
|
*
|
|
|
|
* struct in_out {
|
|
|
|
* char *in;
|
|
|
|
* u32 out;
|
|
|
|
* } in_out[] = { ... };
|
|
|
|
*
|
|
|
|
* bt_assert_out_fn_in(my_function, in_out, "%s", "%u");
|
|
|
|
*/
|
|
|
|
#define bt_assert_out_fn_in(fn, in_out, in_fmt, out_fmt) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do \
|
|
|
|
{ \
|
2015-04-15 09:51:24 +00:00
|
|
|
unsigned int i; \
|
|
|
|
for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++) \
|
|
|
|
{ \
|
|
|
|
typeof(in_out[i].out) fn_out = fn(in_out[i].in); \
|
|
|
|
int single_test_case_success = (fn(in_out[i].in) == in_out[i].out); \
|
|
|
|
bt_test_suite_success &= single_test_case_success; \
|
|
|
|
bt_print_result_line(fn, in_out[i].in, in_out[i].out, fn_out, in_fmt, out_fmt, single_test_case_success); \
|
|
|
|
} \
|
2015-04-13 08:52:21 +00:00
|
|
|
} while (0)
|
|
|
|
|
2015-04-15 09:51:24 +00:00
|
|
|
/**
|
|
|
|
* Usage:
|
|
|
|
* void my_function(const char *input_data, u32 *output_data) { ... }
|
|
|
|
*
|
|
|
|
* struct in_out {
|
|
|
|
* char *in;
|
|
|
|
* u32 out;
|
|
|
|
* } in_out[] = { ... };
|
|
|
|
*
|
|
|
|
* bt_assert_fn_in_out(my_function, in_out, "%s", "%u");
|
|
|
|
*/
|
|
|
|
#define bt_assert_fn_in_out(fn, in_out, in_fmt, out_fmt) \
|
2015-04-13 08:52:21 +00:00
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
unsigned int i; \
|
|
|
|
for (i = 0; i < (sizeof(in_out)/sizeof(in_out[0])); i++) \
|
|
|
|
{ \
|
2015-04-15 09:51:24 +00:00
|
|
|
typeof(in_out[i].out) fn_out; \
|
|
|
|
memset(&fn_out, '\0', sizeof(fn_out)); \
|
|
|
|
fn(in_out[i].in, &fn_out); \
|
|
|
|
int single_test_case_success = !memcmp(&fn_out, &in_out[i].out, sizeof(in_out[i].out)); \
|
|
|
|
bt_test_suite_success &= single_test_case_success; \
|
|
|
|
\
|
|
|
|
bt_print_result_line(fn, in_out[i].in, in_out[i].out, fn_out, in_fmt, out_fmt, single_test_case_success); \
|
2015-04-13 08:52:21 +00:00
|
|
|
} \
|
|
|
|
} while (0)
|
2015-03-27 13:04:37 +00:00
|
|
|
|
2015-03-17 10:27:40 +00:00
|
|
|
#endif /* _BIRDTEST_H_ */
|